ReferencesHandler.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /* eslint-disable
  2. handle-callback-err,
  3. max-len,
  4. no-unused-vars,
  5. */
  6. // TODO: This file was created by bulk-decaffeinate.
  7. // Fix any style issues and re-enable lint.
  8. /*
  9. * decaffeinate suggestions:
  10. * DS102: Remove unnecessary code created because of implicit returns
  11. * DS103: Rewrite code to no longer use __guard__
  12. * DS207: Consider shorter variations of null checks
  13. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  14. */
  15. let ReferencesHandler
  16. const logger = require('logger-sharelatex')
  17. const request = require('request')
  18. const settings = require('settings-sharelatex')
  19. const Features = require('../../infrastructure/Features')
  20. const ProjectGetter = require('../Project/ProjectGetter')
  21. const UserGetter = require('../User/UserGetter')
  22. const DocumentUpdaterHandler = require('../DocumentUpdater/DocumentUpdaterHandler')
  23. const _ = require('underscore')
  24. const Async = require('async')
  25. const oneMinInMs = 60 * 1000
  26. const fiveMinsInMs = oneMinInMs * 5
  27. if (!Features.hasFeature('references')) {
  28. logger.log('references search not enabled')
  29. }
  30. module.exports = ReferencesHandler = {
  31. _buildDocUrl(projectId, docId) {
  32. return `${settings.apis.docstore.url}/project/${projectId}/doc/${docId}/raw`
  33. },
  34. _buildFileUrl(projectId, fileId) {
  35. return `${settings.apis.filestore.url}/project/${projectId}/file/${fileId}`
  36. },
  37. _findBibFileIds(project) {
  38. const ids = []
  39. var _process = function(folder) {
  40. _.each(folder.fileRefs || [], function(file) {
  41. if (
  42. __guard__(file != null ? file.name : undefined, x1 =>
  43. x1.match(/^.*\.bib$/)
  44. )
  45. ) {
  46. return ids.push(file._id)
  47. }
  48. })
  49. return _.each(folder.folders || [], folder => _process(folder))
  50. }
  51. _.each(project.rootFolder || [], rootFolder => _process(rootFolder))
  52. return ids
  53. },
  54. _findBibDocIds(project) {
  55. const ids = []
  56. var _process = function(folder) {
  57. _.each(folder.docs || [], function(doc) {
  58. if (
  59. __guard__(doc != null ? doc.name : undefined, x1 =>
  60. x1.match(/^.*\.bib$/)
  61. )
  62. ) {
  63. return ids.push(doc._id)
  64. }
  65. })
  66. return _.each(folder.folders || [], folder => _process(folder))
  67. }
  68. _.each(project.rootFolder || [], rootFolder => _process(rootFolder))
  69. return ids
  70. },
  71. _isFullIndex(project, callback) {
  72. if (callback == null) {
  73. callback = function(err, result) {}
  74. }
  75. return UserGetter.getUser(project.owner_ref, { features: true }, function(
  76. err,
  77. owner
  78. ) {
  79. if (err != null) {
  80. return callback(err)
  81. }
  82. const features = owner != null ? owner.features : undefined
  83. return callback(
  84. null,
  85. (features != null ? features.references : undefined) === true ||
  86. (features != null ? features.referencesSearch : undefined) === true
  87. )
  88. })
  89. },
  90. indexAll(projectId, callback) {
  91. if (callback == null) {
  92. callback = function(err, data) {}
  93. }
  94. return ProjectGetter.getProject(
  95. projectId,
  96. { rootFolder: true, owner_ref: 1 },
  97. function(err, project) {
  98. if (err) {
  99. logger.warn({ err, projectId }, 'error finding project')
  100. return callback(err)
  101. }
  102. logger.log({ projectId }, 'indexing all bib files in project')
  103. const docIds = ReferencesHandler._findBibDocIds(project)
  104. const fileIds = ReferencesHandler._findBibFileIds(project)
  105. return ReferencesHandler._doIndexOperation(
  106. projectId,
  107. project,
  108. docIds,
  109. fileIds,
  110. callback
  111. )
  112. }
  113. )
  114. },
  115. index(projectId, docIds, callback) {
  116. if (callback == null) {
  117. callback = function(err, data) {}
  118. }
  119. return ProjectGetter.getProject(
  120. projectId,
  121. { rootFolder: true, owner_ref: 1 },
  122. function(err, project) {
  123. if (err) {
  124. logger.warn({ err, projectId }, 'error finding project')
  125. return callback(err)
  126. }
  127. return ReferencesHandler._doIndexOperation(
  128. projectId,
  129. project,
  130. docIds,
  131. [],
  132. callback
  133. )
  134. }
  135. )
  136. },
  137. _doIndexOperation(projectId, project, docIds, fileIds, callback) {
  138. if (!Features.hasFeature('references')) {
  139. return callback()
  140. }
  141. return ReferencesHandler._isFullIndex(project, function(err, isFullIndex) {
  142. if (err) {
  143. logger.warn(
  144. { err, projectId },
  145. 'error checking whether to do full index'
  146. )
  147. return callback(err)
  148. }
  149. logger.log(
  150. { projectId, docIds },
  151. 'flushing docs to mongo before calling references service'
  152. )
  153. return Async.series(
  154. docIds.map(docId => cb =>
  155. DocumentUpdaterHandler.flushDocToMongo(projectId, docId, cb)
  156. ),
  157. function(err) {
  158. // continue
  159. if (err) {
  160. logger.warn(
  161. { err, projectId, docIds },
  162. 'error flushing docs to mongo'
  163. )
  164. return callback(err)
  165. }
  166. const bibDocUrls = docIds.map(docId =>
  167. ReferencesHandler._buildDocUrl(projectId, docId)
  168. )
  169. const bibFileUrls = fileIds.map(fileId =>
  170. ReferencesHandler._buildFileUrl(projectId, fileId)
  171. )
  172. const allUrls = bibDocUrls.concat(bibFileUrls)
  173. logger.log(
  174. { projectId, isFullIndex, docIds, bibDocUrls },
  175. 'sending request to references service'
  176. )
  177. return request.post(
  178. {
  179. url: `${settings.apis.references.url}/project/${projectId}/index`,
  180. json: {
  181. docUrls: allUrls,
  182. fullIndex: isFullIndex
  183. }
  184. },
  185. function(err, res, data) {
  186. if (err) {
  187. logger.warn(
  188. { err, projectId },
  189. 'error communicating with references api'
  190. )
  191. return callback(err)
  192. }
  193. if (res.statusCode >= 200 && res.statusCode < 300) {
  194. logger.log({ projectId }, 'got keys from references api')
  195. return callback(null, data)
  196. } else {
  197. err = new Error(
  198. `references api responded with non-success code: ${
  199. res.statusCode
  200. }`
  201. )
  202. logger.log({ err, projectId }, 'error updating references')
  203. return callback(err)
  204. }
  205. }
  206. )
  207. }
  208. )
  209. })
  210. }
  211. }
  212. function __guard__(value, transform) {
  213. return typeof value !== 'undefined' && value !== null
  214. ? transform(value)
  215. : undefined
  216. }