Repository navigation
[Store] Extract per-object metadata and runtime state headers from MasterService - #4127
Conversation
There was a problem hiding this comment.
🟢 Approval recommended
The refactor is fully reviewed; the remaining documentation nit is non-blocking.
Pull request overview
Extracts per-object metadata and runtime-state types from MasterService into standalone headers without behavior changes.
Changes:
- Adds
object_metadata.handobject_runtime_state.h. - Updates
master_service.h, implementation, and tests to use extracted types. - Preserves existing declarations and locking behavior.
File summaries
| File | Summary |
|---|---|
mooncake-store/tests/promotion_on_hit_test.cpp |
Updates promotion result type references. |
mooncake-store/tests/master_service_test_fixture.h |
Updates metadata type references. |
mooncake-store/tests/ha/master_service_ha_test.cpp |
Updates promotion task type references. |
mooncake-store/src/master_service.cpp |
Updates extracted type references. |
mooncake-store/include/object_runtime_state.h |
Defines standalone runtime-state types. |
mooncake-store/include/object_metadata.h |
Defines standalone metadata types; module documentation has a minor locking clarification nit. |
mooncake-store/include/master_service.h |
Includes the new headers and removes moved declarations. |
Review details
Suppressed comments (1)
mooncake-store/include/object_metadata.h:9
- This module comment says
ObjectMetadatacarries no lock, but the type still declaresmutable SpinLock lockbelow (line 105), which protects the lease and soft-pin fields. Please distinguish the absence of an object-level ownership lock from this internal lock so the extraction does not document a locking contract that contradicts the implementation.
// state and the tenant quota ledger. It carries no lock of its own: whoever
// owns the envelope decides how it is guarded.
- Files reviewed: 7/7 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
|
||
| struct ResolvedSoftPinRequest { | ||
| SoftPinAction action{SoftPinAction::PRESERVE}; | ||
| uint64_t ttl_ms{0}; |
There was a problem hiding this comment.
Use std::chrono::millisecond
|
|
||
| struct PendingSoftPinAction { | ||
| SoftPinAction action{SoftPinAction::PRESERVE}; | ||
| uint64_t ttl_ms{0}; |
…aders Move MasterService::ObjectMetadata, ResolvedSoftPinRequest and the per-key runtime task records (DynamicReplicaPending, ReplicationTask, OffloadingTask, PromotionQueueResult, PromotionCandidateReason, PromotionCandidate, PromotionTask) to namespace scope in their own headers. This is a relocation: the moved text is unchanged apart from the four-space nesting indent. No type is used with a MasterService:: qualification anywhere in the tree, and the seven members the move drops later (EraseReplica/EraseReplicaByID/GetMemReplicaCount/GetNoFReplicaCount/ HasMemReplica/HasNoFReplica/NeedsReadLeaseRefresh) have no callers, so the extraction is self-contained. The runtime-state records are named for their responsibility rather than for their consumer, per review feedback on the module boundary.
4814bcf to
b918c9b
Compare
| struct PendingSoftPinAction { | ||
| SoftPinAction action{SoftPinAction::PRESERVE}; | ||
| std::chrono::milliseconds ttl{0}; | ||
| std::vector<ReplicaID> eligible_replica_ids; |
There was a problem hiding this comment.
Using std::unordered_set to manage those replica ids
The pending soft-pin action only ever asks whether a replica id belongs to the write being committed, never in what order or with duplicates, so an unordered_set says that directly. Both queries become O(1) instead of a linear scan over a vector: PendingSoftPinOwnsReplica runs per replica of a PutEnd walk, and ClearPendingSoftPinIfNoViableReplica runs per replica of the object. The two construction sites (PutStart and the UpsertStart replacement path) build the set instead of a vector.
Picks up 1a0c0a4 so the branch builds against current main.
1d7a189 made DeleteRange a pure virtual on HaKvBackend and updated the other test backends, but missed this one, so batch_oplog_snapshot_gc_test does not compile: FakeBackend is abstract and the test cannot instantiate it. Return INVALID_PARAMS, which is what the interface asks an unsupported backend to do and what the sibling fakes return. The GC path under test never deletes through this backend.
Resolves the collision with kvcache-ai#4135, which added MasterServiceTestPeer as the single test access boundary and aliased the per-object types off MasterService. Three of those aliases (ObjectMetadata, PromotionQueueResult, PromotionTask) have pointed at namespace-scope types since the extraction, so the peer now names them directly; the two test files that reach these types through the peer keep upstream's spelling and the fixture keeps the chrono TTL signature.
|
Could you resolve the conflict? Thanks |
The alias target already says which namespace the type lives in.
rishabhsinha17
left a comment
There was a problem hiding this comment.
I reviewed #3822 and followed the split here. Read the full diff at 348108e against main. The extraction is faithful. object_runtime_state.h carries the per-key task records over unchanged, and object_metadata.h carries the envelope with only the two refinements Aionw asked for, the chrono ttl type and the unordered_set of eligible replica ids. Both preserve behavior. Eligible replica ids are only ever membership tested and are unique within a write, and the rewritten ComputeSoftPinDeadline keeps the saturation contract, since ResolveSoftPinRequest now does the only uint64 to milliseconds conversion and does it behind the max_kv_soft_pin_ttl_ guard. One boundary did move. A ttl between int64 max ms and uint64 max used to saturate to a permanent pin and would now wrap negative, but hitting that takes an operator raising max_kv_soft_pin_ttl past roughly 292 million years, so I would leave it.
Nothing from the #3822 review is lost in this slice. This split leaves TenantScopedRemoveAllSuppressesClearOnRace and the rest of the suppression coverage in master_service_test.cpp alone, and the fixture change is only the deadline helper signature. My two open asks there, the suppression race coverage and a TEST_F for the rebind helper, belong to the tenant-scoped split and I will re-raise them on that PR.
Restore the MasterService class body that the merge resolution truncated, place PromotionTask::from_prefetch in the upstream object_runtime_state.h layout (kvcache-ai#4127), close the DummyClient batchProbeKey brace, and restore the buffer_pool.py lines the smoke suite imports. Also drop a duplicated MasterSnapshotManager friend line and an empty namespace left by the merge.
Adapt to upstream changes since the PR opened: - MasterService header split (kvcache-ai#4127): PromotionTask::from_prefetch moves to object_runtime_state.h; friend list follows the MasterServiceTestPeer form (kvcache-ai#4135) plus PrefetchTaskMasterTest. - probeKey/BatchProbeKey RPCs (kvcache-ai#3801) coexist with ExistOptions. - Python unified-package layout (kvcache-ai#3586): keep buffer_pool.py at its pre-existing path; migration is a separate follow-up.
Adapt to upstream changes since the PR opened: - MasterService header split (kvcache-ai#4127): PromotionTask::from_prefetch moves to object_runtime_state.h; friend list follows the MasterServiceTestPeer form (kvcache-ai#4135), plus PrefetchTaskMasterTest. - probeKey/BatchProbeKey RPCs (kvcache-ai#3801) coexist with ExistOptions. - Python unified-package layout (kvcache-ai#3586): keep buffer_pool.py at its pre-existing path; migration is a separate follow-up. - Design doc moved to docs/source/design/store/ssd-prefetch.md per the kvcache-ai#4196 module-grouped layout; drop stale toctree entries for moved docs.
Description
Moves the per-object metadata envelope and the per-key runtime state records out of
MasterServiceinto their own headers:mooncake-store/include/object_metadata.hResolvedSoftPinRequest,ObjectMetadata(with its nestedSoftPinEvaluation,PendingSoftPinAction,DynamicReplicaRecord)mooncake-store/include/object_runtime_state.hDynamicReplicaPending,ReplicationTask,OffloadingTask,PromotionQueueResult,PromotionCandidateReason,PromotionCandidate,PromotionTaskThese are per-object types, but they are declared inside the service that owns the metadata shard tables. Anything that needs one of them pulls in the whole service header and the quota/HA machinery behind it, and the object's own state cannot be moved out of the shard tables while its declarations live there. RFC #3670 moves metadata ownership from shards to tenants and narrows the mutation boundary from one shard lock to one object lock; separating the types is the step that makes that move expressible.
object_runtime_state.hnames the records after what they are rather than after their consumer.No behavior change. The declarations are unchanged apart from the dedent and the
clang-formatre-wrap that follow from leaving their old nesting, and theMasterService::qualification dropped where these types are named.Changes on top of the move:
ResolvedSoftPinRequest::ttl_msandPendingSoftPinAction::ttl_msbecomestd::chrono::milliseconds ttl, andComputeSoftPinDeadlinetakes that duration rather than a rawuint64_t. The rep-range guard it carried is unreachable once the parameter is a duration, so it is gone; the config-facinguint64_tvalues are converted at the boundary inResolveSoftPinRequest.PendingSoftPinAction::eligible_replica_idsis astd::unordered_set<ReplicaID>. The only question asked of it is membership, once per replica on two paths, so the set states that directly and neither query scans.object_metadata.hmodule comment now says what actually guards the envelope: it has no ownership lock, and the internal spin lock it does carry covers onlylease_andsoft_pin_timeout.Module
mooncake-store)Type of Change
How Has This Been Tested?
Build and the store regression set on a 256-core Ubuntu box, Debug + Ninja,
USE_ETCD=ON, GNU 11, run over the same subset onupstream/mainand on this branch so the two can be compared.Test commands:
Test results:
upstream/main— same subset, same build, same result.ObjectMetadatastill carries no ownership lock; its internalSpinLockand theGUARDED_BYannotations are unchanged.clang-format --dry-runreports no new violations on the files this PR touches.Checklist
./scripts/code_format.shAI Assistance Disclosure