Workflow status is tracked in GitHub: https://github.com/emulebb/emulebb-rust/issues/153. This local document is retained as the durable engineering spec and evidence record.
RUST-BUG-131 - Make category deletion and transfer remap atomic¶
Summary¶
Apply category deletion, category ordering changes, and affected transfer assignments as one durable operation. A failure at any intermediate statement must leave both the running client and the restart state on the old category snapshot.
Current State¶
crates/emulebb-core/src/category_runtime.rs deletes the selected category,
deletes shifted rows, persists replacement category rows one at a time, and then
updates affected transfer manifests one at a time. The metadata APIs used by
that sequence own separate transactions. A mid-sequence error can therefore
leave missing or reinterpreted category indexes and transfer assignments that
do not match the in-memory snapshot.
RUST-BUG-053 established the required user-visible behavior: transfers in the
deleted category return to default and later categories shift down. This item
preserves that behavior while fixing the durability boundary.
Why This Matters¶
Category deletion is a compound state transition. Partial persistence can move downloads into the wrong logical category after restart, which is a data-model correctness defect rather than a recoverable display issue.
Representative Sites¶
crates/emulebb-core/src/category_runtime.rscategory deletion and remap.crates/emulebb-metadata/src/profile_store.rscategory row writes.crates/emulebb-metadata/src/transfer_store.rstransfer category updates.crates/emulebb-ed2k/src/ed2k_transfer/metadata.rsmanifest category writes.
Intended Shape¶
- Expose one metadata transaction that applies the category snapshot and every affected transfer assignment before commit.
- Publish the new in-memory snapshot only after the durable transaction commits.
- Prefer stable internal category identity plus a separate display/order field, projecting stock/MFC positional semantics at the API boundary, if that makes the schema and future reordering safer.
- If positional identifiers remain durable, update them in one set-oriented transaction with constraints that reject invalid references.
Scope Constraints¶
- Preserve the
RUST-BUG-053deletion result visible to users and imported MFC profiles. - The beta schema and API may change when a stable identity model produces the cleaner long-term design; do not retain a fragile schema for compatibility.
- Do not hold the global async core-state lock while SQLite waits or flushes;
coordinate that boundary with
RUST-REF-016. - Do not silently repair ambiguous partial state after commit; prevent it from being committed.
Acceptance Criteria¶
- [ ] Category deletion and every affected transfer assignment commit in one atomic durable transaction.
- [ ] Failure injection at each write boundary leaves the pre-delete snapshot intact both in memory and after restart.
- [ ] Successful deletion resets transfers in the removed category and shifts later user-visible categories exactly once.
- [ ] Category identifiers cannot refer to a different logical category after crash, rollback, retry, or restart.
- [ ] Concurrent category and transfer mutations are serialized through an explicit ownership boundary instead of incidental global locking.
Validation¶
- Metadata transaction tests with statement-by-statement failure injection.
- Core restart tests for first, middle, last, populated, and empty category deletion.
- Concurrent category edit and transfer update tests.
- Imported MFC profile regression preserving expected positional behavior.