AWSSDKPersistorManager.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /* eslint-disable
  2. handle-callback-err,
  3. no-return-assign,
  4. */
  5. // TODO: This file was created by bulk-decaffeinate.
  6. // Fix any style issues and re-enable lint.
  7. /*
  8. * decaffeinate suggestions:
  9. * DS102: Remove unnecessary code created because of implicit returns
  10. * DS207: Consider shorter variations of null checks
  11. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  12. */
  13. // This module is not used in production, which currently uses
  14. // S3PersistorManager. The intention is to migrate S3PersistorManager to use the
  15. // latest aws-sdk and delete this module so that PersistorManager would load the
  16. // same backend for both the 's3' and 'aws-sdk' options.
  17. const logger = require('logger-sharelatex')
  18. const aws = require('aws-sdk')
  19. const _ = require('underscore')
  20. const fs = require('fs')
  21. const Errors = require('./Errors')
  22. const s3 = new aws.S3()
  23. module.exports = {
  24. sendFile(bucketName, key, fsPath, callback) {
  25. logger.log({ bucketName, key }, 'send file data to s3')
  26. const stream = fs.createReadStream(fsPath)
  27. return s3.upload({ Bucket: bucketName, Key: key, Body: stream }, function(
  28. err,
  29. data
  30. ) {
  31. if (err != null) {
  32. logger.err(
  33. { err, Bucket: bucketName, Key: key },
  34. 'error sending file data to s3'
  35. )
  36. }
  37. return callback(err)
  38. })
  39. },
  40. sendStream(bucketName, key, stream, callback) {
  41. logger.log({ bucketName, key }, 'send file stream to s3')
  42. return s3.upload({ Bucket: bucketName, Key: key, Body: stream }, function(
  43. err,
  44. data
  45. ) {
  46. if (err != null) {
  47. logger.err(
  48. { err, Bucket: bucketName, Key: key },
  49. 'error sending file stream to s3'
  50. )
  51. }
  52. return callback(err)
  53. })
  54. },
  55. getFileStream(bucketName, key, opts, callback) {
  56. if (callback == null) {
  57. callback = function(err, res) {}
  58. }
  59. logger.log({ bucketName, key }, 'get file stream from s3')
  60. callback = _.once(callback)
  61. const params = {
  62. Bucket: bucketName,
  63. Key: key
  64. }
  65. if (opts.start != null && opts.end != null) {
  66. params.Range = `bytes=${opts.start}-${opts.end}`
  67. }
  68. const request = s3.getObject(params)
  69. const stream = request.createReadStream()
  70. stream.on('readable', () => callback(null, stream))
  71. return stream.on('error', function(err) {
  72. logger.err({ err, bucketName, key }, 'error getting file stream from s3')
  73. if (err.code === 'NoSuchKey') {
  74. return callback(
  75. new Errors.NotFoundError(`File not found in S3: ${bucketName}:${key}`)
  76. )
  77. }
  78. return callback(err)
  79. })
  80. },
  81. copyFile(bucketName, sourceKey, destKey, callback) {
  82. logger.log({ bucketName, sourceKey, destKey }, 'copying file in s3')
  83. const source = bucketName + '/' + sourceKey
  84. return s3.copyObject(
  85. { Bucket: bucketName, Key: destKey, CopySource: source },
  86. function(err) {
  87. if (err != null) {
  88. logger.err(
  89. { err, bucketName, sourceKey, destKey },
  90. 'something went wrong copying file in s3'
  91. )
  92. }
  93. return callback(err)
  94. }
  95. )
  96. },
  97. deleteFile(bucketName, key, callback) {
  98. logger.log({ bucketName, key }, 'delete file in s3')
  99. return s3.deleteObject({ Bucket: bucketName, Key: key }, function(err) {
  100. if (err != null) {
  101. logger.err(
  102. { err, bucketName, key },
  103. 'something went wrong deleting file in s3'
  104. )
  105. }
  106. return callback(err)
  107. })
  108. },
  109. deleteDirectory(bucketName, key, callback) {
  110. logger.log({ bucketName, key }, 'delete directory in s3')
  111. return s3.listObjects({ Bucket: bucketName, Prefix: key }, function(
  112. err,
  113. data
  114. ) {
  115. if (err != null) {
  116. logger.err(
  117. { err, bucketName, key },
  118. 'something went wrong listing prefix in s3'
  119. )
  120. return callback(err)
  121. }
  122. if (data.Contents.length === 0) {
  123. logger.log({ bucketName, key }, 'the directory is empty')
  124. return callback()
  125. }
  126. const keys = _.map(data.Contents, entry => ({
  127. Key: entry.Key
  128. }))
  129. return s3.deleteObjects(
  130. {
  131. Bucket: bucketName,
  132. Delete: {
  133. Objects: keys,
  134. Quiet: true
  135. }
  136. },
  137. function(err) {
  138. if (err != null) {
  139. logger.err(
  140. { err, bucketName, key: keys },
  141. 'something went wrong deleting directory in s3'
  142. )
  143. }
  144. return callback(err)
  145. }
  146. )
  147. })
  148. },
  149. checkIfFileExists(bucketName, key, callback) {
  150. logger.log({ bucketName, key }, 'check file existence in s3')
  151. return s3.headObject({ Bucket: bucketName, Key: key }, function(err, data) {
  152. if (err != null) {
  153. if (err.code === 'NotFound') {
  154. return callback(null, false)
  155. }
  156. logger.err(
  157. { err, bucketName, key },
  158. 'something went wrong checking head in s3'
  159. )
  160. return callback(err)
  161. }
  162. return callback(null, data.ETag != null)
  163. })
  164. },
  165. directorySize(bucketName, key, callback) {
  166. logger.log({ bucketName, key }, 'get project size in s3')
  167. return s3.listObjects({ Bucket: bucketName, Prefix: key }, function(
  168. err,
  169. data
  170. ) {
  171. if (err != null) {
  172. logger.err(
  173. { err, bucketName, key },
  174. 'something went wrong listing prefix in s3'
  175. )
  176. return callback(err)
  177. }
  178. if (data.Contents.length === 0) {
  179. logger.log({ bucketName, key }, 'the directory is empty')
  180. return callback()
  181. }
  182. let totalSize = 0
  183. _.each(data.Contents, entry => (totalSize += entry.Size))
  184. return callback(null, totalSize)
  185. })
  186. }
  187. }