CodamAIDocs
Topicdone

May the client retry?

Which operations can be repeated safely, and for which a repetition creates a second object.

Variants
GET/POST read, queryPUTPATCHDELETEPOST createrollbackafter 401after 4xxafter 5xxno response

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?

Operationrepeatable?What a repetition does
POST /read/{id}, GET /read/{id}, POST /query, POST /{id}/historyyesnothing, it only reads
PUT /update/{id}yesthe same end state; _updatedOn and, for audited models, another revision
PATCH /update/{id}yesthe same end state, as long as the values are absolute
DELETE /delete/{id}yesthe second request returns 404, because the object is already gone
POST /{id}/rollback/{revision}yesthe same content, another revision
POST /createnoa second object with a new id
POST /create for a singletonyesthe second request returns 400 object-already-exists|use-update

Two limitations for PUT and PATCH:

  • List entries without id are 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 their id.
  • 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.

What to do after which response?
ResponseSaved? What to do?
2xxsaved. Do not repeat.
200 with CDMS_CREATE_SUCCEEDED_READ_FAILEDcreated, the id is in the response. Do not create again.
401nothing. Renew the token, then repeat the same request, even a create.
400, 403, 404, 422nothing. An unchanged repetition fails the same way; fix the cause first.
409 already-exists or database-integrity-failednothing. The stored data stands in the way; an unchanged repetition fails the same way.
409 CDMS_OPTIMISTIC_LOCK_CONFLICTnothing. Read the object again, redo the change, then repeat.
503nothing. The database cannot be reached or did not grant a lock in time. Repeat after a pause.
500nothing. 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.

  1. 1
    Client→CDMS
    POST /order/create with orderNr: A-1000
  2. 2
    Client
    no response, timeout
  3. 3
    Client→CDMS
    searches first: POST /order/query with filter orderNr EQ A-1000
  4. 4
    Client
    hit → the object already exists, take over its id
  5. 5
    Client→CDMS
    no 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

Sources in the code and the knowledge base
  • CDMS/cdms-rest-api – RequestTransactionCommitter (commit before the response), CdmsExceptionMapper (rollback on every error), AbstractRestSingletonApi.createObject (object-already-exists|use-update)
  • CDMS/cdms-system-layer – AbstractSystemLayer.createObject, updateObject, patchObject, deleteObject, historyRollback
  • CDMS/cdms-persistence-database – AuditHistoryReader.historyRollback (new revision)
Search