packages feed

shibuya-core-0.8.0.1: CHANGELOG.md

# Changelog

## 0.8.0.1 — 2026-07-04

### Other Changes

- Reduced per-message allocation on the `Async` and `Ahead` concurrency paths
  by widening the streamly dispatch buffer to `2 * n` (the thread bound stays
  at `n`). A buffer equal to the thread count throttled worker dispatch and
  caused dispatch churn that allocated up to +90% on the `Async`
  concurrency-levels benchmarks (EP-30). No API or behavior change.
- Documented the accepted ~126 bytes/message cost of the separate handler and
  finalizer exception frames that guarantee "always finalize" (EP-31).

## 0.8.0.0 — 2026-07-04

### Breaking Changes

- New application code should import the `Shibuya` umbrella module. It
  re-exports the stable app, handler, batch, retry, policy, metrics, and
  tracing surface. `Shibuya.Core` remains as a deprecated compatibility
  re-export for this release.
- Runner internals moved under `Shibuya.Internal.Runner.*` and carry no PVP
  stability guarantee. The public moves are:
  `Shibuya.Runner.Metrics` -> `Shibuya.Core.Metrics`;
  `Shibuya.Runner.{Master,Supervised,Batcher,BatchProcessor}` ->
  `Shibuya.Internal.Runner.*`; `Shibuya.Runner.{Halt,Ingester}` ->
  `Shibuya.Internal.Runner.*` as hidden implementation modules.
  `Shibuya.Runner.Serial` and `Shibuya.Runner.Processor` were deleted.
  `Shibuya.Prelude` is no longer exposed.
- `AppHandle` and `Master` are now opaque in public modules. Use
  `getAppMaster`, `getAppMetrics`, `waitApp`, `stopApp`, and
  `stopAppGracefully` instead of record fields. Metrics servers should import
  `Master`, `getAllMetricsIO`, and `getProcessorMetricsIO` from
  `Shibuya.App`.
- `runApp` now takes an `AppConfig` record and validates `inboxSize`.
  Invalid sizes return `Left (AppConfigInvalid (InvalidInboxSize n))`
  instead of crashing or stalling.

  ```haskell
  -- before
  runApp IgnoreFailures 100 processors

  -- after
  runApp defaultAppConfig processors

  -- custom strategy/size
  runApp defaultAppConfig {strategy = IgnoreFailures, inboxSize = 100} processors
  ```

- Handlers now receive `Message es msg` instead of `Ingested es msg`.
  Handlers that only use `.envelope` or `.lease` need a signature update;
  handlers can no longer call the adapter finalizer directly. The framework
  owns finalization and calls `AckHandle.finalize` after the handler returns
  or throws. Adapter finalizers should remain idempotent or phase-tracked.
- `BatchHandler` likewise receives `NonEmpty (Message es msg)` instead of
  `NonEmpty (Ingested es msg)`.
- Removed dead or misleading surface: `HandlerError.HandlerTimeout`,
  `RuntimeError.InboxOverflow`, `StreamStats.dropped`, `incDropped`,
  the always-zero `shibuya_messages_dropped_total` Prometheus metric, and
  `Shibuya.Telemetry.Config`.
- Renamed `Ordering` to `OrderingPolicy`, eliminating the need for
  `import Prelude hiding (Ordering)`. `runSupervised` also takes the ordering
  policy before `Concurrency`.
- `BatchingProcessor` now rejects `PartitionedInOrder` combined with `Ahead`
  or `Async`, because batches are scheduled by `BatchKey`, not
  `Envelope.partition`.
- Renamed `Shibuya.Stream.batchStream` to `chunksOf`.

### New Features

- Added `mkEnvelope :: MessageId -> msg -> Envelope msg`. It fills optional
  metadata with defaults; set optional fields with record update syntax. This
  is the recommended construction path because future optional `Envelope`
  fields can then be added without forcing adapter code to change, avoiding
  the kind of major bumps required by 0.5.0.0 and 0.7.0.0.
- Added `mkIngested :: Envelope msg -> AckHandle es -> Ingested es msg`.
- Added `Message es msg`, the read-only handler view containing envelope and
  optional lease.
- `PartitionedInOrder` with `Ahead` or `Async` is now enforced for
  single-message processors. Messages sharing an `Envelope.partition` key are
  processed and acknowledged in arrival order, distinct partitions run
  concurrently up to the configured bound, and messages with no partition key
  are unconstrained.

### Bug Fixes

- Handler exceptions on the single-message runner path now finalize the message
  with `AckRetry (RetryDelay 0)` using the same bounded finalizer retry helper
  as batch processing, so adapters observe a disposition instead of silently
  losing or stranding the delivery. Exhausted finalizer retry now halts the
  processor loudly with the failed message id.
- Batch accumulation failures, including exceptions from user-provided
  `batchKey` functions, now fail the processor loudly instead of letting the
  batcher consumer die while the processor reports clean completion.
- Batch processing now isolates `AckHalt`: batches already emitted after a halt
  no longer re-enter the user batch handler, and their messages are finalized
  with `AckRetry (RetryDelay 0)` instead of being left unacknowledged.
- The keyed batch scheduler now keeps its pending queue bounded and owns its
  reader and worker threads with structured cleanup, preventing unbounded pulls
  under slow handlers and preventing finalization after forced shutdown returns.

### Other Changes

- Corrected `Ahead` documentation. It preserves stream-yield order only;
  handler execution and acknowledgement may complete in any order.
- `TraceHeaders` remains a type alias with the same representation as
  `Headers`; its docs now clarify that it is only the parsed W3C trace-context
  projection, while `Headers` is the complete broker header set.
- `shibuya-pgmq-adapter` and `shibuya-kafka-adapter` should migrate envelope
  construction to `mkEnvelope` in their next releases.
- Removed unused dependencies from `shibuya-core`: `effectful-core`,
  `generic-lens`, `lens`, `uuid`, and `vector`. Internal unlift imports now use
  the stable top-level `Effectful` exports.

## 0.7.1.0 — 2026-06-15

### Bug Fixes

- Supervised processors now observe their ingester async after draining
  already-ingested messages. If the source dies with an exception, the
  processor is marked `Failed`, its `done` flag is set, and the exception is
  rethrown to the supervisor instead of being reported as a clean stream
  completion.

## 0.7.0.0 — 2026-06-05

### Breaking Changes

- `Envelope` gained a `headers :: !(Maybe Headers)` field carrying every
  message header the source broker delivered, in order and including
  duplicates. Direct constructions of `Envelope` must add the field.
  `Nothing` means the adapter does not surface headers; `Just []` means
  it does and the message had none. The new `Headers` type alias
  (`[(ByteString, ByteString)]`) is exported from `Shibuya.Core` and
  `Shibuya.Core.Types`. The W3C trace headers continue to appear in
  `traceContext` as before; they now also appear verbatim in `headers`.

## 0.6.0.0 — 2026-05-31

### Breaking Changes

- OpenTelemetry messaging spans now emit `messaging.operation.type =
  "process"` instead of the deprecated `messaging.operation = "process"`
  wire key. The Haskell constant `attrMessagingOperation` keeps the same
  name and now resolves to the current semantic-conventions key, so source
  imports continue to compile. Dashboards, alerts, and trace queries that
  filter on `messaging.operation` must be updated to
  `messaging.operation.type`.

### Other Changes

- Upgrade OpenTelemetry dependencies to the 1.0 ecosystem:
  `hs-opentelemetry-api ^>= 1.0`,
  `hs-opentelemetry-propagator-w3c ^>= 1.0`, and test-only
  `hs-opentelemetry-exporter-in-memory ^>= 1.0`.
- Move `hs-opentelemetry-semantic-conventions` to the latest Haskell
  generated package available with the 1.0 release, `^>= 1.40`, and source
  Shibuya's generic messaging keys from its typed exports.

## 0.5.0.0 — 2026-05-05

### Breaking Changes

- `Envelope` gained an `attributes :: !(HashMap Text Attribute)` field
  carrying adapter-supplied OpenTelemetry attributes for the per-message
  processing span. Direct constructions of `Envelope` must add the
  field; pass `Data.HashMap.Strict.empty` when the adapter has nothing
  to contribute (the common case). `Envelope`'s `NFData` instance is
  now hand-written rather than derived (because `Attribute` from
  `hs-opentelemetry-api` does not ship `NFData`); the strictness shape
  is unchanged for every other field.

### New Features

- `Shibuya.Runner.Supervised`'s `processOne` now applies
  `envelope.attributes` to its Consumer-kind span after setting the
  framework-default `messaging.*` attributes, so adapter-supplied
  keys override framework defaults of the same name. This lets
  broker-aware adapters (Kafka in particular) emit typed attributes
  (`messaging.kafka.destination.partition`,
  `messaging.kafka.message.offset`) and override the
  `messaging.system` default — without opening a second span. The
  per-record `Shibuya.Adapter.Kafka.Tracing.traced` wrapper that
  previously bolted these on can now be removed; see the audit
  document `docs/plans/9-otel-audit-findings.md` (Finding F1, P0)
  for the full motivation.
- `Shibuya.Telemetry.Propagation.currentTraceHeaders ::
  (Tracing :> es, IOE :> es) => Eff es (Maybe TraceHeaders)` looks
  up the currently-active OTel span (via thread-local context) and
  encodes its trace context as W3C headers, ready for an adapter
  to attach to an outgoing message. Returns `Nothing` when tracing
  is disabled or there is no active span. The intended call sites
  are adapter-side DLQ writes (so the failing-consumer's trace
  links to the resulting DLQ message) and ad-hoc producer paths.
  See the audit document `docs/plans/9-otel-audit-findings.md`
  (Findings F3 and F5).

## 0.4.0.0 — 2026-04-29

### Breaking Changes

- `Envelope` gained an `attempt :: !(Maybe Attempt)` field carrying the
  adapter's delivery counter (zero-indexed; `Nothing` if unknown). Direct
  constructions of `Envelope` must add the field. The new `Attempt`
  newtype is exported from `Shibuya.Core` and `Shibuya.Core.Types`.

### New Features

- New module `Shibuya.Core.Retry` providing `BackoffPolicy`, `Jitter`
  (`NoJitter`, `FullJitter`, `EqualJitter`), `defaultBackoffPolicy`, the
  pure evaluator `exponentialBackoffPure`, the effectful
  `exponentialBackoff`, and the handler convenience `retryWithBackoff`.
  Handlers can now compute exponentially-growing, jittered retry delays
  with a single call: `retryWithBackoff defaultBackoffPolicy
  ingested.envelope`. Pulls in `random ^>=1.2` as a new build-depends
  (already a transitive dep — ships with GHC). See the module haddock and
  the new `RetrySpec` test for usage patterns.
- A runnable end-to-end demonstration of the new API lives in the
  sibling [`shibuya-pgmq-adapter`](https://github.com/shinzui/shibuya-pgmq-adapter)
  repo at `shibuya-pgmq-example/`, exposed via the `backoff-demo`
  subcommand of `shibuya-pgmq-consumer`. The plan
  `docs/plans/8-demonstrate-backoff-end-to-end.md` records setup
  instructions and captured transcripts.

## 0.3.0.0 — 2026-04-24

Version bumped to track the shared release version. No user-visible
changes to `shibuya-core` itself.

## 0.2.0.0 — 2026-04-22

### Breaking Changes

- `Shibuya.Telemetry.Semantic`: rename `processMessageSpanName :: Text` to
  `processSpanName :: Text -> Text`. The span name is now built from the
  destination (processor id), yielding e.g. `"shibuya-consumer process"`, in
  line with the OpenTelemetry messaging-spans recommendation.
- `Shibuya.Telemetry.Semantic`: remove `attrMessagingDestinationPartitionId`
  (replaced by the Shibuya-specific `attrShibuyaPartition`).
- `Shibuya.Telemetry.Semantic`: remove `eventHandlerException`.

### New Features

- `Shibuya.Telemetry.Semantic`: add `attrMessagingOperation` and
  `attrShibuyaPartition` attribute keys. Messaging attribute keys are now
  sourced from the typed `AttributeKey` values exported by
  `OpenTelemetry.SemanticConventions`, so upstream renames surface as
  compile errors rather than silent wire-format drift.
- `Shibuya.Core.Types`: add `NFData` instances for `MessageId`, `Cursor`,
  and `Envelope a` (when `a` itself has an `NFData` instance). Benchmark
  authors no longer need to declare these as orphans.

## 0.1.0.0 — 2026-02-24

Initial release.

### New Features

- Multi-queue processing with `runApp` and `QueueProcessor` API
- Backpressure via bounded inbox
- AckHalt support to stop processing on halt decision
- Serial, Ahead, and Async concurrent processing modes
- Policy validation enforcement (StrictInOrder requires Serial)
- Graceful shutdown with configurable drain timeout
- NQE-based supervision via Master/Supervisor
- OpenTelemetry tracing integration with W3C trace context propagation
- Mock adapter for testing

### Bug Fixes

- Fix race conditions and incomplete cleanup in runner
- Fix data races in concurrent test handlers using atomicModifyIORef'

### Other Changes

- Consolidate error handling with unified error types
- Define own SupervisionStrategy type to decouple from NQE
- Use registerDelay for cleaner timeout handling
- Replace polling with STM blocking in waitApp