# Changelog
## 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