/// <summary> /// Loads a clean copy of the model and passes it to the given /// block, which should apply changes to that model that can /// be retried from scratch multiple times until successful. /// /// This method will return the final state of the saved model. /// The caller should use this afterward, instead of the instance /// it had passed in to the call. /// </summary> /// <param name="model">The model.</param> /// <param name="block">The block.</param> /// <returns>the latest version of the model provided to the method</returns> public virtual T UpdateDocumentWithRetry(T model, Action <T> block) { var documentKey = model.Key; var success = false; T documentToReturn = null; while (!success) { // load a clean copy of the document var latestDocument = GetDocument(documentKey); // if we were unable to find a document then create the document and // return the latest version of the document to the caller if (latestDocument == null) { return(CreateDocument(model)); } // pass the latest document to the given block so the latest changes can be applied if (block != null) { block(latestDocument); } latestDocument.Version += 1; latestDocument.UpdatedAt = SetUpdatedAtWithNoTimeTravel(model.UpdatedAt); var latestDocumentJson = latestDocument.ToJson(); var storeResult = Client.ExecuteCas(StoreMode.Replace, latestDocument.Key, latestDocumentJson, latestDocument.CasValue); if (!storeResult.Success) { continue; } documentToReturn = latestDocument; success = true; } return(documentToReturn); }