How OfficeCLI Batch Mode Handles Atomic Operations with Rollback on Failure
OfficeCLI guarantees atomic batch execution by combining a pre-batch disk barrier, deferred in-memory mutations, and automatic file reloading to restore the original document state if any operation fails.
OfficeCLI, the open-source document automation CLI from the iOfficeAI/OfficeCLI repository, provides a sophisticated batch processing system that treats multi-step document mutations as atomic transactions. When executing commands like set, add, remove, move, or swap against Word documents, the tool ensures that either every operation succeeds or the document reverts to its pre-batch state without partial modifications. This article examines the three-phase mechanism implemented in ResidentServer.cs that enables true all-or-nothing semantics.
The Three-Phase Atomicity Architecture
Phase 1: Pre-Batch Flush Barrier
Before executing the first mutation, the resident server writes the current in-memory DOM to disk to create a deterministic rollback point. This barrier, implemented in src/officecli/ResidentServer.cs (lines 1241-1248), ensures the on-disk file reflects the exact pre-batch state before any modifications occur. By flushing the document to storage upfront, OfficeCLI establishes a pristine snapshot that can be reloaded if subsequent operations encounter errors.
Phase 2: Deferred Saves During Execution
During batch processing, the system temporarily disables automatic document serialization by setting the handler's DeferSave flag to true. As defined in src/officecli/ResidentServer.cs (lines 71-78), this deferral mechanism prevents intermediate states from reaching the disk and eliminates the O(N²) performance cost of saving after every individual mutation. Each command modifies only the resident in-memory DOM, leaving the disk snapshot untouched until the batch completes successfully.
Phase 3: Atomic Rollback on Failure
After processing all batch items, the server checks the anyFailed condition to determine if any mutation encountered an error. If the batch was configured as atomic (the default) and a failure occurred, the system disposes the resident handler, discards the modified in-memory DOM, and reloads the original file from the pre-batch snapshot. This rollback logic in src/officecli/ResidentServer.cs (lines 1212-1239) effectively restores the document to its exact pre-execution state, ensuring zero side effects from failed operations.
Implementation Details and Handler Coordination
The atomic guarantee relies on tight coordination between ResidentServer.cs and document-specific handlers such as WordHandler.cs. The handler's DeferSave property controls the autosave watchdog, while SnapshotPendingWholeParts and DiscardOnDispose hooks enable clean teardown during rollback scenarios. CommandBuilder.cs parses the JSON batch payload, executes each mutation, and tracks success states to trigger the rollback mechanism when necessary.
Practical Usage and Edge Cases
Atomic mode is the default behavior for all batch operations. To execute a batch with atomic guarantees:
officecli batch --file report.docx \
'[{"command":"set","path":"/body/p[1]","prop":"bold","value":true},
{"command":"add","path":"/body","type":"image","src":"logo.png"}]'
To disable atomicity and continue processing after individual failures, use the --best-effort flag:
officecli batch --best-effort --file report.docx \
'[{"command":"set","path":"/body/p[1]","prop":"bold","value":true},
{"command":"set","path":"/nonexistent","prop":"color","value":"red"}]'
Critical edge cases and guarantees include:
- Read-only batches: When commands contain only
get,query, orviewverbs, the atomic barrier is skipped entirely since no mutations occur. - Resident flush mode OFF: If the resident handler's flush mode is disabled, the pre-batch barrier throws a
CliExceptionbecause no on-disk rollback point exists. You must either save the document manually before batching or use--best-effort. - Partial failures: In atomic mode, any single failure triggers complete rollback, returning exit code 1 and leaving the original document unchanged via
CommandBuilder.PrintBatchResults.
Summary
- OfficeCLI batch mode implements atomic operations through a pre-batch flush barrier that snapshots document state to disk before any mutations occur.
- Deferred saves prevent intermediate states from persisting during batch execution, keeping the disk snapshot pristine while modifying only the in-memory DOM.
- On failure, the system reloads the original file from the pre-batch snapshot, discarding the modified resident handler to ensure all-or-nothing semantics.
- The
--best-effortflag disables atomicity, allowing partial success but removing rollback guarantees. - Implementation spans
ResidentServer.cs,WordHandler.cs(viaDeferSaveandDiscardOnDispose), andCommandBuilder.cswith specific line references to the barrier, deferral, and rollback logic.
Frequently Asked Questions
What happens if a batch command fails in the middle of execution?
If any mutation fails during an atomic batch, OfficeCLI immediately stops processing subsequent commands, disposes the resident handler containing the modified DOM, and reloads the document from the pre-batch disk snapshot created by the flush barrier. This ensures the file reverts to its exact pre-execution state, with the failure reported through a non-zero exit code and CommandBuilder.PrintBatchResults.
How does the pre-batch barrier affect performance?
The barrier imposes a single upfront save operation before mutations begin. While this adds initial latency, it prevents the O(N²) cost of saving after every mutation and eliminates the risk of partial writes. The rollback cost is limited to a single file reload, making the atomic guarantee efficient even for large batches.
Can I use atomic batch mode with the resident server's flush mode disabled?
No. If the resident handler's flush mode is set to OFF, the pre-batch barrier cannot create a disk snapshot, causing OfficeCLI to throw a CliException. You must either save the document manually before batching or use the --best-effort flag to disable atomic requirements.
What is the difference between atomic mode and best-effort mode?
Atomic mode (default) guarantees that all mutations succeed or none are applied, using rollback mechanisms to restore the original document on failure. Best-effort mode (--best-effort) processes each command independently, reporting failures without stopping execution or rolling back previous successful mutations, which may leave the document in a partially modified state.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →