Skip to content

Releases: Cratis/Chronicle.Kotlin

Release v2.10.0

Choose a tag to compare

@github-actions github-actions released this 11 Aug 17:32
54d048f

Summary

A Spring Boot starter reduces setting Chronicle up to adding a dependency: a
connected client, artifacts registered before the first request is served, and
an IEventStore ready to inject.

Stacked on #46 — that PR carries the artifact discovery and registration this
starter builds on, and should merge first.

Added

  • io.cratis:chronicle-spring-boot-starter — a connected client, artifacts registered before the first request is served, and an IEventStore ready to inject, configured under cratis.chronicle.
  • Spring Boot multi-tenancy: the injected IEventStore routes to the namespace the current work belongs to, resolved from a fixed value, an HTTP header, the request subdomain, or a claim on the authenticated principal.
  • Spring Boot gives each request an identity taken from the authenticated principal, a causation trail describing the call, and a unit of work that commits on success and rolls back on failure. Each can be switched off on its own.
  • Chronicle — the Java-facing Spring bean exposing the everyday operations without coroutines, for Java callers and blocking MVC handlers.
  • IEventStoreNamespaceResolver for hosts that decide the namespace themselves.
  • Spring Boot samples for Kotlin and Java, each with a walkthrough.
  • A guide for Spring Boot support.

Changed

  • The README is rewritten around what the client does for you, with Kotlin and Java shown side by side throughout.

Release v2.9.0

Choose a tag to compare

@github-actions github-actions released this 07 Aug 11:12
dc6861e

Summary

Artifacts register themselves, and the twelve open issues in this repository are
closed alongside — most of them parity gaps with the .NET client, several of
them things a JVM application simply could not express before.

Added

  • Artifacts are discovered and registered with the kernel automatically when the client connects, in the order the kernel needs them, and again on every reconnect. Manual registration is unchanged and still fully supported.
  • IEventStore.registerAll() registers every artifact in one call, and awaitRegistration() waits for the automatic pass so the first append is deterministic.
  • ChronicleOptions.withoutAutoRegistration() turns discovery off, and withArtifactsFrom(vararg packages) narrows it to the packages you own. KnownClientArtifacts takes an explicit list where classpath scanning is unwanted.
  • IArtifactActivator lets a dependency injection container create artifacts, so a reactor or reducer can take its dependencies through its constructor.
  • Reactor, reducer and read model reactor handlers may be suspend, so a handler that awaits an HTTP call or the event log no longer blocks the thread the observation runs on. (#16)
  • IReactorMiddleware wraps every reactor handler invocation, keeping tracing, logging and metrics out of reactor code. Java implements BlockingReactorMiddleware instead. (#11)
  • A reactor handler may take parameters beyond the event — a read model resolved for the event's event source out of the box, or anything an IReactorMethodArgumentResolver supplies. (#27)
  • ICanBeNotifiedAboutReplay tells a reactor when a replay begins and ends, per partition. (#13)
  • store.failedPartitions surfaces the partitions an observer is stuck on, with the history of attempts, and retries one once the cause is fixed. (#13)
  • ConceptAs<T> gives a domain value a type of its own, so the compiler can tell a book's identifier from a member's. Concepts serialize as the value they wrap, so adopting one for a property already in production changes neither the JSON nor the schema. (#15)
  • AppendOptions.causation and EventForEventSourceId.causation attribute an append to a chain other than the ambient one — an imported event, or a side effect that belongs to a chain of its own. (#43)
  • Chronicle work is reported as OpenTelemetry spans: appends, batches, reactor observations and reducer folds. Nothing to turn on. (#18)
  • IProjectionsService.query(declaration) runs a Projection Declaration Language declaration and returns what it projected, without registering anything. (#19)
  • Captures — sources outside Chronicle, pulled in and appended as events. Declare an ICapture and discovery saves and starts it on connect, or drive store.captures directly. (#10)
  • io.cratis:chronicle-testingEventScenario and ReadModelScenario specify what a slice appends and what a reducer folds, in-process, with no kernel, container or database. (#25)
  • Guides for artifact registration, strongly-typed identifiers, tracing, captures and testing.

Changed

  • ChronicleOptions gains autoDiscoverAndRegister (on by default), artifacts, artifactActivator and openTelemetry.
  • Both console samples now opt out of automatic registration, so they keep working as a tour of the registration API.
  • IConstraintBuilder.uniqueFor and IWebhookDefinitionBuilder.withEventType take a Java Class as well as a KClass, and Causation.of(...) builds one without naming a value class — all three were unreachable from Java before. (#36)

Fixed

  • A reactor, reducer or read model reactor with no handlers at all now fails at registration instead of registering successfully and observing nothing. (#17)
  • A reactor or reducer declared internal or private failed on every event it was given, because reflection refused to invoke a handler on a non-public class.
  • The client's public ABI is checked in and validated on every build, and a Java conformance fixture compiles every public entry point from Java — Java had broken twice while CI stayed green. (#36)

Release v2.8.0

Choose a tag to compare

@github-actions github-actions released this 06 Aug 12:19
a78de4e

Summary

Events can be appended across several event sources as one atomic batch, and composed before committing.

Added

  • appendMany accepting events that each carry their own event source id, stream, tags and subject, committed as one atomic operation with an optional concurrency scope per event source. (#14)
  • Compose a batch across call sites with eventSequence.forEventSourceId(id) { ... }, inspect it, and commit it with perform(). (#14)

Release v2.7.0

Choose a tag to compare

@github-actions github-actions released this 06 Aug 11:48
1ed07f0

Summary

Geospatial values can be modelled from Kotlin and Java.

Added

  • Point, LineString and Polygon types that serialize as GeoJSON, so Chronicle recognizes them as geospatial and the sink can index and query them. (#28)
  • Generated schemas mark geospatial properties with the point, linestring and polygon formats, matching the .NET client. (#28)
  • ChronicleGson.chronicleGson exposes the client's own serializer, for callers producing event content themselves.

Release v2.6.0

Choose a tag to compare

@github-actions github-actions released this 06 Aug 11:45
c6aebec

Summary

Reactors can now respond to read model changes, not just events.

Added

  • IReadModelReactor — react to read model instances being added, modified or removed by writing added, modified or removed methods, with no watch loop to maintain. (#12)
  • Read model reactor handlers can return events to be appended as side effects, using the changed instance's key as the event source id. (#12)

Release v2.5.0

Choose a tag to compare

@github-actions github-actions released this 06 Aug 10:01
10d292d

Summary

Reactors and reducers can be labelled and can narrow which events they observe.

Added

  • @Tag labels a reactor or reducer for tooling, without affecting what it observes. (#24)
  • @FilterEventsByTag, @EventSourceType and @EventStreamType narrow the events the kernel delivers to an observer, so filtered-out events are never sent. (#24)

Release v2.4.0

Choose a tag to compare

@github-actions github-actions released this 06 Aug 09:45
a6c5f97

Summary

Appends can now be shaped by the caller instead of using fixed values.

Added

  • AppendOptions takes eventSourceType, eventStreamType, eventStreamId, subject, tags and occurred, so an append can target a non-default stream, carry tags, be backdated, or name the compliance subject. (#23)
  • AppendOptionsBuilder for constructing options from Java, where Kotlin's default arguments are unavailable. (#23)

Fixed

  • The compliance subject was fixed to the event source id with no way to override it, so PII for a subject other than the event source could not be modeled from Kotlin or Java. (#23)

Release v2.3.1

Choose a tag to compare

@github-actions github-actions released this 06 Aug 09:06
fa1aa76

Summary

The repository could not be checked out or built on macOS or Windows.

Fixed

  • IdentityProvider.kt and identityProvider.kt differed only by case, so only one could exist in the working tree on a case-insensitive filesystem and the build failed with an unresolved reference. (#29)

Release v2.3.0

Choose a tag to compare

@github-actions github-actions released this 06 Aug 09:01
151ed29

Summary

Kotlin and Java reactors and reducers reach parity with the C# client on observation behavior.

Added

  • @Reactor and @Reducer take an eventSequence, for observing a sequence other than the event log.
  • @Reducer takes isActive, for a reducer the kernel does not actively run.
  • @OnceOnly excludes a reactor from replay on the class, or a single handler on a method.
  • @Replay marks the handler that takes over while an observer is being replayed.
  • Reducer handlers can take an EventContext after the state.
  • EventContext carries the observation state, event source type, event stream type and id, event store, namespace, causation, tags, and hash.

Changed

  • Handler shapes the client cannot invoke now fail at register() instead of on every event. (#17)

Fixed

  • EventContext.correlationId was a random value and causedBy was always Identity.unknown; both are now read from the kernel.

Release v2.2.0

Choose a tag to compare

@github-actions github-actions released this 06 Aug 06:53
6c8058d

Summary

Brings the Kotlin/Java Chronicle client to parity with the other Chronicle clients across two phases of work:

  1. Earlier phase: four new service modules (ExternalServices, Webhooks, Jobs, EventStoreSubscriptions), event type migrations, 15 new model-bound projection attributes, a richer declarative projection builder, a richer ReadModels API, reactor side-effect events, and PII encryption key deletion.
  2. This phase: three confirmed bug fixes, full IEventSequence/IEventLog completeness (redact, concurrency scopes, bookmarked reads, stream completion, a live append feed), IEventStore interface completeness, a richer UnitOfWork, constraint scoping, and typed read-model observation.

Fully additive — nothing existing changes behavior, except one safe, pre-release-only behavior change noted below.

Added

Service modules, migrations, projections, read models (earlier phase)

  • ExternalServices — register named HTTP or database (MS SQL / PostgreSQL) endpoints with basic/bearer/OAuth authentication, addressable by name from other Chronicle integrations.
  • Webhooks — register webhooks either via a discoverable @Webhook + IWebhookDefiner class or imperatively, with authentication, header, event-type filtering, and replay/activation options; list and remove webhooks.
  • Jobs — list jobs and their steps, get a single job, and stop/resume/delete a job.
  • EventStoreSubscriptions — subscribe an event store to another event store's outbox with optional event-type filtering, list, and unsubscribe. Now defaults to every event type this client has registered when a subscription isn't narrowed explicitly, instead of subscribing to nothing.
  • Event type migrations — IEventTypeMigration/EventTypeMigration base class plus an EventTypeMigrationBuilder DSL (renamedFrom, defaultValue, split, combine) for upcasting/downcasting between event type generations, discovered alongside @EventType classes at register().
  • 15 new model-bound projection attributes: @Join, @ChildrenFrom, @Nested, @ClearWith, @Count, @Increment, @Decrement, @AddFrom, @SubtractFrom, @FromAll, @FromEvery, @NotRewindable, @RemovedWith, @RemovedWithJoin, @NoAutoMap.
  • Declarative projection builder methods: .join(), .fromEvery()/.fromAll(), .removedWith()/.removedWithJoin(), .children(), .nested(), .notRewindable(), plus composite/constant keys.
  • Reactor handlers can now return a follow-up event, a List<Any>, or the new EventForEventSourceId wrapper, and it's auto-appended as a side effect — same-stream or cross-stream.
  • ComplianceService.deleteEncryptionKey for permanently erasing a subject's PII ("right to be forgotten").

IEventSequence / IEventLog completeness (this phase)

  • redact / redactForEventSource — permanently rewrites one event's content, or every event's content for an event source (optionally narrowed to specific event types). Destructive and irreversible; the single most significant addition in this phase.
  • Real ConcurrencyScope support via AppendOptions.concurrencyScope and ConcurrencyScopeBuilder, and appendMany now commits the whole batch through a single atomic RPC instead of one Append call per event.
  • getTailSequenceNumber, getNextSequenceNumber, getTailSequenceNumberForObserver — the current/next position in the sequence, including relative to the event types a specific reactor/reducer handles.
  • getForEventSourceIdAndEventTypes, getFromSequenceNumber — reading events back for one event source (narrowed by type/stream) or forward from a bookmarked position.
  • completeStream — closes an event stream type/id pair so it can no longer be appended to.
  • appendOperations — a hot Flow that emits after every completed append made through a specific IEventSequence instance.

IEventStore / IChronicleClient completeness (this phase)

  • compliance, eventTypes, namespaces, externalServices, jobs, eventStoreSubscriptions, webhooks, and identities are now all on the IEventStore interface itself (previously only on the concrete EventStore class), plus getEventSequence(id) for non-default event sequences.
  • IChronicleClient.getEventStores() / evictEventStores() — list every event store known to the kernel, and clear this client's cached EventStore instances without disposing the client.
  • IIdentityManagerService.rename — renames the human-readable name the kernel has stored for an identity.
  • INamespacesService.getAll() — lists every namespace in the event store.
  • ChronicleConnectionString.toString() — renders a parsed connection string back to its textual form; round-trips through parse().

Transactions, constraints, seeding, read models (this phase)

  • Richer IUnitOfWork: isSuccess, getConstraintViolations/getConcurrencyViolations/getAppendErrors, onCompleted, tryGetLastCommittedEventSequenceNumber. Richer IUnitOfWorkManager: tryGetFor, setCurrent.
  • Constraint scoping — IConstraintBuilder.perEventSourceType()/.perEventStreamType()/.perEventStreamId() narrow a constraint's uniqueness check to a dimension instead of checking globally across the whole event store.
  • IEventSeedingBuilder.forNamespace() — a scoped builder for seed data targeting a namespace other than the event store's own; typed forEventType() for both the top-level and namespace-scoped builders.
  • watch()/getSnapshotsById() now deserialize straight into the caller's read model type instead of raw JSON; releaseMany decrypts @Pii properties for a batch of instances in one call.

Samples, docs, and Java interop (both phases)

  • Both Kotlin and Java console samples demonstrate every feature above end-to-end, wired into the existing interactive command loop — including, this phase, a single-event redact, a bulk "GDPR erase everything for this customer" redact, constraint scoping, IdentityManager.rename, read-model snapshot history, and a live background watcher using typed watch().
  • Java bridge parity for all of the above via io.cratis.chronicle.java.*JavaBridge, including new bridges for the value-class-typed members Java cannot call directly (redact, the event-lookup methods, completeStream, ConcurrencyScopeBuilder.withSequenceNumber, and a callback-based subscription to watch/appendOperations).
  • New and expanded guide/reference pages (Webhooks, Jobs, Event Type Migrations, Event Store Subscriptions, External Services, EventStore API, Seeding, Configuration, Constraints, Transactions, Read Models, Annotations), with matching validated snippets in both the Kotlin and Java client-snippet trees.

Fixed

  • UniqueConstraintBuilder.on() was silently ignoring the property actually passed to it and always keying the constraint on the first declared property instead.
  • Event type and read model registration sent an empty "{}" schema to the kernel instead of a real JSON schema reflecting the type's properties; PII compliance metadata is now wired into that generated schema too.

Behavior change (safe — pre-release, within this same unreleased PR)

  • IUnitOfWorkManager.current now throws NoUnitOfWorkHasBeenStarted when no unit of work has been begun on the current thread, rather than any prior placeholder behavior. Since this entire UnitOfWork surface is new in this unreleased PR, there is no released behavior to break.

Known follow-up

  • EventTypesService's migration-building path, ProjectionsService's new reflection/wire-building paths, and ReactorsService's side-effect appending don't have dedicated unit tests yet — there's no established gRPC-stub-mocking pattern in this codebase for those specific paths, only pure-logic builders (EventTypeMigrationBuilder, ProjectionBuilderFor) are covered. Flagging as a follow-up rather than blocking this PR.
  • The event type migration builder DSL (renamedFrom/defaultValue/split/combine) has no Java bridge yet, since it relies on Kotlin property references (KProperty1) that Java can't produce directly. The Java client-snippet for migrations is left as an honest "not supported" placeholder rather than a misleading example.

Test plan

  • ./gradlew clean build test — zero errors, 224 tests passing (up from 133 at the start of this PR)
  • python3 Documentation/validate-client-snippets.py — all Kotlin and Java client snippets compile
  • bash Documentation/verify-markdown.sh — markdown lint and link checks pass
  • Both samples (Samples/Kotlin/Console, Samples/Java/Console) build cleanly