Imagine a collection app with a bulk action: select 40 movie editions and move their catalog location from “Living room shelf” to “Moving box 03.” The request times out. Did nothing happen, did everything happen, or did only some records change?
A generic “Something went wrong” toast leaves the user unable to answer that question. A better design makes the outcome inspectable at the item level. This is a conceptual design exercise, not a claim about an existing production implementation.
Define what is moving
The action changes a catalog record's location. It cannot establish where the physical disc actually is. Keep “recorded location” distinct from “physically checked” if the product supports both.
Use stable edition IDs, not movie titles, as the selection. A user may own multiple editions of the same film. At submission, freeze the selected IDs and destination into an operation record; do not reconstruct them later from a filter whose results may have changed.
For each item, retain the expected source location and record version. This gives the service a basis for detecting edits made after the user opened the selection screen.
Choose the transaction boundary deliberately
If the product requires all selected records to move together and the storage system can support that requirement, a transaction may be the simplest contract. A partially successful workflow should not be the accidental result of an implementation shortcut.
Here, assume independent item updates are useful and the batch may span multiple requests. Show that contract before submission: each selected edition will be processed separately, and the result can contain both successful and unsuccessful items.
Separate unknown from failed
Give the operation a durable ID that the client can use to retrieve its status after a refresh or network interruption. Suggested item states are pending, processing, succeeded, conflict, and failed. At the client, “outcome not yet confirmed” describes missing information rather than a confirmed server-side failure.
A summary such as “32 moved, 3 need review, 5 awaiting confirmation” tells the user more than a percentage. Keep the item list available so they can see which editions remain unresolved. Do not report the entire selection as moved because the first request was accepted.
Make retries safe at the item level
A timeout can occur after the server commits an update but before the client receives the response. Microsoft Azure's Retry pattern guidance highlights the importance of considering idempotency: repeating a request must not accidentally repeat effects.
For this design, give each item action an identity derived from the operation ID and edition ID. The server should persist the result with the location change atomically, or use an equivalent consistency mechanism. A repeated request with the same identity returns that established result instead of producing another move event.
Setting a location to the same value may look harmless, but duplicate audit entries or notifications are still duplicate effects. Handle those consistently too. Bind the identity to the original request contents and reject attempts to reuse it with a different destination.
Treat a conflict as a decision
Suppose another device moved an edition to “Bedroom shelf” while the batch was running. Compare the current version with the expected version before applying the change. A mismatch should produce a conflict, not silently overwrite the newer location.
Show the expected source, current source, and requested destination. Let the user keep the current location or explicitly start a new move based on the latest state. A conflict needs a decision; endlessly retrying the unchanged request will not resolve it.
Make undo another checked operation
Store the original location for each successful item. An undo request can attempt to restore that location, but only after checking that the record still reflects the move being reversed.
If somebody has edited the location again, surface a conflict rather than sending it back to an obsolete shelf. Report undo results with the same per-item clarity as the original operation. “Undo requested” and “all changes reversed” are different outcomes.
Review the uncomfortable cases
A useful review includes a lost response after a successful write, a reload during processing, a repeated submit, a destination removed before execution, an edition deleted mid-batch, and an undo after a later edit. For each case, ask what the server knows, what the interface can truthfully show, and what action remains available.
This example draws its domain from our DVDWholesaleShop catalog, but the proposed workflow belongs to a hypothetical collection app. The same design questions apply to bulk labels, document folders, and asset assignments.
A dependable batch action leaves a readable account of what happened. That account is what lets a user recover without guessing.
Top comments (0)