SubscriptionRuntime

Runs the subscriptions of one subscription group over the partitions this node owns (–§3).

Which partitions those are is decided outside, by the partition leases (me.ahoo.wow.runtime.cluster.PartitionOwnership): passed to start, then moved one at a time with startPartition and stopPartition as the node acquires and hands off partitions. For each partition the runtime reads the log once and fans the entries out to every subscription (PartitionRunner); each subscription keeps its own checkpoint per partition, runs one aggregate's entries in version order and different aggregates in parallel, and parks an aggregate whose handler keeps failing (SubscriptionWorker).

Duplicates are possible above a checkpoint (an entry handled but not yet saved when the node stopped or crashed), never below it, so handlers are idempotent by (ref, version).

It takes part in waits: a subscription signals, through signals, the wait an entry carries when the wait's next hop is that subscription; and as the SubscriptionDirectory of its group it tells a wait which subscriptions there are, of what kind, and whether one has handled a stream.

The same runtime reads another context's published topic instead of the log (me.ahoo.wow.runtime.source.TopicSubscriptions): its partitions are leased the same way, its entries fanned out through one shared tail per partition, its checkpoints (the offset after the last record completed) kept in the same store, and its parked aggregates in the same ledger, each with the offset to re-scan from.

Constructors

Link copied to clipboard
constructor(group: String, log: EventLog, checkpoints: CheckpointStore, ledger: FailureLedger, subscriptions: Collection<Subscription> = emptyList(), options: SubscriptionOptions = SubscriptionOptions(), clock: Clock = Clock.systemUTC(), context: CoroutineContext = Dispatchers.Default, signals: SignalSender = SignalSender.NONE, notifier: ParkedNotifier = ParkedNotifier.NONE, observer: Observer = Observer.NONE, classification: FailureClassification = RuntimeFailures.DEFAULT, cutover: String? = null, catchUps: Semaphore? = null, fatals: NodeFatals = NodeFatals.NONE)

Properties

Link copied to clipboard
Link copied to clipboard

Whether the runtime is running.

Link copied to clipboard

The partitions the runtime is reading now.

Link copied to clipboard

The subscriptions registered, by their contexts and names, read from any thread.

Functions

Link copied to clipboard
suspend fun add(subscription: Subscription)

Registers subscription. On a running runtime it starts at once in every partition: it catches up from its checkpoint (or as Subscription.startFrom says) on its own read, then joins the shared tail.

Link copied to clipboard
open override fun covers(subscription: String, type: AggregateType): Boolean

Whether subscription's filter takes streams of type: its context, and its aggregates when it names any.

Link copied to clipboard
open suspend override fun hasHandled(subscription: String, stream: EventStreamRecord): Boolean

Whether subscription is past stream for good: its progress in the stream's partition (the running worker's watermark, else the saved checkpoint) is at or past the stream's position, and the stream's aggregate is not parked.

Link copied to clipboard
open override fun kindOf(context: String, subscription: String): FunctionKind?

The kind of subscription in context, or null when it is not known.

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

The partitions this runtime's subscriptions have paused on a systemic failure, each a subscription in a partition this node runs; empty while the runtime is stopped.

Link copied to clipboard

Where each subscription stands in each partition this runtime runs on this node: its watermark, the sequence up to which every entry is complete. Against the source's head it is how far a subscription, a rebuild under a new name among them, has come. Empty while the runtime is stopped.

Link copied to clipboard
suspend fun progress(subscription: String, partitions: Int): Long?

How far subscription has come over all partitions of its source: the sum, over each partition, of its progress there. In a partition this node runs, the worker's SubscriptionWorker.progress, which grows the moment an entry completes, even above an entry still running; in the others, the saved checkpoint (else 0), which another node moves forward. The sum changes when the subscription completed an entry: the snapshot subscription's is the validator of the cached counts, so a count after a write this node completed sees the write. Null when subscription is not registered.

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

Handles subscription's parked aggregate ref again from its parked version, then resolves its ledger entry; the aggregate's new entries are handled after it, in version order (see SubscriptionWorker.retry). The runtime must be running the aggregate's partition.

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

Whether the runtime runs subscription in ref's partition here now: retry and skip act on the aggregate at once. Otherwise its owner is another node, which takes an operator's request from the ledger.

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

Resolves subscription's parked aggregate ref without handling what was skipped; its new entries are handled from now on.

Link copied to clipboard
suspend fun start(partitions: Set<Int> = emptySet())

Starts reading partitions, each subscription from its checkpoint; more can be started later.

Link copied to clipboard
suspend fun startPartition(partition: Int, reads: Job? = null)

Starts reading partition on the running runtime, each subscription from its checkpoint: the node has just acquired it. Nothing happens when it is read already; a start of it already running is waited for.

Link copied to clipboard
suspend fun stop()

Stops reading, waits at most SubscriptionOptions.stopTimeout for the entries in flight, abandons the rest, and saves every checkpoint. An abandoned entry is above the saved checkpoint and is handled after a restart.

Link copied to clipboard
suspend fun stopPartition(partition: Int)

Stops reading partition as stop does for all of them: waits at most SubscriptionOptions.stopTimeout for its entries in flight and saves its checkpoints, so the node can hand the partition off. The other partitions keep running. Nothing happens when it is not read; a start of it running is waited for first.

Link copied to clipboard

The partitions this runtime's subscriptions throttle on backpressure, each a subscription in a partition this node runs; empty while the runtime is stopped.