Skip to content

Commit 47cd16f

Browse files
fix: only restore backup when gateway needs to start, not on every request
The catch-all route and /api/status were calling restoreIfNeeded on EVERY request, including WebSocket reconnects from the browser. If a reconnect happened after a sync stored a backup handle, restoreIfNeeded would mount a FUSE overlay. The next createBackup would then reset the overlay, wiping upper-layer files (like the marker). Fix: check if the gateway is already running FIRST. Only call restoreIfNeeded if the gateway needs to be started.
1 parent 85f0c23 commit 47cd16f

2 files changed

Lines changed: 29 additions & 23 deletions

File tree

src/index.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -258,23 +258,25 @@ app.all('*', async (c) => {
258258

259259
console.log('[PROXY] Handling request:', url.pathname);
260260

261-
// Restore from backup before starting the gateway.
262-
// This is only called here (catch-all) and from /api/status — NOT from admin
263-
// routes like sync or debug/cli, because the SDK resets the FUSE overlay on
264-
// createBackup, wiping upper-layer writes.
265-
try {
266-
await Promise.race([
267-
restoreIfNeeded(sandbox, c.env.BACKUP_BUCKET),
268-
new Promise((_, reject) => setTimeout(() => reject(new Error('Restore timeout')), 15_000)),
269-
]);
270-
} catch (err) {
271-
console.error('[PROXY] Backup restore failed/timeout:', err);
272-
}
273-
274261
// Check if gateway is already running
275262
const existingProcess = await findExistingGatewayProcess(sandbox);
276263
const isGatewayReady = existingProcess !== null && existingProcess.status === 'running';
277264

265+
// Only restore from backup when the gateway needs to start.
266+
// Restoring on every request (including WebSocket reconnects) would mount a
267+
// FUSE overlay that interferes with createBackup — the SDK resets the overlay
268+
// on backup, wiping upper-layer writes.
269+
if (!isGatewayReady) {
270+
try {
271+
await Promise.race([
272+
restoreIfNeeded(sandbox, c.env.BACKUP_BUCKET),
273+
new Promise((_, reject) => setTimeout(() => reject(new Error('Restore timeout')), 15_000)),
274+
]);
275+
} catch (err) {
276+
console.error('[PROXY] Backup restore failed/timeout:', err);
277+
}
278+
}
279+
278280
// For browser requests (non-WebSocket, non-API), show loading page if gateway isn't ready
279281
const isWebSocketRequest = request.headers.get('Upgrade')?.toLowerCase() === 'websocket';
280282
const acceptsHtml = request.headers.get('Accept')?.includes('text/html');

src/routes/public.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,24 @@ publicRoutes.get('/logo-small.png', (c) => {
3535
publicRoutes.get('/api/status', async (c) => {
3636
const sandbox = c.get('sandbox');
3737

38-
// Restore from backup before checking/starting the gateway
39-
try {
40-
await Promise.race([
41-
restoreIfNeeded(sandbox, c.env.BACKUP_BUCKET),
42-
new Promise((_, reject) => setTimeout(() => reject(new Error('Restore timeout')), 15_000)),
43-
]);
44-
} catch (err) {
45-
console.error('[api/status] Backup restore failed/timeout:', err);
46-
}
47-
4838
try {
4939
let process = await findExistingGatewayProcess(sandbox);
5040
console.log('[api/status] existing process:', process?.id ?? 'none', process?.status ?? '');
5141
if (!process) {
42+
// Restore from backup only when the gateway needs to start.
43+
// Restoring while the gateway is running would mount a FUSE overlay
44+
// that interferes with createBackup.
45+
try {
46+
await Promise.race([
47+
restoreIfNeeded(sandbox, c.env.BACKUP_BUCKET),
48+
new Promise((_, reject) =>
49+
setTimeout(() => reject(new Error('Restore timeout')), 15_000),
50+
),
51+
]);
52+
} catch (err) {
53+
console.error('[api/status] Backup restore failed/timeout:', err);
54+
}
55+
5256
// No gateway process found — start it with a short timeout.
5357
// The loading page polls /api/status every few seconds, so even
5458
// if this attempt times out, subsequent polls will retry.

0 commit comments

Comments
 (0)