Răsfoiți Sursa

Merge pull request #25928 from overleaf/bg-history-redis-move-test-script-helpers

move test script helpers in history-v1

GitOrigin-RevId: cc2e5d8b1baea7396f948883a12a91846f77836c
Brian Gough 1 an în urmă
părinte
comite
b2b676249d

+ 4 - 82
services/history-v1/test/acceptance/js/storage/expire_redis_chunks.test.js

@@ -1,91 +1,13 @@
 'use strict'
 
 const { expect } = require('chai')
-const { promisify } = require('node:util')
-const { execFile } = require('node:child_process')
-const { Snapshot, Author, Change } = require('overleaf-editor-core')
+const { Author, Change } = require('overleaf-editor-core')
 const cleanup = require('./support/cleanup')
-const redisBackend = require('../../../../storage/lib/chunk_store/redis')
-const redis = require('../../../../storage/lib/redis')
-const rclient = redis.rclientHistory
-const keySchema = redisBackend.keySchema
+const { setupProjectState, rclient, keySchema } = require('./support/redis')
+const { runScript } = require('./support/runscript')
 
 const SCRIPT_PATH = 'storage/scripts/expire_redis_chunks.js'
 
-async function runExpireScript() {
-  const TIMEOUT = 10 * 1000 // 10 seconds
-  let result
-  try {
-    result = await promisify(execFile)('node', [SCRIPT_PATH], {
-      encoding: 'utf-8',
-      timeout: TIMEOUT,
-      env: {
-        ...process.env,
-        LOG_LEVEL: 'debug', // Override LOG_LEVEL for script output
-      },
-    })
-    result.status = 0
-  } catch (err) {
-    const { stdout, stderr, code } = err
-    if (typeof code !== 'number') {
-      console.error('Error running expire script:', err)
-      throw err
-    }
-    result = { stdout, stderr, status: code }
-  }
-  // The script might exit with status 1 if it finds no keys to process, which is ok
-  if (result.status !== 0 && result.status !== 1) {
-    console.error('Expire script failed:', result.stderr)
-    throw new Error(`expire script failed with status ${result.status}`)
-  }
-  return result
-}
-
-// Helper to set up a basic project state in Redis
-async function setupProjectState(
-  projectId,
-  {
-    headVersion = 0,
-    persistedVersion = null,
-    expireTime = null,
-    persistTime = null,
-    changes = [],
-  }
-) {
-  const headSnapshot = new Snapshot()
-  await rclient.set(
-    keySchema.head({ projectId }),
-    JSON.stringify(headSnapshot.toRaw())
-  )
-  await rclient.set(
-    keySchema.headVersion({ projectId }),
-    headVersion.toString()
-  )
-
-  if (persistedVersion !== null) {
-    await rclient.set(
-      keySchema.persistedVersion({ projectId }),
-      persistedVersion.toString()
-    )
-  }
-  if (expireTime !== null) {
-    await rclient.set(
-      keySchema.expireTime({ projectId }),
-      expireTime.toString()
-    )
-  }
-  if (persistTime !== null) {
-    await rclient.set(
-      keySchema.persistTime({ projectId }),
-      persistTime.toString()
-    )
-  }
-  if (changes.length > 0) {
-    const rawChanges = changes.map(c => JSON.stringify(c.toRaw()))
-    await rclient.rpush(keySchema.changes({ projectId }), ...rawChanges)
-  }
-}
-
 function makeChange() {
   const timestamp = new Date()
   const author = new Author(123, 'test@example.com', 'Test User')
@@ -150,7 +72,7 @@ describe('expire_redis_chunks script', function () {
     })
 
     // Run the expire script once after all projects are set up
-    await runExpireScript()
+    await runScript(SCRIPT_PATH)
   })
 
   async function checkProjectStatus(projectId) {

+ 75 - 0
services/history-v1/test/acceptance/js/storage/support/redis.js

@@ -0,0 +1,75 @@
+'use strict'
+
+const { Snapshot } = require('overleaf-editor-core')
+const redis = require('../../../../../storage/lib/redis')
+const redisBackend = require('../../../../../storage/lib/chunk_store/redis')
+const rclient = redis.rclientHistory
+const keySchema = redisBackend.keySchema
+
+// Helper to set up a basic project state in Redis
+async function setupProjectState(
+  projectId,
+  {
+    headVersion = 0,
+    persistedVersion = null,
+    expireTime = null,
+    persistTime = null,
+    changes = [],
+    expireTimeFuture = false, // Default to not setting future expire time unless specified
+  }
+) {
+  const headSnapshot = new Snapshot()
+  await rclient.set(
+    keySchema.head({ projectId }),
+    JSON.stringify(headSnapshot.toRaw())
+  )
+  await rclient.set(
+    keySchema.headVersion({ projectId }),
+    headVersion.toString()
+  )
+
+  if (persistedVersion !== null) {
+    await rclient.set(
+      keySchema.persistedVersion({ projectId }),
+      persistedVersion.toString()
+    )
+  } else {
+    await rclient.del(keySchema.persistedVersion({ projectId }))
+  }
+
+  if (expireTime !== null) {
+    await rclient.set(
+      keySchema.expireTime({ projectId }),
+      expireTime.toString()
+    )
+  } else {
+    // If expireTimeFuture is true, set it to a future time, otherwise delete it if null
+    if (expireTimeFuture) {
+      const futureExpireTime = Date.now() + 5 * 60 * 1000 // 5 minutes in the future
+      await rclient.set(
+        keySchema.expireTime({ projectId }),
+        futureExpireTime.toString()
+      )
+    } else {
+      await rclient.del(keySchema.expireTime({ projectId }))
+    }
+  }
+
+  if (persistTime !== null) {
+    await rclient.set(
+      keySchema.persistTime({ projectId }),
+      persistTime.toString()
+    )
+  } else {
+    await rclient.del(keySchema.persistTime({ projectId }))
+  }
+
+  if (changes.length > 0) {
+    const rawChanges = changes.map(c => JSON.stringify(c.toRaw()))
+    await rclient.rpush(keySchema.changes({ projectId }), ...rawChanges)
+  } else {
+    await rclient.del(keySchema.changes({ projectId }))
+  }
+}
+
+module.exports = { setupProjectState, rclient, keySchema }

+ 35 - 0
services/history-v1/test/acceptance/js/storage/support/runscript.js

@@ -0,0 +1,35 @@
+'use strict'
+
+const { promisify } = require('node:util')
+const { execFile } = require('node:child_process')
+
+async function runScript(scriptPath, options = {}) {
+  const TIMEOUT = options.timeout || 10 * 1000 // 10 seconds default
+  let result
+  try {
+    result = await promisify(execFile)('node', [scriptPath], {
+      encoding: 'utf-8',
+      timeout: TIMEOUT,
+      env: {
+        ...process.env,
+        LOG_LEVEL: 'debug', // Override LOG_LEVEL for script output
+      },
+    })
+    result.status = 0
+  } catch (err) {
+    const { stdout, stderr, code } = err
+    if (typeof code !== 'number') {
+      console.error(`Error running script ${scriptPath}:`, err)
+      throw err
+    }
+    result = { stdout, stderr, status: code }
+  }
+  // The script might exit with status 1 if it finds no keys to process, which is ok
+  if (result.status !== 0 && result.status !== 1) {
+    console.error(`Script ${scriptPath} failed:`, result.stderr)
+    throw new Error(`Script ${scriptPath} failed with status ${result.status}`)
+  }
+  return result
+}
+
+module.exports = { runScript }