diff options
author | Jason Zhang <jason.zhang@mongodb.com> | 2023-01-26 03:51:07 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-01-26 05:16:57 +0000 |
commit | be8fd031fb851f5c0c2288585abafd92439c8d0a (patch) | |
tree | f1cb7b7e5c35cbf7088dbb4702b8d435391422e0 /src/mongo/db/query | |
parent | 63970dc922c2b307c59a9543613f41714fb1b6d6 (diff) | |
download | mongo-be8fd031fb851f5c0c2288585abafd92439c8d0a.tar.gz |
SERVER-70506 Support retryability for updateOne, deleteOne, and findAndModify
Diffstat (limited to 'src/mongo/db/query')
-rw-r--r-- | src/mongo/db/query/cursor_response.cpp | 28 | ||||
-rw-r--r-- | src/mongo/db/query/cursor_response.h | 13 | ||||
-rw-r--r-- | src/mongo/db/query/cursor_response.idl | 9 |
3 files changed, 46 insertions, 4 deletions
diff --git a/src/mongo/db/query/cursor_response.cpp b/src/mongo/db/query/cursor_response.cpp index d53a24c7c5f..1940e3def4d 100644 --- a/src/mongo/db/query/cursor_response.cpp +++ b/src/mongo/db/query/cursor_response.cpp @@ -57,6 +57,7 @@ const char kBatchDocSequenceFieldInitial[] = "cursor.firstBatch"; const char kPostBatchResumeTokenField[] = "postBatchResumeToken"; const char kPartialResultsReturnedField[] = "partialResultsReturned"; const char kInvalidatedField[] = "invalidated"; +const char kWasStatementExecuted[] = "$_wasStatementExecuted"; } // namespace @@ -84,6 +85,10 @@ void CursorResponseBuilder::done(CursorId cursorId, const NamespaceString& curso _cursorObject->append(kInvalidatedField, _invalidated); } + if (_wasStatementExecuted) { + _cursorObject->append(kWasStatementExecuted, _wasStatementExecuted); + } + _cursorObject->append(kIdField, cursorId); _cursorObject->append(kNsField, NamespaceStringUtil::serialize(cursorNamespace)); if (_options.atClusterTime) { @@ -140,7 +145,8 @@ CursorResponse::CursorResponse(NamespaceString nss, boost::optional<BSONObj> varsField, boost::optional<std::string> cursorType, bool partialResultsReturned, - bool invalidated) + bool invalidated, + bool wasStatementExecuted) : _nss(std::move(nss)), _cursorId(cursorId), _batch(std::move(batch)), @@ -150,7 +156,8 @@ CursorResponse::CursorResponse(NamespaceString nss, _varsField(std::move(varsField)), _cursorType(std::move(cursorType)), _partialResultsReturned(partialResultsReturned), - _invalidated(invalidated) {} + _invalidated(invalidated), + _wasStatementExecuted(wasStatementExecuted) {} std::vector<StatusWith<CursorResponse>> CursorResponse::parseFromBSONMany( const BSONObj& cmdResponse) { @@ -299,6 +306,16 @@ StatusWith<CursorResponse> CursorResponse::parseFromBSON(const BSONObj& cmdRespo } } + auto wasStatementExecuted = cursorObj[kWasStatementExecuted]; + if (wasStatementExecuted) { + if (wasStatementExecuted.type() != BSONType::Bool) { + return {ErrorCodes::BadValue, + str::stream() << kWasStatementExecuted + << " format is invalid; expected Bool, but found: " + << wasStatementExecuted.type()}; + } + } + auto writeConcernError = cmdResponse["writeConcernError"]; if (writeConcernError && writeConcernError.type() != BSONType::Object) { @@ -317,7 +334,8 @@ StatusWith<CursorResponse> CursorResponse::parseFromBSON(const BSONObj& cmdRespo varsElt ? varsElt.Obj().getOwned() : boost::optional<BSONObj>{}, typeElt ? boost::make_optional<std::string>(typeElt.String()) : boost::none, partialResultsReturned.trueValue(), - invalidatedElem.trueValue()}}; + invalidatedElem.trueValue(), + wasStatementExecuted.trueValue()}}; } void CursorResponse::addToBSON(CursorResponse::ResponseType responseType, @@ -351,6 +369,10 @@ void CursorResponse::addToBSON(CursorResponse::ResponseType responseType, cursorBuilder.append(kInvalidatedField, _invalidated); } + if (_wasStatementExecuted) { + cursorBuilder.append(kWasStatementExecuted, _wasStatementExecuted); + } + cursorBuilder.doneFast(); builder->append("ok", 1.0); diff --git a/src/mongo/db/query/cursor_response.h b/src/mongo/db/query/cursor_response.h index 7b33b71e1d5..87f5f22c263 100644 --- a/src/mongo/db/query/cursor_response.h +++ b/src/mongo/db/query/cursor_response.h @@ -99,6 +99,10 @@ public: _invalidated = true; } + void setWasStatementExecuted(bool wasStatementExecuted) { + _wasStatementExecuted = true; + } + long long numDocs() const { return _numDocs; } @@ -135,6 +139,7 @@ private: BSONObj _postBatchResumeToken; bool _partialResultsReturned = false; bool _invalidated = false; + bool _wasStatementExecuted = false; }; /** @@ -216,7 +221,8 @@ public: boost::optional<BSONObj> varsField = boost::none, boost::optional<std::string> cursorType = boost::none, bool partialResultsReturned = false, - bool invalidated = false); + bool invalidated = false, + bool wasStatementExecuted = false); CursorResponse(CursorResponse&& other) = default; CursorResponse& operator=(CursorResponse&& other) = default; @@ -269,6 +275,10 @@ public: return _invalidated; } + bool getWasStatementExecuted() const { + return _wasStatementExecuted; + } + /** * Converts this response to its raw BSON representation. */ @@ -289,6 +299,7 @@ private: boost::optional<std::string> _cursorType; bool _partialResultsReturned = false; bool _invalidated = false; + bool _wasStatementExecuted = false; }; } // namespace mongo diff --git a/src/mongo/db/query/cursor_response.idl b/src/mongo/db/query/cursor_response.idl index af264710874..391beb38c35 100644 --- a/src/mongo/db/query/cursor_response.idl +++ b/src/mongo/db/query/cursor_response.idl @@ -76,6 +76,15 @@ structs: description: "Boolean represents if the cursor has been invalidated." type: optionalBool stability: stable + $_wasStatementExecuted: + description: "An optional field set to true if a write without shard key had already + applied the write. To provide some context, this internal field is + used by the two phase write without shard key protocol introduced in + PM-1632 to support retryable writes for updateOne without shard key, + deleteOne without shard key, and findAndModify without shard key." + type: optionalBool + cpp_name: wasStatementExecuted + stability: internal InitialResponseCursor: description: "A struct representing an initial response cursor." |