ExportXMLWordPrintableJSON

    • Type: Task
    • Resolution: Unresolved
    • Priority: Major - P3
    • None
    • Affects Version/s: None
    • Component/s: None
    • None
    • Storage Execution
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      If a replicated metadata checkpoint includes a new timestamp but no new replicated metadata deltas, the checkpoint is formatted in the oplog as top-level container write, not an applyOps entry. isCheckpointApplyOpsEntry(), will return false for this oplog entry because it is not an applyOps entry, and this is OK because we do not need to validate timestamp-only checkpoints.

      1. Document this decision in the technical design.
      2. Add a test to size_count_checkpoint_validator_test.cpp that illustrates this behavior.
      diff --git a/src/mongo/db/replicated_fast_count/size_count_checkpoint_validator_test.cpp b/src/mongo/db/replicated_fast_count/size_count_checkpoint_validator_test.cpp
      index 56a5da20e0b9..839760e96492 100644
      --- a/src/mongo/db/replicated_fast_count/size_count_checkpoint_validator_test.cpp
      +++ b/src/mongo/db/replicated_fast_count/size_count_checkpoint_validator_test.cpp
      @@ -277,25 +277,44 @@ protected:
       }; TEST_F(CheckpointOplogParsingTest, ClassifiesEntriesOnRealOplog) {
      +    // Write a checkpoint with only a timestamp store entry.
      +    {
      +        const OplogScanResult batch{.deltas = {}, .lastTimestamp = Timestamp(0, 2)};
      +        ASSERT_TRUE(flusher::flush(operationContext(), *sizeCountStore, *timestampStore, batch)
      +                        .has_value());
      +
      +        // Check isCheckpointApplyOpsEntry() correctly matches on checkpoint.
      +        const std::vector<repl::OplogEntry> checkpointEntries =
      +            getOplogEntriesMatching(operationContext(), [](const repl::OplogEntry& entry) {
      +                return isCheckpointApplyOpsEntry(entry);
      +            });
      +        // THIS IS THE EXPECTED BEHAVIOR.
      +        ASSERT_EQ(checkpointEntries.size(), 0);
      +    }
      +
           // Write a user write, a checkpoint, and a watermark to the oplog.
      -    insertUserDoc(BSON("_id" << 0 << "x" << 0));
      -    const OplogScanResult batch{
      -        .deltas = {{UUID::gen(),
      -                    ReplicatedMetadataDelta{
      -                        .metadata = {.sizeCount = CollectionSizeCount{.size = 30, .count = 2}}}}},
      -        .lastTimestamp = Timestamp(1, 2)};
      -    ASSERT_TRUE(
      -        flusher::flush(operationContext(), *sizeCountStore, *timestampStore, batch).has_value());
      -    flusher::writeWatermark(operationContext());
      -
      -    // Check isCheckpointApplyOpsEntry() correctly matches on checkpoint.
      -    const std::vector<repl::OplogEntry> checkpointEntries =
      -        getOplogEntriesMatching(operationContext(), [](const repl::OplogEntry& entry) {
      -            return isCheckpointApplyOpsEntry(entry);
      -        });
      -    ASSERT_EQ(checkpointEntries.size(), 1);
      -    EXPECT_EQ(checkpointEntries.front().getOpType(), repl::OpTypeEnum::kCommand);
      -    EXPECT_EQ(checkpointEntries.front().getCommandType(), repl::CommandTypeEnum::kApplyOps);
      +    {
      +        insertUserDoc(BSON("_id" << 0 << "x" << 0));
      +        const OplogScanResult batch{
      +            .deltas = {{UUID::gen(),
      +                        ReplicatedMetadataDelta{
      +                            .metadata = {.sizeCount =
      +                                             CollectionSizeCount{.size = 30, .count = 2}}}}},
      +            .lastTimestamp = Timestamp(1, 2)};
      +        ASSERT_TRUE(flusher::flush(operationContext(), *sizeCountStore, *timestampStore, batch)
      +                        .has_value());
      +        flusher::writeWatermark(operationContext());
      +
      +        // Check isCheckpointApplyOpsEntry() correctly matches on checkpoint.
      +        const std::vector<repl::OplogEntry> checkpointEntries =
      +            getOplogEntriesMatching(operationContext(), [](const repl::OplogEntry& entry) {
      +                return isCheckpointApplyOpsEntry(entry);
      +            });
      +        ASSERT_EQ(checkpointEntries.size(), 1);
      +        EXPECT_EQ(checkpointEntries.front().getOpType(), repl::OpTypeEnum::kCommand);
      +        EXPECT_EQ(checkpointEntries.front().getCommandType(), repl::CommandTypeEnum::kApplyOps);
      +    }     // Check isCheckpointApplyOpsEntry() does not match on watermark.
           const std::vector<repl::OplogEntry> watermarkEntries =
      
      

       

       

            Assignee:
            Cedric Sirianni
            Reporter:
            Cedric Sirianni
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: