Releases: shinzui/kiroku
Release list
kiroku-store v0.3.0.1
kiroku-store v0.3.0.1
Hackage: https://hackage.haskell.org/package/kiroku-store-0.3.0.1
What's Changed
Bug Fixes
- A failure raised inside an opaque
runTransactionbody now preserves its
SQLSTATE and server message. Anything that was not astream_events_pkey
duplicate previously went through the append-shaped mapper with a
<transaction>sentinel stream, so e.g. a foreign-key violation surfaced as
StreamNotFound (StreamName "<transaction>")and lost the real diagnostics.
Such failures now map through the generic mapper — the foreign-key case above
becomesUnexpectedServerError "23503"with the server's message intact.
Duplicate-event mapping is unchanged.
kiroku-store-migrations v0.3.0.0
kiroku-store-migrations v0.3.0.0
Hackage: https://hackage.haskell.org/package/kiroku-store-migrations-0.3.0.0
What's Changed
Breaking Changes
- Upgraded
pg-migrateto 1.1.0.0.kiroku-store-migrate checknow takes the
manifest as--manifest PATHinstead of a positional argument, matching
new --manifest.
New Features
kiroku-store-migrate upandrepairaccept explicit--waitand
--no-statement-timeoutoverrides; omitting an execution flag now preserves
the application's configured runner settings instead of discarding them.- Successful migration, repair, and history-import runs are no longer replaced
by an error when advisory unlock or statement-timeout restoration fails; the
durable report is preserved and the cleanup observation attached to it.
Fixes
- Adding or removing a migration SQL file without listing it in the manifest no
longer silently reuses a stale compile-time embedding: the embedding module now
forces GHC to revalidate manifest membership on every build it runs.
shibuya-kiroku-adapter v0.4.0.0
shibuya-kiroku-adapter v0.4.0.0
Hackage: https://hackage.haskell.org/package/shibuya-kiroku-adapter-0.4.0.0
What's Changed
Breaking Changes
KirokuAdapterConfigandKirokuConsumerGroupConfiggain a
queueCapacityfield, defaulting to 16 in the smart constructors.- Requires
shibuya-core >=0.8 && <0.9(was>=0.7) andkiroku-store ^>=0.3.
Fixed
- Adapter subscriptions now rely on Kiroku's default lossless
PauseAndResumeoverflow policy instead of pinning fail-fast
DropSubscription. guardKirokuHandlerWithandguardKirokuHandlerconvert synchronous handler
exceptions into finalized ack decisions so Kiroku workers are not abandoned
mid-ack.kirokuConsumerGroupProcessorsapplies the default guard
automatically.Adapter.sourcenow 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.kirokuConsumerGroupProcessorsnow throwsInvalidConsumerGroupfor
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-corestill 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.
kiroku-store v0.3.0.0
kiroku-store v0.3.0.0
Hackage: https://hackage.haskell.org/package/kiroku-store-0.3.0.0
What's Changed
This release requires migrations 0003–0007 from kiroku-store-migrations.
Breaking Changes
- Backward reads now paginate.
readStreamBackwardandreadAllBackwardtreat a
nonzero cursor as an exclusive upper bound, so a page returns events older
than the cursor instead of newer ones. The interpreter maps the caller cursor
0tomaxBound, soStreamVersion 0/GlobalPosition 0still means "start
from the latest event" (versions and positions start at 1, so the sentinel can
never collide with a real value). Previously a nonzero cursor read in the wrong
direction, which made backward pagination impossible: feeding the last returned
version back in returned the same newest page again. Any caller passing a
nonzero backward cursor gets different results, and any mockStore
interpreter must mirror the0 -> maxBoundmapping. - Oversized stream names are rejected before any database work.
StoreError
gainsStreamNameTooLong !StreamName !Int(theIntis the offending UTF-8
byte length), andKiroku.Store.ErrorexportsmaxStreamNameBytes(512) and
validateStreamName :: StreamName -> Either StoreError (). Every
application-stream entry point —appendToStream,appendMultiStream,
linkToStream,softDeleteStream,hardDeleteStream,undeleteStream, and
therunTransactionAppending*wrappers — runs the same validation (reserved
$allplus the length bound) up front instead of only rejecting$all. The
bound exists because the append notification payload embeds the stream name and
PostgreSQL rejectspg_notifypayloads of 8,000 bytes or more; a name that
used to fail late as an opaque trigger error now fails immediately with a typed
error. Exhaustive matches onStoreErrormust handle the new constructor. - Publisher queues are created only for non-group
AllStreamssubscriptions.
Categorysubscriptions and all consumer-group members no longer register a
bounded queue with theEventPublisher; they are DB-driven in live mode. As a
consequenceSubscriptionConfig.queueCapacityand
SubscriptionConfig.overflowPolicyhave no effect for those targets, and they
can no longer be paused, dropped, or terminated withSubscriptionOverflowed.
In the exposedKiroku.Store.Subscription.Workermodule,runWorker's
signature changed from taking aTBQueue (Vector RecordedEvent)plus aTVar SubscriberStatusto taking a single new exported sumLiveSource (LiveFromPublisherQueue | LiveFromCategoryNotify | LiveFromGroupPolling),
fixed atsubscribetime from the config's(consumerGroup, target)shape. - Empty append batches are rejected.
StoreErrorgainsEmptyAppendBatch !StreamNameandAppendConflictgainsEmptyAppendBatchConflict !StreamName
(mapped byappendConflictToStoreError).appendToStreamwith[]now fails
withEmptyAppendBatchbefore any pool work; previously it took the global
$allrow lock, fired NOTIFY triggers, created an empty stream under
NoStream, and surfaced a misleadingWrongExpectedVersion/
StreamNotFound.appendMultiStream []is an explicit no-op returning[]
without a round trip, while a per-stream empty event list inside a non-empty op
list is rejected withEmptyAppendBatch. - Link failures are typed.
StoreErrorgainsEventAlreadyLinked !StreamName !(Maybe EventId)(the23505unique violation onstream_events_pkey,
carrying the offending event id when PostgreSQL's detail string is parseable)
andLinkSourceEventMissing !StreamName(the23502not-null violation raised
whenlinkToStreamreferences an event id that does not exist; the whole batch
rolls back). Both previously surfaced as an opaqueConnectionErrorcarrying a
stringifiedUsageError. StreamInfogains atruncateBefore :: !StreamVersionfield. Code
constructing or exhaustively matchingStreamInfomust be updated.- The
Storeeffect gainsSetStreamTruncateBefore :: StreamName -> StreamVersion -> Store m (Maybe StreamId)andEventExistsInStream :: StreamName -> EventId -> Store m Bool. Mock and test interpreters of the
Storeeffect must add arms for both. Kiroku.Store.SQL's hard-delete statements were resplit.
deleteStreamJunctionsStmtis removed, replaced bydeleteAllRowsForOriginStmt,
deleteJunctionsByEventIdsStmt,deleteStreamOwnJunctionsStmt, and
deleteDeadLettersForOrphanedEventsStmt, which the interpreter runs in sequence
beforedeleteOrphanedEventsStmt.- Checkpoint-load failures now fail the subscription loudly. A
UsageErrorwhile
reading a subscription's saved checkpoint at startup surfaces through the
handle'swaitasLeft eand the worker stops; it no longer falls back to
GlobalPosition 0and silently re-processes the whole history. subscriptionAckStreamandsubscriptionStreamreject a zero buffer, throwing
the newInvalidStreamBufferSizeexception (exported from
Kiroku.Store.Subscription.Stream) whenbufferSizeis0; a zero-capacity
TBQueuewould deadlock the bridge handler on its first delivery.- Duplicate events inside transaction bodies are typed.
runTransaction,
runTransactionNoRetry, and therunTransactionAppending*wrappers map a
23505violation onevents_pkey/stream_events_pkeytoDuplicateEvent (Just eid)(newmapTransactionUsageErrorinKiroku.Store.Error) instead of
the previous opaqueConnectionError.
New Features
- Logical truncate-before marker (close-the-book compaction).
Kiroku.Store.Lifecycle.setStreamTruncateBefore :: StreamName -> StreamVersion -> Eff es (Maybe StreamId)andclearStreamTruncateBefore :: StreamName -> Eff es (Maybe StreamId)set a per-stream cursor below which ordered per-stream
reads hide events.readStreamForward,readStreamBackward, and the paged
readStreamForwardStreamreturn only events whosestreamVersionis at or
above the marker; the$allglobal log,readCategory, subscriptions, and
existence probes are deliberately unaffected, so global history stays complete
and future projections can still be built from it. No events are deleted and
the operation is fully reversible. The typical use is snapshot-and-compact:
append a snapshot event at versionV, then callsetStreamTruncateBefore name Vso rehydration starts there. The marker is surfaced on
StreamInfo.truncateBeforeviagetStream, is idempotent, returnsNothing
for a missing or soft-deleted stream, and rejects$allwith
ReservedStreamName. Backed by the newstreams.truncate_beforecolumn
shipped bykiroku-store-migrations. Kiroku.Store.Read.eventExistsInStreamadds an indexed point lookup for
idempotency checks that need to know whether a specific event id is present in
a live stream without scanning that stream. Soft-deleted streams report
False, matchingreadStreamForwardvisibility.Kiroku.Store.TypesexportscategoryName :: StreamName -> CategoryName(the
substring before the first-) and its dualstreamNameInCategory :: CategoryName -> Text -> StreamName. This is the canonical Haskell mirror of
thestreams.categorygenerated column and of the rule used byreadCategory
and category-targeted subscriptions; previously every consumer hand-rolled it.
Notification.categoryFromPayloadnow routes throughcategoryName, so the
rule has one definition.- New observability event
KirokuEventPublisherLoopError !SomeException, emitted
when the publisher's broadcast iteration throws a synchronous non-UsageError
exception (typically a user-supplieddecodeHookor observability handler).
Exhaustive matches onKirokuEventmust handle it.
Bug Fixes
- The publisher survives failing callbacks. A synchronous exception from the
broadcast iteration is caught, reported asKirokuEventPublisherLoopError, and
retried on the next notification or the 30-second safety poll without advancing
lastPublished; previously it killed the publisher loop and stalled every live
subscription. All store-internal threads (publisher, worker, notifier) now emit
observability events through a hardenedemitOrDropthat drops synchronous
exceptions thrown by the handler and rethrows async ones, so a throwing
metrics or logging callback can no longer kill a store thread. - Streamly bridges terminate with the worker's outcome.
subscriptionStreamand
subscriptionAckStreamend the stream normally when the worker stops cleanly
or is cancelled, and rethrow the worker's exception from the next stream pull
when it dies for any other reason (overflow, handler exception, dead-letter
database error, decode-hook exception); previously the consumer blocked
forever. The cancel action no longer writes a sentinel into the bounded queue,
so it cannot block behind a full bridge buffer. - Subscription startup no longer leaks registrations. The pre-fork window in
subscribeis masked and each acquired registration is paired with
bracketOnErrorcleanup, so an exception between publisher registration and
the worker fork can no longer leave a subscriber registered with no reader.
Notifier startup releases its connection ifLISTENfails. - Hard delete purges dead letters.
hardDeleteStreamdeletes
kiroku.dead_lettersrows for exactly the events whose payloads it orphans,
before deleting those payloads. Becausedead_letters.event_idhas a foreign
key toevents(event_id)with no cascade, hard-deleting a stream that had
dead-lettered events previously failed on that constraint. - Single-stream appends retry transient conflicts.
appendToStreamretries once
when the first attempt fails with PostgreSQL40001(serialization failure) or
40P01(deadlock detected) — the same SQLSTATE sethasql-transaction
ret...
kiroku-store-migrations v0.2.0.0
kiroku-store-migrations v0.2.0.0
Hackage: https://hackage.haskell.org/package/kiroku-store-migrations-0.2.0.0
What's Changed
Breaking Changes
- Migrated the package's runtime from Codd to
pg-migrate. The public API now
exports the nativekirokuMigrationscomponent andkirokuMigrationPlan
instead of Codd settings, runner, ledger-status, and schema-check wrappers. - Replaced timestamped runtime identities with manifest-ordered
0001through
0007identities while preserving every SQL payload byte. - Replaced the Codd CLI and
CODD_*configuration surface with the standard
pg-migrate-clicommand tree andDATABASE_URL.verifynow compares the
declared plan with thepgmigrateledger; it does not compare live schema
objects with an expected-schema snapshot.
New Features
- Added a manifest-backed, compile-time-embedded migration component that
applications can compose with other libraries in explicit dependency order. - Added checked-in Codd history mappings and
SamePayloadevidence for safe,
non-replaying import from currentcoddand legacycodd_schemaledgers.
Shared-ledger consumers can combine Kiroku's exported payloads and mappings
with their own components before importing. - Added the standard
pg-migrate-cliplanning, inspection, execution,
verification, status, and numeric migration-authoring commands. - Added fresh-apply, rerun, concurrent-apply, strict ledger verification, Codd
import, partial-row rejection, audit, and source-preservation coverage. The
full Kiroku store suite now consumes the same native plan through
kiroku-test-support. - Appended
0008-schema-management-comment, a non-destructive observable
native-runner canary. Fresh and imported-prefix tests prove it applies once,
verifies strictly, and reruns asAlreadyAppliedwithout changing historical
payloads or Codd mappings.
Changed
- Preserved the seven historical SQL payloads byte-for-byte while moving their
authoritative ordering tomigrations/manifest;migrations.lockremains
the source evidence used during Codd history import. - Removed Codd,
codd-extras,file-embed, andpostgresql-simplefrom the
normal library and executable dependency closure. - Removed the orphaned Codd expected-schema snapshot, its writer executable, the
Cabal flag that gated it, and the accompanying Nix closure workaround. Codd
ledger history import remains supported independently through
pg-migrate-import-codd.
kiroku-otel v0.2.0.1
kiroku-otel v0.2.0.1
Hackage: https://hackage.haskell.org/package/kiroku-otel-0.2.0.1
What's Changed
Other Changes
- Requires
kiroku-store ^>=0.3. The tracer matches exhaustively on
KirokuEvent, so it now handles that release's new
KirokuEventPublisherLoopErrorconstructor; the event is ignored rather than
turned into a span, since the publisher loop is not a per-subscription unit of
work. No change tokiroku-otel's own API.
kiroku-metrics v0.1.0.1
kiroku-metrics v0.1.0.1
Hackage: https://hackage.haskell.org/package/kiroku-metrics-0.1.0.1
What's Changed
Other Changes
- Relaxed dependency bounds to
kiroku-store ^>=0.3andkiroku-cli ^>=0.2. No
change tokiroku-metrics' own API or behavior.
kiroku-cli v0.2.0.0
kiroku-cli v0.2.0.0
Hackage: https://hackage.haskell.org/package/kiroku-cli-0.2.0.0
What's Changed
Breaking Changes
- The standalone
kirokubinary is now a pure remote client. It no longer opens
a store, and the--database-url,--schema, and--pool-sizeoptions are
gone. Subscription status is resolved from--remote-urlor the
KIROKU_REMOTE_URLenvironment variable and served by a running worker's
kiroku-metrics/subscriptionsendpoint; with neither set, the binary exits
with guidance instead of connecting to a database. The embeddable library path
(runKirokuCommandWithStore/renderKirokuCommandWithStore) still reads the
in-process registry, so host applications are unaffected. StandaloneOptionsandStandaloneRuntimeare now newtypes carrying only
command :: KirokuCommand.StandaloneOptionslostdatabaseUrl,schema,
andpoolSize;StandaloneRuntimelostsettings :: ConnectionSettings.
resolveStandaloneOptionsno longer builds connection settings.- Record field prefixes were dropped throughout the public API, so field
selectors are renamed.StandaloneOptions.standaloneCommandand
StandaloneRuntime.runtimeCommandboth becomecommand, and
SubscriptionStatusRow'srowSubscription,rowMember,rowPhase, and
rowGlobalPositionbecomesubscription,member,phase, and
globalPosition. The affected records now deriveGeneric, so they are
addressable withgeneric-lenslabels (row ^. #subscription). - Requires
kiroku-store ^>=0.3.
New Features
Kiroku.Cli.Subscription.Statusgains a remote client:
fetchRemoteSubscriptionStatusRowsandrenderRemoteSubscriptionStatusquery
a worker's/subscriptionsendpoint overhttp-client/http-client-tls.SubscriptionStatusRowgainsToJSON/FromJSONinstances, giving the HTTP
endpoint and the CLI a single wire contract;renderJsonnow encodes through
that codec.StatusOptionsgainsendpoint :: Maybe RemoteEndpoint(Nothingreads the
in-process registry;Justqueries a remote worker), populated by the new
--remote-urloption.
kiroku-metrics v0.1.0.0
kiroku-metrics v0.1.0.0
Hackage: https://hackage.haskell.org/package/kiroku-metrics-0.1.0.0
First release. A sister package to kiroku-store that exposes operational metrics and event streams over HTTP without pulling a web framework into the core library.
What's Changed
New Features
- In-process metrics collector and JSON-encodable snapshot type.
- HTTP endpoints serving metrics as JSON, Prometheus exposition format, and a health check.
- WebSocket channel for streaming live metrics and events out of a running store.
- Live subscription-status endpoint over HTTP, with a CLI remote client.
- Runnable, self-verifying
kiroku-metrics-example(opt-in via-fexample) and a user guide.
shibuya-kiroku-adapter v0.2.0.0
shibuya-kiroku-adapter v0.2.0.0
Hackage: https://hackage.haskell.org/package/shibuya-kiroku-adapter-0.2.0.0
Changes
- Breaking: targets shibuya-core >=0.6 && <0.7 and OpenTelemetry API 1.0.
- AckRetry and AckDeadLetter now drive Kiroku checkpointing through the ack-coupled subscription stream.
- Added envelope tracing attributes, defaultKirokuAdapterConfig, consumer-group processor helpers, and event-type/selector forwarding.