Skip to content

Commit

Permalink
Fix: double-check that the root doc exists.
Browse files Browse the repository at this point in the history
Pando's database writes use document filters to avoid doing writes under
two circumstances:

1. Conditional updates whose preconditions fail
2. Updates inside nonexistent state tree nodes

In either case, bosk is supposed to ignore the updates.

However, this led to a bug when refurbishing from pando to another
format. Refurbishing deletes any existing state documents, and this led
to a window after the delete but before the DELETE event arrives, during
which updates would be silently ignored.

As a workaround, when we detect that an update affected no documents, we
double check that the root document does, in fact, exist.

For Sequoia, for simplicity, we don't do this.
  • Loading branch information
prdoyle committed Feb 9, 2024
1 parent 9c5629a commit 97deb18
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -781,8 +781,16 @@ private boolean doUpdate(BsonDocument updateDoc, BsonDocument filter) {
UpdateResult result = collection.updateOne(filter, updateDoc);
LOGGER.debug("| Update result: {}", result);
if (result.wasAcknowledged()) {
assert result.getMatchedCount() <= 1;
return result.getMatchedCount() >= 1;
long matchedCount = result.getMatchedCount();
if (matchedCount == 0) {
LOGGER.debug("| -> No documents were updated; double-checking that the root document still exists");
try (var cursor = collection.find(documentFilter(rootRef)).limit(1).cursor()) {
if (!cursor.hasNext()) {
throw new IllegalStateException("Root document disappeared");
}
}
}
return matchedCount >= 1;
} else {
LOGGER.error("MongoDB write was not acknowledged");
LOGGER.trace("Details of MongoDB write not acknowledged:\n\tFilter: {}\n\tUpdate: {}\n\tResult: {}", filter, updateDoc, result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,24 @@ private boolean doUpdate(BsonDocument updateDoc, BsonDocument filter) {
UpdateResult result = collection.updateOne(filter, updateDoc);
LOGGER.debug("| Update result: {}", result);
if (result.wasAcknowledged()) {
// NOTE: This case can occur in a few situations:
// 1. A conditional update whose precondition failed
// 2. An update inside a nonexistent node
// 3. The bosk document has disappeared
//
// Differentiating these cases without transactions is complex,
// and the only benefit of the Sequoia format is its simplicity,
// so for now, we're opting not to handle this case.
//
// This means valid updates can be silently ignored during the window
// between when a refurbish operation deletes the bosk document and
// when the corresponding change event arrives. We are going to accept
// and document this risk for the time being, unless we can determine
// a sufficiently straightforward way to detect this situation.
//
// Therefore, when refurbishing from Sequoia to another format,
// the system should be quiescent or else updates may be lost.

assert result.getMatchedCount() <= 1;
return result.getMatchedCount() >= 1;
} else {
Expand Down

0 comments on commit 97deb18

Please sign in to comment.