Skip to content

Releases: shinzui/kiroku

kiroku-store v0.3.0.1

Choose a tag to compare

@shinzui shinzui released this 14 Jul 14:12

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 runTransaction body now preserves its
    SQLSTATE and server message. Anything that was not a stream_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
    becomes UnexpectedServerError "23503" with the server's message intact.
    Duplicate-event mapping is unchanged.

kiroku-store-migrations v0.3.0.0

Choose a tag to compare

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-migrate to 1.1.0.0. kiroku-store-migrate check now takes the
    manifest as --manifest PATH instead of a positional argument, matching
    new --manifest.

New Features

  • kiroku-store-migrate up and repair accept explicit --wait and
    --no-statement-timeout overrides; 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

Choose a tag to compare

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

  • 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.

kiroku-store v0.3.0.0

Choose a tag to compare

@shinzui shinzui released this 11 Jul 15:23

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 00030007 from kiroku-store-migrations.

Breaking Changes

  • Backward reads now paginate. readStreamBackward and readAllBackward treat 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
    0 to maxBound, so StreamVersion 0 / GlobalPosition 0 still 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 mock Store
    interpreter must mirror the 0 -> maxBound mapping.
  • Oversized stream names are rejected before any database work. StoreError
    gains StreamNameTooLong !StreamName !Int (the Int is the offending UTF-8
    byte length), and Kiroku.Store.Error exports maxStreamNameBytes (512) and
    validateStreamName :: StreamName -> Either StoreError (). Every
    application-stream entry point — appendToStream, appendMultiStream,
    linkToStream, softDeleteStream, hardDeleteStream, undeleteStream, and
    the runTransactionAppending* wrappers — runs the same validation (reserved
    $all plus the length bound) up front instead of only rejecting $all. The
    bound exists because the append notification payload embeds the stream name and
    PostgreSQL rejects pg_notify payloads 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 on StoreError must handle the new constructor.
  • Publisher queues are created only for non-group AllStreams subscriptions.
    Category subscriptions and all consumer-group members no longer register a
    bounded queue with the EventPublisher; they are DB-driven in live mode. As a
    consequence SubscriptionConfig.queueCapacity and
    SubscriptionConfig.overflowPolicy have no effect for those targets, and they
    can no longer be paused, dropped, or terminated with SubscriptionOverflowed.
    In the exposed Kiroku.Store.Subscription.Worker module, runWorker's
    signature changed from taking a TBQueue (Vector RecordedEvent) plus a TVar SubscriberStatus to taking a single new exported sum LiveSource (LiveFromPublisherQueue | LiveFromCategoryNotify | LiveFromGroupPolling),
    fixed at subscribe time from the config's (consumerGroup, target) shape.
  • Empty append batches are rejected. StoreError gains EmptyAppendBatch !StreamName and AppendConflict gains EmptyAppendBatchConflict !StreamName
    (mapped by appendConflictToStoreError). appendToStream with [] now fails
    with EmptyAppendBatch before any pool work; previously it took the global
    $all row lock, fired NOTIFY triggers, created an empty stream under
    NoStream, and surfaced a misleading WrongExpectedVersion /
    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 with EmptyAppendBatch.
  • Link failures are typed. StoreError gains EventAlreadyLinked !StreamName !(Maybe EventId) (the 23505 unique violation on stream_events_pkey,
    carrying the offending event id when PostgreSQL's detail string is parseable)
    and LinkSourceEventMissing !StreamName (the 23502 not-null violation raised
    when linkToStream references an event id that does not exist; the whole batch
    rolls back). Both previously surfaced as an opaque ConnectionError carrying a
    stringified UsageError.
  • StreamInfo gains a truncateBefore :: !StreamVersion field. Code
    constructing or exhaustively matching StreamInfo must be updated.
  • The Store effect gains SetStreamTruncateBefore :: StreamName -> StreamVersion -> Store m (Maybe StreamId) and EventExistsInStream :: StreamName -> EventId -> Store m Bool. Mock and test interpreters of the
    Store effect must add arms for both.
  • Kiroku.Store.SQL's hard-delete statements were resplit.
    deleteStreamJunctionsStmt is removed, replaced by deleteAllRowsForOriginStmt,
    deleteJunctionsByEventIdsStmt, deleteStreamOwnJunctionsStmt, and
    deleteDeadLettersForOrphanedEventsStmt, which the interpreter runs in sequence
    before deleteOrphanedEventsStmt.
  • Checkpoint-load failures now fail the subscription loudly. A UsageError while
    reading a subscription's saved checkpoint at startup surfaces through the
    handle's wait as Left e and the worker stops; it no longer falls back to
    GlobalPosition 0 and silently re-processes the whole history.
  • subscriptionAckStream and subscriptionStream reject a zero buffer, throwing
    the new InvalidStreamBufferSize exception (exported from
    Kiroku.Store.Subscription.Stream) when bufferSize is 0; a zero-capacity
    TBQueue would deadlock the bridge handler on its first delivery.
  • Duplicate events inside transaction bodies are typed. runTransaction,
    runTransactionNoRetry, and the runTransactionAppending* wrappers map a
    23505 violation on events_pkey / stream_events_pkey to DuplicateEvent (Just eid) (new mapTransactionUsageError in Kiroku.Store.Error) instead of
    the previous opaque ConnectionError.

New Features

  • Logical truncate-before marker (close-the-book compaction).
    Kiroku.Store.Lifecycle.setStreamTruncateBefore :: StreamName -> StreamVersion -> Eff es (Maybe StreamId) and clearStreamTruncateBefore :: StreamName -> Eff es (Maybe StreamId) set a per-stream cursor below which ordered per-stream
    reads hide events. readStreamForward, readStreamBackward, and the paged
    readStreamForwardStream return only events whose streamVersion is at or
    above the marker; the $all global 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 version V, then call setStreamTruncateBefore name V so rehydration starts there. The marker is surfaced on
    StreamInfo.truncateBefore via getStream, is idempotent, returns Nothing
    for a missing or soft-deleted stream, and rejects $all with
    ReservedStreamName. Backed by the new streams.truncate_before column
    shipped by kiroku-store-migrations.
  • Kiroku.Store.Read.eventExistsInStream adds 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, matching readStreamForward visibility.
  • Kiroku.Store.Types exports categoryName :: StreamName -> CategoryName (the
    substring before the first -) and its dual streamNameInCategory :: CategoryName -> Text -> StreamName. This is the canonical Haskell mirror of
    the streams.category generated column and of the rule used by readCategory
    and category-targeted subscriptions; previously every consumer hand-rolled it.
    Notification.categoryFromPayload now routes through categoryName, 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-supplied decodeHook or observability handler).
    Exhaustive matches on KirokuEvent must handle it.

Bug Fixes

  • The publisher survives failing callbacks. A synchronous exception from the
    broadcast iteration is caught, reported as KirokuEventPublisherLoopError, 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 hardened emitOrDrop that 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. subscriptionStream and
    subscriptionAckStream end 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
    subscribe is masked and each acquired registration is paired with
    bracketOnError cleanup, 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 if LISTEN fails.
  • Hard delete purges dead letters. hardDeleteStream deletes
    kiroku.dead_letters rows for exactly the events whose payloads it orphans,
    before deleting those payloads. Because dead_letters.event_id has a foreign
    key to events(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. appendToStream retries once
    when the first attempt fails with PostgreSQL 40001 (serialization failure) or
    40P01 (deadlock detected) — the same SQLSTATE set hasql-transaction
    ret...
Read more

kiroku-store-migrations v0.2.0.0

Choose a tag to compare

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 native kirokuMigrations component and kirokuMigrationPlan
    instead of Codd settings, runner, ledger-status, and schema-check wrappers.
  • Replaced timestamped runtime identities with manifest-ordered 0001 through
    0007 identities while preserving every SQL payload byte.
  • Replaced the Codd CLI and CODD_* configuration surface with the standard
    pg-migrate-cli command tree and DATABASE_URL. verify now compares the
    declared plan with the pgmigrate ledger; 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 SamePayload evidence for safe,
    non-replaying import from current codd and legacy codd_schema ledgers.
    Shared-ledger consumers can combine Kiroku's exported payloads and mappings
    with their own components before importing.
  • Added the standard pg-migrate-cli planning, 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 as AlreadyApplied without changing historical
    payloads or Codd mappings.

Changed

  • Preserved the seven historical SQL payloads byte-for-byte while moving their
    authoritative ordering to migrations/manifest; migrations.lock remains
    the source evidence used during Codd history import.
  • Removed Codd, codd-extras, file-embed, and postgresql-simple from 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

Choose a tag to compare

@shinzui shinzui released this 11 Jul 15:23

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
    KirokuEventPublisherLoopError constructor; the event is ignored rather than
    turned into a span, since the publisher loop is not a per-subscription unit of
    work. No change to kiroku-otel's own API.

kiroku-metrics v0.1.0.1

Choose a tag to compare

@shinzui shinzui released this 11 Jul 15:24

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.3 and kiroku-cli ^>=0.2. No
    change to kiroku-metrics' own API or behavior.

kiroku-cli v0.2.0.0

Choose a tag to compare

@shinzui shinzui released this 11 Jul 15:24

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 kiroku binary is now a pure remote client. It no longer opens
    a store, and the --database-url, --schema, and --pool-size options are
    gone. Subscription status is resolved from --remote-url or the
    KIROKU_REMOTE_URL environment variable and served by a running worker's
    kiroku-metrics /subscriptions endpoint; 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.
  • StandaloneOptions and StandaloneRuntime are now newtypes carrying only
    command :: KirokuCommand. StandaloneOptions lost databaseUrl, schema,
    and poolSize; StandaloneRuntime lost settings :: ConnectionSettings.
    resolveStandaloneOptions no longer builds connection settings.
  • Record field prefixes were dropped throughout the public API, so field
    selectors are renamed. StandaloneOptions.standaloneCommand and
    StandaloneRuntime.runtimeCommand both become command, and
    SubscriptionStatusRow's rowSubscription, rowMember, rowPhase, and
    rowGlobalPosition become subscription, member, phase, and
    globalPosition. The affected records now derive Generic, so they are
    addressable with generic-lens labels (row ^. #subscription).
  • Requires kiroku-store ^>=0.3.

New Features

  • Kiroku.Cli.Subscription.Status gains a remote client:
    fetchRemoteSubscriptionStatusRows and renderRemoteSubscriptionStatus query
    a worker's /subscriptions endpoint over http-client /http-client-tls.
  • SubscriptionStatusRow gains ToJSON / FromJSON instances, giving the HTTP
    endpoint and the CLI a single wire contract; renderJson now encodes through
    that codec.
  • StatusOptions gains endpoint :: Maybe RemoteEndpoint (Nothing reads the
    in-process registry; Just queries a remote worker), populated by the new
    --remote-url option.

kiroku-metrics v0.1.0.0

Choose a tag to compare

@shinzui shinzui released this 16 Jun 04:02

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

Choose a tag to compare

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.