Skip to content

chore(release): cut 1.0.0-beta04 - #35

Merged
darkryh merged 1 commit into
masterfrom
chore/release-beta04
Aug 26, 2026
Merged

darkryh merged 1 commit into
masterfrom
chore/release-beta04

Conversation

@darkryh

@darkryh darkryh commented Aug 26, 2026

Copy link
Copy Markdown
Owner

Cuts 1.0.0-beta04. Version pins move together, as in the beta03 cut: gradle.properties (what release-library.yml publishes), the README and docs snippets, the initializr default, and the sample + consumer-smoke consumer builds.

What this release carries

Katalyst has a shutdown lifecycle. It had StartupHook and ReadyHook and nothing on the way down, so it closed the connection pool with application background work still running — the polling loops and consumers ReadyHook's own KDoc invites. Every such shutdown ended in:

SQLSTATE(08006) / java.net.SocketException: Socket closed
IllegalStateException: No transaction manager for db ExposedDatabase[...](null)
  • ShutdownHook is the missing half, and it suspends — Katalyst awaits it, so a worker can cancelAndJoin() and be genuinely finished before anything is taken away. Ktor's ApplicationStopping subscribers are synchronous and can only ever signal a worker, never join it.
  • Teardown moves to ApplicationStopped. Katalyst subscribes before start() while an application's KtorModules subscribe during it, so Katalyst was always first in the handler list and the documented, Ktor-native way to stop a worker was guaranteed to run too late. Applications using that idiom are fixed without changing a line.
  • The pool gets a bounded moment to go quiet before it closes, covering work that was cancelled but not joined. If it expires, a WARN names how many connections are still checked out — the signal that some background work needs a ShutdownHook.
  • KatalystFeature.onShutdown(context) — the same gap one level up.
  • LifecycleHook now carries id/order for all three hook interfaces.

The defect was present since at least alpha10 and is not a beta03 regression — verified by reproducing it identically on beta02 and beta03.

Breaking (pre-1.0)

ReadyHook and StartupHook lose their own getId/getOrder (and their DefaultImpls) to LifecycleHook. Source-compatible; binary-breaking for already-compiled hook implementors, so consumers recompile.

Validated on this commit

  • full check, apiCheck, koverVerify
  • samples/validate-samples.sh — the plugin and all starters resolve for a real external consumer
  • harness/consumer-smoke/run-all-engines.sh — netty, jetty, cio

🤖 Generated with Claude Code

Version pins move together, as in fd9c836: gradle.properties (which is what
release-library.yml publishes), the README and docs snippets, the initializr
default, and the sample + consumer-smoke consumer builds.

What this release carries:

  - Katalyst has a shutdown lifecycle. It had StartupHook and ReadyHook and
    nothing on the way down, so it closed the connection pool with application
    background work still running - the polling loops and consumers ReadyHook's
    own KDoc invites. Every such shutdown ended in SQLSTATE 08006 / Socket
    closed followed by "No transaction manager for db ExposedDatabase[...]".

    ShutdownHook is the missing half, and it SUSPENDS: Katalyst awaits it, so a
    worker can cancelAndJoin and be genuinely finished before anything is taken
    away. Ktor's ApplicationStopping subscribers are synchronous and can only
    ever signal a worker, never join it.

  - Katalyst now tears down on ApplicationStopped rather than
    ApplicationStopping. It subscribes before start() while an application's
    KtorModules subscribe during it, so it was always first in the handler list
    and the documented, Ktor-native way to stop a worker was guaranteed to run
    too late. Applications using that idiom are fixed without changing a line.

  - The connection pool is given a bounded moment to go quiet before it closes,
    covering work that was cancelled but not joined. If it expires, a WARN names
    how many connections are still checked out - which is the signal that some
    background work needs a ShutdownHook.

  - KatalystFeature gains onShutdown(context), the same gap one level up.

  - LifecycleHook now carries id/order for StartupHook, ReadyHook and
    ShutdownHook. Each declared its own defaults before, so the most ordinary
    shape in the framework - one class that starts a worker and stops it again -
    had to override both for no reason. Source-compatible; binary-breaking for
    already-compiled hook implementors, which is acceptable pre-1.0.

The defect was present since at least alpha10 and is not a beta03 regression -
verified by reproducing it identically on beta02 and beta03.

Validated on this commit: full `check`, `apiCheck`, `koverVerify`,
`samples/validate-samples.sh`, and consumer-smoke across netty/jetty/cio.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@darkryh
darkryh merged commit d87728e into master Aug 26, 2026
2 checks passed
@darkryh
darkryh deleted the chore/release-beta04 branch August 26, 2026 21:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant