Forráskód Böngészése

[project-history] return status "423 Locked" when redis lock is taken (#34429)

GitOrigin-RevId: f40230bc98e8ed8a5358e6db5c515cb2a58f9b85
Jakob Ackermann 1 hónapja
szülő
commit
cb9e834a1f

+ 8 - 0
services/project-history/app/js/server.js

@@ -1,5 +1,6 @@
 import Metrics from '@overleaf/metrics'
 import logger from '@overleaf/logger'
+import OError from '@overleaf/o-error'
 import express from 'express'
 import bodyParser from 'body-parser'
 import * as Errors from './Errors.js'
@@ -54,6 +55,13 @@ app.use(function (error, req, res, next) {
     res.sendStatus(422)
   } else if (error instanceof Errors.TooManyRequestsError) {
     res.status(429).set('Retry-After', 300).end()
+  } else if (
+    error instanceof OError &&
+    error.message === 'Timeout' &&
+    error.info?.key
+  ) {
+    logger.warn({ error, req }, error.message)
+    res.status(423).json({ message: 'redis lock is taken' })
   } else {
     logger.error({ err: error, req }, error.message)
     res.status(500).json({ message: 'an internal error occurred' })

+ 19 - 0
services/project-history/test/acceptance/js/FlushManagerTests.js

@@ -3,10 +3,13 @@ import { expect } from 'chai'
 import { fetchNothing, fetchJsonWithResponse } from '@overleaf/fetch-utils'
 import assert from 'node:assert'
 import mongodb from 'mongodb-legacy'
+import RedisWrapper from '@overleaf/redis-wrapper'
 import * as ProjectHistoryClient from './helpers/ProjectHistoryClient.js'
 import * as ProjectHistoryApp from './helpers/ProjectHistoryApp.js'
 import Settings from '@overleaf/settings'
 const { ObjectId } = mongodb
+const LockKey = Settings.redis.lock.key_schema
+const lockRClient = RedisWrapper.createClient(Settings.redis.lock)
 
 const MockHistoryStore = () => nock('http://127.0.0.1:3100')
 const MockWeb = () => nock('http://127.0.0.1:3000')
@@ -150,6 +153,22 @@ describe('Flushing old queues', function () {
       })
     })
 
+    describe('when the project lock is already held', function () {
+      it('returns 423', async function () {
+        const key = LockKey.projectHistoryLock({ project_id: this.projectId })
+        await lockRClient.set(key, 'taken')
+        try {
+          const { statusCode } = await ProjectHistoryClient.flushProject(
+            this.projectId,
+            { allowErrors: true }
+          )
+          expect(statusCode).to.equal(423)
+        } finally {
+          await lockRClient.del(key)
+        }
+      })
+    })
+
     describe('when the update is newer than the cutoff and project has short queue', function () {
       beforeEach(function () {
         Settings.shortHistoryQueues.push(this.projectId)