Skip to content

Wire per-topic partial-messages SubOpts flags (step 1)#460

Draft
lucassaldanha wants to merge 4 commits intolibp2p:developfrom
lucassaldanha:feature/partial-messages-subopts-444
Draft

Wire per-topic partial-messages SubOpts flags (step 1)#460
lucassaldanha wants to merge 4 commits intolibp2p:developfrom
lucassaldanha:feature/partial-messages-subopts-444

Conversation

@lucassaldanha
Copy link
Copy Markdown
Collaborator

Summary

Step 1 of the gossipsub partial-messages extension under #435.

Plumbs SubOpts.requestsPartial / SubOpts.supportsSendingPartial through subscribe announcements in both directions, and tracks the per-peer-per-topic receive state. No routing behaviour changes yet — handler, RPC dispatch, publish, and routing rules are later steps.

Addresses #444.

Scope

  • AbstractRouter parses the flags on inbound SubOpts and applies the spec coercion supportsSendingPartial := requestsPartial || supportsSendingPartial. Flags are zeroed when subscribe=false.
  • New AbstractRouter.enqueueSubscribe(queue, topic) hook unifies outbound subscribe enqueueing so GossipRouter can attach per-topic flags in a single override (used by both subscribe() and the onPeerActive re-announce).
  • GossipRouter:
    • setTopicPartialFlags(topic, requestsPartial, supportsSendingPartial) — configures flags advertised for a locally-subscribed topic (router-level API; public Gossip / PubsubApi surface intentionally untouched until Step 2 / Expose application interface to use partial messages #446).
    • New PartialSubscriptionState field stores inbound flags per (topic, peer). Plain HashMap — single-threaded pubsub event loop invariant.
    • Cleanup on peer disconnect, local topic unsubscribe, and per-peer topic unsubscribe.
  • Outbound unsubscribe MUST NOT carry partial flags; enforced at the SubscriptionPart wire-build site.

Design reference: docs/partial-messages.md §4.5, §5, §6.1.

Out of scope (later steps)

Test plan

  • libp2p/src/test/kotlin/io/libp2p/pubsub/gossip/PartialSubscriptionStateTest.kt — 10 unit tests for the new state container (set/remove/disconnect/topic-gc semantics).
  • libp2p/src/test/kotlin/io/libp2p/pubsub/gossip/extensions/PartialSubscriptionWireTest.kt — 9 integration tests via TwoRoutersTest:
    • outbound: configured flags carried with send-side coercion; supportsSendingPartial-only; no flags when none configured; unsubscribe strips flags.
    • inbound: receive-side coercion; supportsSendingPartial-only stored verbatim; both-false leaves state empty; unsubscribe ignores flags and clears prior state; disconnect clears state; local unsubscribe clears state for that topic only.
  • ./gradlew :libp2p:test --tests "io.libp2p.pubsub.*" — all pubsub tests green (no regressions in GossipExtensionsMessageHandlingTest, GossipExtensionsStateTest, floodsub, etc.).
  • ./gradlew :libp2p:spotlessCheck — clean.

Stacking note

This PR stacks on #457 (design-doc-only). Until that merges, the diff here will show the docs/partial-messages.md commit as well; it will drop out after rebasing on develop post-#457.

Captures the MVP scope, jvm-libp2p/client responsibility boundary,
client-facing API, routing semantics, per-group lifecycle and DoS
caps, and the implementation plan for the gossipsub partial-messages
extension. Lands ahead of implementation so sub-issues of libp2p#435 can
reference a stable design anchor.
Step 1 of the partial-messages extension: plumb SubOpts.requestsPartial /
SubOpts.supportsSendingPartial through subscribe announcements in both
directions, and track the per-peer-per-topic receive state.

- AbstractRouter parses the flags with the spec-mandated coercion
  (supportsSendingPartial := requestsPartial || supportsSendingPartial)
  and zeroes them on subscribe=false.
- New enqueueSubscribe hook unifies outbound subscribe enqueueing so
  GossipRouter can attach per-topic flags in a single override.
- GossipRouter exposes setTopicPartialFlags(topic, ...) to configure
  flags advertised for a locally-subscribed topic, and stores inbound
  flags in a new PartialSubscriptionState (plain HashMap on the pubsub
  event loop). State is cleaned on peer disconnect, topic unsubscribe,
  and per-peer unsubscribe.
- Outbound unsubscribe MUST NOT carry partial flags; enforced at the
  SubscriptionPart wire-build site.

No routing behaviour changes yet. See docs/partial-messages.md §4.5,
§5, §6.1 for context.
…t addSubscription overload

- `PartialSubscriptionWireTest`: route reads of `partialSubscriptionState`
  through `submitOnEventThread { ... }.join()`. The state container is
  not thread-safe; direct access from the JUnit thread races the event
  loop and can surface as `ConcurrentModificationException` or stale
  reads. Two helpers (`peerFlagsOnEventLoop`, `snapshotPartialStateOnEventLoop`)
  establish the happens-before barrier.

- `RpcPartsQueue`: remove the 2-arg `addSubscription(topic, status)`
  default overload. The remaining 4-arg abstract method is the single
  source of truth; `addSubscribe` / `addUnsubscribe` remain the
  convenience entry points.
- `PartialSubFlags.coerce(requestsPartial, supportsSendingPartial)`:
  single source of truth for the spec coercion rule
  `supportsSendingPartial := requestsPartial || supportsSendingPartial`.
  Used from `GossipRouter.setTopicPartialFlags` for the outbound side.
  AbstractRouter keeps the inline expression for the receive side to
  avoid a reverse layering dependency (pubsub -> gossip); a comment
  notes the rule is applied on both sides.

- `PartialSubscriptionState.setPeerFlags`: document that passing
  `PartialSubFlags.NONE` (or any equivalent all-false flags) is
  treated as a removal. Makes the set-sometimes-deletes invariant
  explicit for readers.

- `AbstractRouter.handleMessageSubscriptions`: add Kdoc now that the
  method is `protected open`. Documents the "call super" contract
  for overrides (GossipRouter relies on this to keep peersTopics and
  partialSubscriptionState in sync) and the flag-normalisation
  precondition.
@lucassaldanha lucassaldanha changed the title Wire per-topic partial-messages SubOpts flags (#444) [step 1] Wire per-topic partial-messages SubOpts flags (#444) Apr 27, 2026
@lucassaldanha lucassaldanha changed the title [step 1] Wire per-topic partial-messages SubOpts flags (#444) Wire per-topic partial-messages SubOpts flags (#444) (step 1) Apr 27, 2026
@lucassaldanha lucassaldanha changed the title Wire per-topic partial-messages SubOpts flags (#444) (step 1) Wire per-topic partial-messages SubOpts flags (step 1) Apr 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant