@hackage / shibuya-kiroku-adapter

Kiroku event store adapter for the Shibuya queue processing framework

Latest0.4.0.0

Changelog

Changelog

Unreleased

0.4.0.0 — 2026-07-11

Breaking Changes
  • KirokuAdapterConfig and KirokuConsumerGroupConfig gain a queueCapacity field, defaulting to 16 in the smart constructors.
  • Requires shibuya-core >=0.8 && <0.9 (was >=0.7) and kiroku-store ^>=0.3.
Fixed
  • Adapter subscriptions now rely on Kiroku's default lossless PauseAndResume overflow policy instead of pinning fail-fast DropSubscription.
  • guardKirokuHandlerWith and guardKirokuHandler convert synchronous handler exceptions into finalized ack decisions so Kiroku workers are not abandoned mid-ack. kirokuConsumerGroupProcessors applies the default guard automatically.
  • Adapter.source now has regression coverage for EP-1's termination contract: clean shutdown ends the stream normally, while a worker crash is rethrown to the stream consumer.
  • kirokuConsumerGroupProcessors now throws InvalidConsumerGroup for non-positive group sizes before opening subscriptions, and cleans up already created member adapters if a later member fails during construction.
  • The package description and Haddocks describe the ack-coupled bridge instead of the obsolete no-op ack behavior.
Known Limitations
  • shibuya-core still needs upstream fixes for finalize-on-exception in its supervised processor and for propagating ingester stream failures from the supervised runner. The adapter-side guard is defensive and remains correct after those fixes land.

0.3.0.0 — 2026-06-05

Changed
  • Require shibuya-core >=0.7 && <0.8. Envelope now carries a headers :: Maybe Headers field; toEnvelope sets it to Nothing, because Kiroku events carry no ordered, raw broker headers. W3C trace context continues to be surfaced via traceContext from event metadata.

0.2.0.0 — 2026-05-31

Breaking Changes
Shibuya 0.6 and OpenTelemetry 1.0 semantics
  • The adapter now targets shibuya-core >=0.6 && <0.7 and hs-opentelemetry-api ^>=1.0.
  • Envelope.attributes now also carries current OpenTelemetry messaging semantic-convention attributes for the Kiroku source: messaging.system = "kiroku" and messaging.destination.name set to the subscription name. These override Shibuya's framework defaults on the per-message process span while preserving the existing kiroku.* attributes.
Ack decisions now drive Kiroku checkpointing (plan 40)
  • The adapter bridges through kiroku-store's ack-coupled subscriptionAckStream: each event blocks the Kiroku worker until the Shibuya handler's AckDecision is finalized, so the decision drives Kiroku checkpointing per event. Previously AckRetry / AckDeadLetter were no-ops.
    • AckOk — checkpoint past the event.
    • AckRetry delay — redeliver the same event after delay, bounded by the subscription's retry policy, then dead-letter on exhaustion.
    • AckDeadLetter reason — record the event in kiroku.dead_letters (reason translated to a Kiroku-native DeadLetterReason) and advance past it.
    • AckHalt — cancels the subscription (unchanged).
  • The envelope attempt now reports the zero-based redelivery count.
  • Shibuya.Adapter.Kiroku.Convert exposes toIngestedAck (replacing toIngested), toKirokuResult, and toKirokuDeadLetterReason.
New Features
Kiroku identity on envelope attributes for end-to-end tracing (MasterPlan 6 EP-5)
  • Envelope.attributes (previously always empty) is now populated with the kiroku identity so it appears on Shibuya's per-message span: kiroku.subscription.name, kiroku.event.type, kiroku.event.global_position, and — for a consumer-group member — kiroku.consumer_group.member. Combined with kiroku-otel's native subscription spans, a single trace is followable from a kiroku subscription into Shibuya's processing; the keys match on both sides.
  • Shibuya.Adapter.Kiroku.Convert exposes KirokuEnvelopeAttrs; toEnvelope and toIngestedAck take it. kirokuAdapter derives the subscription name and member from its config, so the single-adapter and consumer-group paths are both covered. No shibuya-core change; the ack-handle logic and trace-context propagation are unchanged.
defaultKirokuAdapterConfig smart constructor
  • defaultKirokuAdapterConfig name target builds a KirokuAdapterConfig with recommended defaults (batch size 100, buffer 256, no consumer group, AllEventTypes, no selector); override individual fields with record-update or a generic-lens label (& #eventTypeFilter .~ …). Prefer it over a full record literal so a future field is inherited at its default automatically — mirrors defaultConsumerGroupConfig and kiroku-store's defaultSubscriptionConfig.
  • KirokuAdapterConfig and KirokuConsumerGroupConfig now derive Generic, enabling generic-lens label access/update of their fields.
Consumer groups as a single partitioned subscription (plan 42)
  • kirokuConsumerGroupProcessors — present a whole kiroku consumer group as one PartitionedInOrder unit: a single call yields N named QueueProcessors (one member adapter each, ProcessorId "<name>-member-<m>"), each pinned to (PartitionedInOrder, Serial). Replaces the manual mapM mkMemberAdapter [0..N-1] wiring.
  • KirokuConsumerGroupConfig + defaultConsumerGroupConfig — describe a whole group (subscription name, target, group size, batch size, buffer size, and a per-member Concurrency that must be Serial).
  • consumerGroupPolicy — map a requested per-member Concurrency onto the validated group policy (PartitionedInOrder, Serial), reusing Shibuya's own validatePolicy so Ahead/Async are rejected early with InvalidPolicyCombo before any subscription opens.
  • No shibuya-core changes: the helper only consumes existing exports.
Event-type filter and selector forwarding (plan 43)
  • KirokuAdapterConfig and KirokuConsumerGroupConfig gain an eventTypeFilter field (AllEventTypes / OnlyEventTypes (Set EventType), default AllEventTypes), forwarded into the underlying subscription so the adapter delivers only the chosen event types. Filtering is worker-side, ahead of the ack-coupled bridge, so a filtered-out event never reaches the Shibuya handler, is never retried or dead-lettered, and the checkpoint still advances past it. EventTypeFilter (..) is re-exported.
  • Both config records also gain an optional selector :: Maybe (RecordedEvent -> Bool) field (default Nothing) — the opaque escape hatch for filtering on a property the type set cannot express (payload, metadata, correlation ids). It composes with eventTypeFilter as a logical AND and is applied worker-side with the same no-stall / checkpoint-advances guarantee. For a consumer group the same predicate is applied to every member.

0.1.0.0 — 2026-05-23

New Features
  • Initial release.
  • kirokuAdapter — create a Shibuya Adapter es RecordedEvent from a Kiroku store handle and subscription configuration.
  • KirokuAdapterConfig — subscription name, target, batch size, and TBQueue buffer size.
  • Ack semantics: AckOk/AckRetry/AckDeadLetter are no-ops (checkpoint managed by Kiroku); AckHalt cancels the subscription.
  • Shibuya.Adapter.Kiroku.Convert — RecordedEvent to Envelope mapping.