Add deleteAllDurableObjects() to workerd:unsafe#6357
Conversation
There was a problem hiding this comment.
I'm Bonk, and I've done a quick review of your PR.
Adds deleteAllDurableObjects() to workerd:unsafe that aborts all evictable DOs, wipes their on-disk SQLite storage, and cancels alarms.
- [LOW] Code duplication between
Server::deleteAllActorsandServer::abortAllActors— The two methods share identical evictable-namespace iteration logic (~15 lines). If that logic ever changes (e.g. a newActorConfigvariant), both must be updated in lockstep. Consider factoring out the iteration into a shared helper that accepts a per-namespace callback, or havingdeleteAllActorsdelegate toabortAllActorsand then do a second pass for storage cleanup only.
This review was generated by an AI code reviewer and may contain errors. Please verify any suggestions before applying them.
|
I'm Bonk, and I've done a quick review of your PR. The PR adds I posted one LOW severity comment about code duplication between |
Merging this PR will not alter performance
Comparing Footnotes
|
|
/bonk fix the conflicts in this PR |
There was a problem hiding this comment.
Re-review after #6104 has landed (per kentonv's request to wait).
- [HIGH] Merge conflicts — The PR's mergeable state is
dirtynow that #6104 has landed. A rebase is needed before this can merge. The alarm scheduler changes in #6104 (per-namespace alarms,AlarmSchedulerconstructor changes) likely conflict withServer::deleteAllActorsand possibly theabortAllActorscall site. - [MEDIUM] Code duplication (still present) —
Server::deleteAllActorsandServer::abortAllActorsstill share ~15 lines of identical evictable-namespace iteration logic, as flagged in my prior review. SinceActorNamespace::deleteAllalready delegates toabortAllinternally,Server::deleteAllActorscould skip the per-namespace abort and just callabortAllActors(reason)first, then do a second pass for storage cleanup only. This would also mean thedeleteAllAlarms()call wouldn't need to be duplicated — it's already done inabortAllActors. Worth considering during the rebase. - [LOW] Post-rebase consideration: per-namespace alarm deletion — With #6104's per-namespace alarm storage, you may want
deleteAllActorsto only delete alarms for evictable namespaces (matching the storage-deletion scope) rather than unconditionally callingdeleteAllAlarms()on the global scheduler. Currently bothabortAllActorsanddeleteAllActorswipe all alarms globally, which also affectspreventEvictionnamespaces' alarms. This may be intentional, but worth verifying against #6104's new namespace-aware alarm model.
The implementation logic itself (abort actors → release file handles → delete storage files) is sound. The test coverage is good — verifies storage deletion, alarm cancellation, and preventEviction exclusion.
This review was generated by an AI code reviewer and may contain errors. Please verify any suggestions before applying them.
|
Review posted on PR #6357. Here's a summary of the findings: HIGH — Merge conflicts: The PR is now in MEDIUM — Code duplication: LOW — Per-namespace alarm deletion: With #6104's per-namespace alarm model, it may be worth verifying whether The implementation logic (abort → release handles → delete storage) is sound, and test coverage is good. |
b05011e to
fb4c79f
Compare
|
@kentonv this should be ready for review now—I've recreated on top of main |
|
I want to note that this is sort of scary functionality to have. I would be extremely upset if, say, |
To clarify the intended use case here, this is specifically to support a user facing API in |
|
/bonk |
There was a problem hiding this comment.
Re-review after the rebase onto main and commit 9e4aed0 addressing kentonv's metadata.sqlite concern.
- [MEDIUM] Code duplication at
Server::deleteAllActors/Server::abortAllActors— Still present from prior reviews. The two methods share identical evictable-namespace iteration logic (~15 lines). SinceActorNamespace::deleteAll()already callsabortAll()internally,Server::deleteAllActorscould callabortAllActors(reason)first and then do a storage-only cleanup pass. This would mean changes to the iteration logic only need to happen in one place. Noted inline — feel free to keep the current factoring if you prefer the explicitness. - kentonv's concern addressed — Commit 9e4aed0 correctly skips
metadata.sqlite*files during storage deletion and instead wipes alarm rows viaAlarmScheduler::deleteAll(). ThestartsWith("metadata.sqlite")check covers WAL/journal companions. The ordering (abort actors → clear alarms → delete files) is sound. - Alarm scheduler
deleteAll()is safe —alarms.clear()cancels in-flight alarm promises before the DB wipe. Since actors are already aborted at this point, any STARTED alarm tasks would already be broken. Prepared statements survive theDELETE FROMsince the table isn't dropped. - Test coverage is good — Tests verify storage wipe, alarm cancellation, and
preventEvictionexclusion. The switch frominMemorytolocalDiskstorage correctly exercises on-disk file deletion.
This review was generated by an AI code reviewer and may contain errors. Please verify any suggestions before applying them.
|
Review posted on PR #6357. Here's a summary: Overall: The implementation is sound. The abort → alarm wipe → file deletion ordering is correct, and the fix for kentonv's metadata.sqlite concern (commit Findings posted:
Reviews: |
75913d9 to
067c94f
Compare
|
The generated output of |
067c94f to
d0e0dac
Compare
Adds a new deleteAllDurableObjects() method to the workerd:unsafe module that aborts all Durable Objects, deletes all their underlying storage (SQLite files on disk), and cancels all scheduled alarms. After calling this, DOs can be recreated with clean state. This is useful for test isolation — clearing all DO state between tests without restarting the workerd process. Like abortAllDurableObjects(), namespaces with preventEviction are not affected. The per-namespace AlarmScheduler introduced in PR #6104 is cleared via a new deleteAll() method that cancels in-memory tasks and wipes the DB. Actor storage files are then deleted from disk.
The AlarmScheduler keeps metadata.sqlite open for the lifetime of the namespace. Deleting it from disk would unlink the file while the scheduler still has it open. Use startsWith to also skip WAL/journal companion files (metadata.sqlite-wal, metadata.sqlite-journal).
59daea7 to
7bbefa4
Compare
…se file handles When sqlite3_close() returns SQLITE_BUSY, the previous code fell back to sqlite3_close_v2() which defers the close, leaving native VFS file handles and memory-mapped sections (CreateFileMapping) active. On Windows this blocks file deletion with ERROR_SHARING_VIOLATION and ERROR_USER_MAPPED_FILE. Instead, iterate any remaining unfinalized statements with sqlite3_next_stmt(), finalize them, then retry sqlite3_close().
On Windows, even after sqlite3_close() returns SQLITE_OK, the OS may not immediately release the file handle. The native SQLite VFS opens files without FILE_SHARE_DELETE, so DeleteFileW() fails with ERROR_SHARING_VIOLATION until the handle is fully released. Add a retry loop (up to 500ms) on Windows only. This is acceptable since deleteAllDurableObjects() is a workerd:unsafe test-only API.
Adds a
deleteAllDurableObjects()method to theworkerd:unsafemodule. This aborts all Durable Objects, deletes all their underlying storage (SQLite files on disk), and cancels all scheduled alarms. After calling this, DOs can be recreated with clean state.Changes
workerd:unsafemodule — newdeleteAllDurableObjects()JS methodIoChannelFactory— newdeleteAllActors()virtual, mirroringabortAllActors()AlarmScheduler— newdeleteAll()that cancels all in-memory alarm tasks and wipes the DB (DELETE FROM _cf_ALARM); called per-namespace since PR Store Durable Object alarms per-namespace on disk #6104 moved alarms to per-namespace schedulersServer— newdeleteAllActors()that iterates evictable namespaces, callingActorNamespace::deleteAll()which: aborts running actors, callsAlarmScheduler::deleteAll(), then deletes all actor SQLite files from diskpreventEvictionnamespaces are unaffected