Upstream deletes from the container are dropped as stale: tombstoneIsStale compares revs from different peers' rev spaces
Los mantenedores suelen responder en 1 día
@aron-cf ya está trabajando en esto.
Desde el 29/9/2026.
Evaluación
Este issue todavía no se ha evaluado.
Descripción
Summary
Deletes made inside the container (rm, and therefore mv) are never applied to the Durable Object's VFS once the DO's local revision counter is ahead of computerd's. tombstoneIsStale compares revisions from two unrelated counters.
Environment
@cloudflare/computer0.3.1 withcomputer-computerd-linux-x64:0.3.1.withWorkspaceContainer+CloudflareContainerBackend, standard-1.- Same code on
main(e5e28a7).
What happens
- A workspace has some history. Local writes via
ws.fs.writeFilebumpvfs_meta.rev, and so does every file pulled back from the container, becauselinkStagedChunksSyncstamps it with a fresh local rev. ws.runtime.exec('rm x', { backend: 'linux' }).- The container's
lsno longer showsx, andresult()reportssync.status: 'complete',pulled: 0. xis still in the DO's VFS. It is never re-pushed, because it did not change locally, so the two sides stay diverged. Amv a barrives as "b created, a still present".
Files created in the container do propagate, because alreadyApplied compares manifest hashes, not revs.
Cause
packages/dofs/src/sync/apply.ts:
function tombstoneIsStale(db, entry) {
const live = resolveInode(db, entry.path, { followSymlinks: false });
if (live === null) return false;
const row = db.one("SELECT rev FROM vfs_nodes WHERE inode = ?", live.inode);
return row !== undefined && row.rev > entry.rev;
}
row.revis the local node's rev (localvfs_meta.revspace).- For an upstream entry,
entry.revcomes from the peer's change log (computerd's own counter). packages/rpc/src/server.tsitself describes the push caller as "a sync peer with its own rev space".
computerd starts fresh after every sleep, so its counter is small, while the DO's grows with every write and pull. row.rev > entry.rev therefore holds for practically every path, and every container delete is dropped as "stale".
On main the predicate is also used by applyChangesSync (apply.ts:426), so the RPC server path has the same comparison. The same predicate runs on the computerd side for deletes pushed from the DO. It works today only because the DO's revs are larger, and would drop DO deletes if the container's counter were ever ahead.
Repro without a container
Drive a real Workspace over node:sqlite against a fake SyncRPC/ShellRPC peer whose counter starts at 1:
- Write
/workspace/xa few times so the local rev is well above the peer's. - Make the fake command append
{ kind: 'delete', path: '/workspace/x', rev: <peer rev> }to the peer's change log. - Run
ws.runtime.exec(..., { backend }).
Result: pulled === 0 and /workspace/x still exists.
Workaround we are running
One possible fix, which we applied as a local patch to dist/index.js: decide staleness by whether the peer has seen the local version. A node pushed to this backend (rev <= pushRev) yields to the peer's delete; a local change newer than the last completed push still wins.
function tombstoneIsStale(db, entry, backend) {
const live = resolveInode(db, entry.path, { followSymlinks: false });
if (live === null) return false;
const row = db.one("SELECT rev FROM vfs_nodes WHERE inode = ?", live.inode);
if (row === void 0) return false;
return row.rev > readWatermark(db, "pushRev", backend ?? DEFAULT_BACKEND_ID);
}
// call site in applyChanges: tombstoneIsStale(db, entry, options.backend)
After a watermark divergence (pullOnceImpl resets pushRev to 0), deletes stay conservatively dropped until the next push re-establishes the watermark. We are not sure this is the right fix for the computerd side, or for pack pulls, but the cross-space comparison looks unintended.
- Lenguaje dominante
- TypeScript
- Estrellas
- 9.5k
- Forks
- 552
- Merge medio
- 2 d 6 h
- PR fusionados (30 d)
- 47
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de cloudflare/computer
-
Sync planning scans the full pending change set before yielding; repeated Durable Object CPU-limit failuresPosiblemente ocupada @aron-cf la tomó hace 1 día. Abiertobug
cloudflare/computer#225 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
enhancement
Dificultad 4/5 3-5 días Aptitud para principiantes 30/100
cloudflare/computer#224 · 5 comentarios · 1 reacción ·
Los mantenedores suelen responder en 1 día
-
Always run the "next" computerd workflow on push to the `release` branchPosiblemente ocupada @aron-cf la tomó hace 2 días. Abiertobug
cloudflare/computer#222 · 2 comentarios · 1 reacción · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
Make just-bash and acorn optional peer dependencies, pulled in only by the backend that needs themAbiertoenhancement
Dificultad 3/5 1-2 días Aptitud para principiantes 45/100
cloudflare/computer#220 · 3 comentarios · 1 reacción ·
Los mantenedores suelen responder en 1 día
-
Workspace namespaces: more than one Workspace per Durable Object storagePosiblemente ocupada @aron-cf la tomó hace 2 días. Abiertoenhancement
cloudflare/computer#219 · 1 comentario · 1 reacción · 1 asignado ·
Los mantenedores suelen responder en 1 día
Todos los issues de cloudflare/computer
Issues similares
-
bug cli service
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
Los mantenedores suelen responder en 1 día
-
create-element: same editorAlias silent-fallback bug as #201, not covered by that fixPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abiertogenerated-by-ai
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
umbraco/Umbraco-CMS-MCP-Editor#208 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Table: Space fires onActivate in single-selection mode — the reference doc and the JSDoc disagreeAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
sidorares/react-x11-components#764 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
backnotprop/plannotator#1840 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
JoviDeCroock/pracht#432 ·
Los mantenedores suelen responder en 1 día