TopicSubscriptions

The subscriptions of one node that read another context's published topic: the runtime of a log's subscriptions over the topic instead, so they keep the semantics of the log's (a shared tail per partition, lanes per aggregate, a checkpoint per subscription and partition at the contiguous low watermark, parking in the ledger), with no Kafka consumer group:

  • Assignment: the topic's partitions are leased in the lease group (service, "topic:<topic>") (LeaseGroup.topic) and spread over the service's nodes by HRW, by the same PartitionOwnership as a context's log; the node reads the partitions it holds, each assigned to its consumer by hand.

  • Offsets: each subscription's checkpoint per partition is in checkpoints, under the lease group's name: the offset to read next, saved once every record before it is done with. Nothing is committed to Kafka.

  • One reader per (node, topic): one SubscriptionRuntime reads each held partition once and fans its records out to every subscription of the topic.

  • Parking: an aggregate parked by one of them is recorded in ledger with the offset of its record; retrying it re-scans that partition from there for the records keyed by the aggregate (TopicEntries); an entry whose offset the topic no longer retains is marked unrecoverable and can only be skipped.

  • Delivery is at least once: a handover or a restart hands over again what is past the saved checkpoint, and a subscription drops a copy of a version it remembers handling (StateEventRecord.id).

start returns at once: the partitions are read once the topic has some, which it may not have yet when its publisher has not started, and the lease group is joined then (awaitStarted). stop hands the held partitions off, saving the checkpoints, and leaves the group.

Partitions added while it reads: every partitionRefresh it reads the topic's partitions again, and when there are more, hands the held ones off, saving their checkpoints, and joins the group again over all of them, so the new ones are read too, from their beginning. HRW gives each partition the same owner whatever their number, so the partitions held before are held again. A topic's partitions are never fewer.

Constructors

Link copied to clipboard
constructor(service: String, topic: String, node: String, addressOf: () -> String, source: PartitionedSource, checkpoints: CheckpointStore, leases: LeaseStore, ledger: FailureLedger, subscriptions: Collection<Subscription>, options: SubscriptionOptions = SubscriptionOptions(), cluster: ClusterOptions = ClusterOptions(), clock: Clock = Clock.systemUTC(), context: CoroutineContext = Dispatchers.Default, signals: SignalSender = SignalSender.NONE, notifier: ParkedNotifier = ParkedNotifier.NONE, partitionRefresh: Duration = Duration.INFINITE, observer: Observer = Observer.NONE, classification: FailureClassification = RuntimeFailures.DEFAULT, membership: ServiceMembership? = null, catchUps: Semaphore? = null, fatals: NodeFatals = NodeFatals.NONE)

Types

Link copied to clipboard

Where a node is in joining a topic's lease group (joinState).

Properties

Link copied to clipboard

The lease group of the topic's partitions: (service, "topic:<topic>").

Link copied to clipboard

The attempts to join that failed since the node last joined: to read the topic's partitions (none yet counts) or to join its lease group; zero once it reads them.

Link copied to clipboard

Where this node is in joining the topic's lease group, for a health model to report: a node JoinState.JOINING for long reads nothing of the topic. See joinFailures for why it waits.

Link copied to clipboard

Why the last attempt to join failed, while joinFailures is not zero.

Link copied to clipboard
Link copied to clipboard

This node's ownership of the topic's partitions, once started.

Link copied to clipboard

The runtime reading the partitions, once started.

Link copied to clipboard
Link copied to clipboard
Link copied to clipboard

Functions

Link copied to clipboard
suspend fun awaitStarted()

Waits until the topic's partitions are known and the lease group joined.

Link copied to clipboard
open override fun paused(): List<PausedPartition>

The partitions of the topic its subscriptions have paused on a systemic failure here.

Link copied to clipboard
suspend fun retry(subscription: String, ref: AggregateRef): Boolean

Handles subscription's parked aggregate ref again by re-scanning its partition from the offset parked (SubscriptionRuntime.retry); this node must hold the partition. False when it was not parked, failed again, or is unrecoverable.

Link copied to clipboard
suspend fun skip(subscription: String, ref: AggregateRef): Boolean

Resolves subscription's parked aggregate ref without handling what was skipped.

Link copied to clipboard
suspend fun start()

Joins the lease group in the background, as soon as the topic has partitions: reads them (retrying while it has none), then acquires this node's share and reads it, retrying until it joins: a join that fails, the lease store unreachable say, is undone and tried again after SubscriptionOptions.readRetry's backoff, and joinState stays JoinState.JOINING meanwhile.

Link copied to clipboard
suspend fun stop()

Hands off the partitions held, saving every checkpoint, and leaves the group; stopping twice does nothing.

Link copied to clipboard

The partitions of the topic its subscriptions throttle on backpressure here.

Link copied to clipboard
open override fun toString(): String