ClsiCacheManager.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. const { NotFoundError } = require('../Errors/Errors')
  2. const ClsiCacheHandler = require('./ClsiCacheHandler')
  3. const DocumentUpdaterHandler = require('../DocumentUpdater/DocumentUpdaterHandler')
  4. const ProjectGetter = require('../Project/ProjectGetter')
  5. const SplitTestHandler = require('../SplitTests/SplitTestHandler')
  6. /**
  7. * Get the most recent build and metadata
  8. *
  9. * Internal: internal metadata; External: fine to send to user as-is.
  10. *
  11. * @param projectId
  12. * @param userId
  13. * @param filename
  14. * @param signal
  15. * @return {Promise<{internal: {zone: string, location: string}, external: {isUpToDate: boolean, lastUpdated: Date, size: number, allFiles: string[]}}>}
  16. */
  17. async function getLatestBuildFromCache(projectId, userId, filename, signal) {
  18. const [
  19. { location, lastModified: lastCompiled, zone, size, allFiles },
  20. lastUpdatedInRedis,
  21. { lastUpdated: lastUpdatedInMongo },
  22. ] = await Promise.all([
  23. ClsiCacheHandler.getLatestOutputFile(projectId, userId, filename, signal),
  24. DocumentUpdaterHandler.promises.getProjectLastUpdatedAt(projectId),
  25. ProjectGetter.promises.getProject(projectId, { lastUpdated: 1 }),
  26. ])
  27. const lastUpdated =
  28. lastUpdatedInRedis > lastUpdatedInMongo
  29. ? lastUpdatedInRedis
  30. : lastUpdatedInMongo
  31. const isUpToDate = lastCompiled >= lastUpdated
  32. return {
  33. internal: {
  34. location,
  35. zone,
  36. },
  37. external: {
  38. isUpToDate,
  39. lastUpdated,
  40. size,
  41. allFiles,
  42. },
  43. }
  44. }
  45. /**
  46. * Collect metadata and prepare the clsi-cache for the given project.
  47. *
  48. * @param projectId
  49. * @param userId
  50. * @param sourceProjectId
  51. * @param templateId
  52. * @param templateVersionId
  53. * @return {Promise<void>}
  54. */
  55. async function prepareClsiCache(
  56. projectId,
  57. userId,
  58. { sourceProjectId, templateId, templateVersionId }
  59. ) {
  60. const { variant } = await SplitTestHandler.promises.getAssignmentForUser(
  61. userId,
  62. 'copy-clsi-cache'
  63. )
  64. if (variant !== 'enabled') return
  65. const signal = AbortSignal.timeout(5_000)
  66. let lastUpdated
  67. let zone = 'b' // populate template data on zone b
  68. if (sourceProjectId) {
  69. try {
  70. ;({
  71. internal: { zone },
  72. external: { lastUpdated },
  73. } = await getLatestBuildFromCache(
  74. sourceProjectId,
  75. userId,
  76. 'output.tar.gz',
  77. signal
  78. ))
  79. } catch (err) {
  80. if (err instanceof NotFoundError) return // nothing cached yet
  81. throw err
  82. }
  83. }
  84. try {
  85. await ClsiCacheHandler.prepareCacheSource(projectId, userId, {
  86. sourceProjectId,
  87. templateId,
  88. templateVersionId,
  89. zone,
  90. lastUpdated,
  91. signal,
  92. })
  93. } catch (err) {
  94. if (err instanceof NotFoundError) return // nothing cached yet/expired.
  95. throw err
  96. }
  97. }
  98. module.exports = {
  99. getLatestBuildFromCache,
  100. prepareClsiCache,
  101. }