code: @InterfaceAudience.Public
      public SavedRevision update(DocumentUpdater updater) throws CouchbaseLiteException {
          int lastErrorCode = Status.UNKNOWN;
          do {
              // if there is a conflict error, get the latest revision from db instead of cache
              if (lastErrorCode == Status.CONFLICT) {
                  forgetCurrentRevision();
              }
              UnsavedRevision newRev = createRevision();
              if (updater.update(newRev) == false) {
                  break;
              }
              try {
                  SavedRevision savedRev = newRev.save();
                  if (savedRev != null) {
                      return savedRev;
                  }
              } catch (CouchbaseLiteException e) {
                  lastErrorCode = e.getCBLStatus().getCode();
                  if (lastErrorCode != Status.CONFLICT)
                      throw e;
              }
          } while (lastErrorCode == Status.CONFLICT);
          return null;
      }
docs: Saves a new revision by letting the caller update the existing properties.
  This method handles conflicts by retrying (calling the block again).
  The DocumentUpdater implementation should modify the properties of
  the new revision and return YES to save or NO to cancel.
  Be careful: the DocumentUpdater can be called multiple times if there is a conflict!
  
  @param updater the callback DocumentUpdater implementation.  Will be called on each
  attempt to save. Should update the given revision's properties and then
  return YES, or just return NO to cancel.
  @return The new saved revision, or null on cancellation.
  @throws CouchbaseLiteException