Skip to content

build(server): take all of kore to 0.1.14 under one version ref - #96

Merged
youndie merged 2 commits into
mainfrom
build/kore-0.1.14
Oct 2, 2026
Merged

youndie merged 2 commits into
mainfrom
build/kore-0.1.14

Conversation

@youndie

@youndie youndie commented Oct 2, 2026

Copy link
Copy Markdown
Owner

Why

kore-core, kore-ktor and the kore.build plugin stayed on 0.1.4 while kore-mcp came in at 0.1.14 under its own ref (#94). Taking the rest of kore to 0.1.14 needs the lifecycle rewired: EngineDrain there refuses to be built beside Ktor's own shutdown hook, and the predicate form of installShutdownRefusal is deprecated, which fails the build here because warnings are errors. This PR does that rewiring and folds the two refs into one.

What changes

  • One kore ref (0.1.14) for kore-core, kore-ktor, kore-mcp and the plugin. koreMcp is removed.

  • startForKore() replaces start(wait = false). On the JVM, Ktor's own hook no longer stops the engine at the signal, in the middle of the announce (kore#90). On Kotlin/Native, a SIGTERM right after start can no longer hang the process (kore B-63).

  • One DrainGate, created in main and handed to both installShutdownRefusal (through module(…, draining)) and EngineDrain. The refusal now opens at the drain, not at the announce (kore B-61). module's new parameter has a default, so McpEndpointTest is unchanged.

  • reuseAddress = true on the engine, and a pre-start bind of port 8080 with the same flag (HttpListener.kt, listenRefusal):

    • a port something already listens on now prints one line and exits with code 1, where CIO used to abort with SIGABRT (kore B-59);
    • a restart in place binds over the old connections' TIME_WAIT (kore B-62).

    awaitPort() used to wait out that TIME_WAIT for up to two minutes. It is deleted.

  • The port check reads only the port, not the process environment. It goes through a kore schema with one key and is given just the port. Reading the real environment would fail: kore's schema refuses any undeclared variable under its prefix, and the kubelet puts KATCHER_PORT, KATCHER_SERVICE_HOST and the other service-link variables into the pod. katcher's port is fixed, so the line it prints names the port, not a variable nobody reads.

  • Health checks. They now stop with stopAndJoin() (kore#79), in RELEASE_CONSUMERS, beside the report queue and a stage before the pool closes. They used to stop in RELEASE_TELEMETRY, after RELEASE_POOLS, so a SELECT 1 could run against a closed pool. kore orders stages, not the participants inside a stage. RELEASE_TELEMETRY is now empty and still reports COMPLETED; the metrik agent flushes itself on ApplicationStopping, inside the drain.

  • The Image job's shutdown step now also requires RELEASE_TELEMETRY, prints the whole transcript, and fails if the container did not leave by itself (exit code 137, or the full 40 s timeout).

  • CLAUDE.md: the lifecycle section is updated to match.

  • Release 0.8.6, as a separate commit: version=0.8.6, chart 0.7.6 / appVersion 0.8.6.

Verification

Local runs on macOS:

  • Tests. :server:jvmTest 128/128 and :server:nativeTest (macosArm64) 128/128, plus :server:ktlintCheck. The new test is HttpListenerTest: with port 0.0.0.0:N held, the refusal names the port and not the synthetic key.
  • Warnings. No kore deprecation warnings: the server compiles with warnings as errors, and the only w: lines in the log are the existing macosX64 notices in build scripts.
  • Ktor is unchanged. I compared the set of io.ktor: coordinates in :server:dependencies before and after, for both jvmRuntimeClasspath and nativeCompileKlibraries, and they are identical: Ktor 3.6.0. The only exception is ktor-server-websockets:3.5.1, which the MCP SDK brings in, exactly as on main.
  • Shutdown on the debug binary. I ran it, waited for /health/ready, then sent SIGTERM. The process left by itself after about 2 s with exit code 0:
    SIGNAL COMPLETED in 4.459us
    ANNOUNCE COMPLETED in 2.009921875s
    DRAIN COMPLETED in 1.490375ms
    RELEASE_CONSUMERS COMPLETED in 411.209us
    RELEASE_POOLS COMPLETED in 1.034583ms
    RELEASE_TELEMETRY COMPLETED in 1.75us
    EXIT COMPLETED in 1.041us
    
  • Busy port. I held port 8080 and started the binary. It printed this one line and exited with code 1:
    katcher cannot start: port 8080 cannot be listened on: bind: Address already in use (errno 48)

CI provides the linuxX64 build and the image proof. The Image job builds the static binary, runs the smoke test, and then runs docker stop against the transcript check above.

Refs: #95

kore-core, kore-ktor and the build plugin stayed on 0.1.4 while kore-mcp
rode 0.1.14 on its own ref, because the newer EngineDrain refuses to run
beside Ktor's own shutdown hook. The lifecycle now uses the 0.1.9+ wiring:

- startForKore() in place of start(wait = false), so Ktor's JVM hook
  cannot stop the engine mid-announce (kore#90) and a native SIGTERM
  right after start cannot hang the process (kore B-63);
- one DrainGate shared by installShutdownRefusal and EngineDrain, so the
  refusal opens at the drain, not at the announce (kore B-61);
- reuseAddress on the engine and a pre-start bind of port 8080 with the
  same flag: a busy port is one line and exit 1 instead of SIGABRT
  (kore B-59), and a restart in place binds over TIME_WAIT (kore B-62).
  The two-minute awaitPort() loop that waited TIME_WAIT out is gone;
- the health-check loop stops with stopAndJoin() (kore#79) in
  RELEASE_CONSUMERS, a stage before the pool closes. It used to stop in
  RELEASE_TELEMETRY, after the pool, so a SELECT 1 could run against a
  closed pool.

The port check goes through a one-key schema fed the port alone, not the
process environment: kore's schema refuses undeclared variables under its
prefix, and the kubelet injects KATCHER_PORT and the other service-link
variables into the pod.

The image job now also requires RELEASE_TELEMETRY, prints the whole
transcript, and fails when the container did not leave by itself.

Refs: #95
All of kore on 0.1.14: startForKore, one DrainGate for the refusal and the drain, SO_REUSEADDR with a pre-start port check, and the health checks stopped before the pool closes.
@youndie
youndie merged commit 73d078b into main Oct 2, 2026
3 checks passed
@youndie
youndie deleted the build/kore-0.1.14 branch October 2, 2026 06:57
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