What this is about
Networks are unreliable. Sometimes a response does not arrive, sometimes a token has expired, sometimes the database is briefly gone. Then the question is: May I simply send the request again?
An operation is called idempotent if running it twice has the same result as running it once. You may repeat such operations safely. CDMS has no idempotency key with which the server itself recognizes repetitions. The decision lies with the client.
Which operation can be repeated?
| Operation | repeatable? | What a repetition does |
|---|---|---|
POST /read/{id}, GET /read/{id}, POST /query, POST /{id}/history | yes | nothing, it only reads |
PUT /update/{id} | yes | the same end state; _updatedOn and, for audited models, another revision |
PATCH /update/{id} | yes | the same end state, as long as the values are absolute |
DELETE /delete/{id} | yes | the second request returns 404, because the object is already gone |
POST /{id}/rollback/{revision} | yes | the same content, another revision |
POST /create | no | a second object with a new id |
POST /create for a singleton | yes | the second request returns 400 object-already-exists|use-update |
Two limitations for PUT and PATCH:
- List entries without
idare new children. Every repetition creates them anew, and the ones created by the previous request drop out of the list (with the DELETE flag they are deleted). Always send existing children with theirid. - Uploaded files are stored again with every repetition. For audited file models, each time another version is created.
What the response says about the state
Because CDMS commits before the response and rolls back on every error, the response tells you what is saved. See One request, one transaction.
| Response | Saved? What to do? |
|---|---|
| 2xx | saved. Do not repeat. |
200 with CDMS_CREATE_SUCCEEDED_READ_FAILED | created, the id is in the response. Do not create again. |
| 401 | nothing. Renew the token, then repeat the same request, even a create. |
| 400, 403, 404, 422 | nothing. An unchanged repetition fails the same way; fix the cause first. |
409 already-exists or database-integrity-failed | nothing. The stored data stands in the way; an unchanged repetition fails the same way. |
409 CDMS_OPTIMISTIC_LOCK_CONFLICT | nothing. Read the object again, redo the change, then repeat. |
| 503 | nothing. The database cannot be reached or did not grant a lock in time. Repeat after a pause. |
| 500 | nothing. An error in the server; a repetition usually does not help. |
| no response (timeout, connection dropped) | unclear: maybe committed, maybe not |
With 401, CDMS did not process the request at all: the filter chain rejects an invalid or expired token before anything is written. See The path of the token.
“Nothing saved” applies to the database. File contents and requests across two databases have their own rules: Files and transaction and No atomicity across two databases.
No response after a create
This is the only case in which a blind repetition does harm. The commit may have succeeded and only the response got lost.
-
1Client→CDMS
POST /order/createwithorderNr: A-1000 -
2Clientno response, timeout
-
3Client→CDMSsearches first:
POST /order/querywith filterorderNr EQ A-1000 -
4Clienthit → the object already exists, take over its
id -
5Client→CDMSno hit → repeat the
create
For this to work, the model needs a field by which you recognize the object: an order number, a reference generated by the client, an email address. Safest is a uniqueness rule on that field: then a duplicate create fails with 409 already-exists instead of creating a second object.
Pitfalls
What comes next
- The bracket around a request: One request, one transaction
- Created, but not read back: Create and read back: STRICT or LENIENT
- Conflicts: Concurrent changes
- All status codes: Map of status codes