[web] gracefully handle broken histories when compiling from history (#32386)

* [web] gracefully handle broken histories when compiling from history

* [web] trim down schema

GitOrigin-RevId: 97d59b31eb25644d7de1194a45281def6982b130
This commit is contained in:
Jakob Ackermann
2026-03-24 09:06:18 +00:00
committed by Copybot
parent e8fe0348a4
commit adef5b26fb
5 changed files with 97 additions and 33 deletions
@@ -244,6 +244,24 @@ export function getUpdates(req, res, next) {
)
}
const getResyncPendingSchema = z.object({
params: z.object({
project_id: zz.objectId(),
}),
})
export function getResyncPending(req, res, next) {
const {
params: { project_id: projectId },
} = parseReq(req, getResyncPendingSchema)
SyncManager.getResyncState(projectId, (err, state) => {
if (err) return next(err)
res.json({
resyncPending: state.isSyncOngoing(),
})
})
}
const latestVersionSchema = z.object({
params: z.object({
project_id: zz.objectId().or(z.coerce.number()),
@@ -25,6 +25,11 @@ export function initialize(app) {
app.post('/project/:project_id/flush', HttpController.flushProject)
app.get(
'/project/:project_id/resync-pending',
HttpController.getResyncPending
)
app.post('/project/:project_id/resync', HttpController.resyncProject)
app.get('/project/:project_id/dump', HttpController.dumpProject)
+11 -4
View File
@@ -91,7 +91,7 @@ async function startHardResync(projectId, options = {}) {
async function startResyncWithoutLock(projectId, options) {
await ErrorRecorder.promises.recordSyncStart(projectId)
const syncState = await _getResyncState(projectId)
const syncState = await getResyncState(projectId)
if (syncState.isSyncOngoing()) {
throw new OError('sync ongoing')
}
@@ -109,7 +109,11 @@ async function startResyncWithoutLock(projectId, options) {
await setResyncState(projectId, syncState)
}
async function _getResyncState(projectId) {
/**
* @param {string} projectId
* @return {Promise<SyncState>}
*/
async function getResyncState(projectId) {
const rawSyncState = await db.projectHistorySyncState.findOne({
project_id: new ObjectId(projectId.toString()),
})
@@ -185,7 +189,7 @@ async function clearResyncStateIfAllAfter(projectId, date) {
}
async function skipUpdatesDuringSync(projectId, updates) {
const syncState = await _getResyncState(projectId)
const syncState = await getResyncState(projectId)
if (!syncState.isSyncOngoing()) {
logger.debug({ projectId }, 'not skipping updates: no resync in progress')
// don't return syncState when unchanged
@@ -229,7 +233,7 @@ async function expandSyncUpdates(
return updates
}
const syncState = await _getResyncState(projectId)
const syncState = await getResyncState(projectId)
// compute the current snapshot from the most recent chunk
const snapshotFiles =
@@ -1284,6 +1288,7 @@ function trackingDirectivesEqual(a, b) {
// EXPORTS
const getResyncStateCb = callbackify(getResyncState)
const startResyncCb = callbackify(startResync)
const startResyncWithoutLockCb = callbackify(startResyncWithoutLock)
const startHardResyncCb = callbackify(startHardResync)
@@ -1327,6 +1332,7 @@ const expandSyncUpdatesCb = (
}
export {
getResyncStateCb as getResyncState,
startResyncCb as startResync,
startResyncWithoutLockCb as startResyncWithoutLock,
startHardResyncCb as startHardResync,
@@ -1337,6 +1343,7 @@ export {
}
export const promises = {
getResyncState,
startResync,
startResyncWithoutLock,
startHardResync,