mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-14 06:03:45 +01:00
Merge pull request #25928 from overleaf/bg-history-redis-move-test-script-helpers
move test script helpers in history-v1 GitOrigin-RevId: cc2e5d8b1baea7396f948883a12a91846f77836c
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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 }
|
||||
@@ -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 }
|
||||
Reference in New Issue
Block a user