Skip to content

feat: transparent retry deduplication#201

Merged
Migorithm merged 41 commits into
mainfrom
feat/182-idempotent-write
Jul 24, 2026
Merged

feat: transparent retry deduplication#201
Migorithm merged 41 commits into
mainfrom
feat/182-idempotent-write

Conversation

@Migorithm

@Migorithm Migorithm commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

closes #182

1. Architecture & Protocol Layering (d10_transparent_retry_deduplication.md)

  • Control Plane Authority: Manages session lifecycle (opening sessions, lease renewal, incarnation fencing, session
    eviction) via metadata Raft state machine.
  • Data Plane Execution: Range data leaders validate request identity ((producer_id, incarnation, range_id, sequence,
    payload_digest)), enforce sequence continuity, deduplicate retries using a bounded result ring, and persist ProducerAppendIdentity in WAL entry headers.

2. Data Plane Deduplication & Auxiliary State

  • ProducerTracker & ProducerSession (): Implements range-level producer state machine tracking contiguous expected sequences, windowed result deduplication, and fencing validation.
  • State Machine & Recovery Integration (state.rs, ): Integrates ProducerTracker into segment store recovery, auxiliary
    snapshots, and periodic checkpointing.
  • Record Headers: Appends include ProducerAppendIdentity within entry headers, replicating session identity to followers for replica consistency.

3. Control Plane Session Authority

  • Session Management (producer_sessions.rs): Added session tracking, incarnation increments for fencing older producer instances, and eviction of expired sessions.
  • Unified Protocol Error Mapping (error.rs): Flattened and unified protocol errors into ServerError for explicit error propagation across controller and data nodes.

4. Client SDK & Producer Session Manager

  • Client Session Tracking (session.rs): Added ProducerSessionManager to handle broker session negotiation, background lease heartbeats, per-range sequence generation, and transparent retries.
  • Optimized Routing Cache (routing.rs): Optimized TopicRouting lookups using O(log N) binary search over sorted writable_ranges, while preserving deterministic keyspace ordering for active_range_ids.

Migorithm added 30 commits July 21, 2026 22:29
We have completed the refactoring of the wire protocol to flatten responses directly into ClientResponse::Ok(ClientSuccess) and ClientResponse::Err(ServerError) across the codebase:

1. Wire Protocol Structure:
- Removed ControlPlaneResponse, DataPlaneResponse, and AdminResponse sub-protocol wrapper enums.
- Updated ClientSuccess in mod.rs to directly contain all 16 success variants (TopicCreated, TopicDeleted, TopicList, TopicDetail, ConsumerGroupAssignment, ConsumerGroupLeft, ProducerSessionOpened, Produced, Fetched, RangeOffset, ConsumerOffsetCommitted, ConsumerOffset, ClusterInfo, TopicStats, ShardInfo, ShardLeader).
- Standardized ClientResponse to consist of:
  - ClientResponse::Ok(ClientSuccess)
  - ClientResponse::Err(ServerError)
  - ClientResponse::Stop

2. Server Controller Integration:
- Refactored handler methods in controller.rs (handle_create_topic, handle_delete_topic, handle_produce, handle_fetch, etc.) to return Result<ClientSuccess, ServerError>.
3. Client SDK & Integration Tests
refactored FetchResult and ListOffsetsResult to leverage standard Result<..., ServerError> types.
Introduce ProducerTracker to manage producer session verification, sequence tracking, and append deduplication:

- Track session incarnation, expiration, and sequence frontiers in ProducerSession
- Enforce strict sequence continuity and detect sequence gaps or identity conflicts
- Maintain a sliding deduplication window (ProducerDeduplicationEntry) to handle idempotent retries
- Track in-flight appends to prevent concurrent duplicate processing
…ryStateManager

- Integrate ProducerTracker into AuxiliaryStateManager alongside consumer offsets
- Refactor DataPlane::handle_produce to delegate segment validation and staging to SegmentStore
- Rename SegmentTracker::stage_producer_entry to stage_entry
- Standardize producer_identity across ReplicationState and commit callbacks
… and domain range resolution

- Change ClientController handlers to return Result<ClientSuccess, ServerError> directly
- Map MetadataError into ServerError to unify control-plane error handling
- Encapsulate range routing (resolve_writable_range) and segment lookup (active_write_segment) into TopicMeta/RangeMeta
- Flatten ClientResponse into Ok(ClientSuccess) and Err(ServerError)
…ce tracking

- Add ClientProducerSessionManager and RangeSequences in session.rs for per-range sequence generation and topology tracking.
- Retain in-flight sequence counters during range retirement and handle session lease renewals safely.
- Consolidate transparent retry logic in producer flush for SessionExpired and Request InFlight errors.
- Add end-to-end SDK tests for producer deduplication.
@Migorithm Migorithm self-assigned this Jul 23, 2026
@Migorithm Migorithm added bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request feat labels Jul 23, 2026
During a FlappingPartition fault, a data write leader (node-1) experiences follower
  replication timeouts and requests a segment roll (RequestSegmentRoll). When the metadata
  state machine commits the roll, DataPlane::handle_segment_roll_committed (state.rs) replays
  uncommitted producer entries into the new successor segment and sets self.needs_flush =
  true.

  However, handle_segment_roll_committed was not scheduling a BatchFlushTimer with the ticker
  system. Without a scheduled timer (or a subsequent incoming client request), flush_batch()
  was never triggered for the replayed records. As a result, the replayed entries remained in
  dirty_segments, and the client's produce request was left stranded on reply_rx.await until
  timing out after 40 seconds.

  #### Fixes Applied

  1. Timer Scheduling on Segment Roll:
      • In state.rs, scheduled BatchFlushTimer::deadline() whenever
      handle_segment_roll_committed sets self.needs_flush = true. This ensures flush_batch()
      is promptly executed to write the WAL, trigger replication, and complete pending
      producer ACK channels for successor segments.
  2. Scenario Recovery Validation:
      • In scenario.rs, updated is_valid() so FlappingPartition and PartitionLeader scenarios
      require at least 15s of post-heal recovery budget before simulation_secs ends, ensuring
      full SWIM reconnect, Raft consensus catch-up, and produce ACK verification before
      simulation termination.
@Migorithm
Migorithm merged commit 0985e9f into main Jul 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request feat

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement durable producer idempotency across retries and failover

1 participant