Repository navigation
build(server): take all of kore to 0.1.14 under one version ref - #96
Merged
Merged
Conversation
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.
This was referenced Oct 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
kore-core,kore-ktorand thekore.buildplugin stayed on 0.1.4 whilekore-mcpcame in at 0.1.14 under its own ref (#94). Taking the rest of kore to 0.1.14 needs the lifecycle rewired:EngineDrainthere refuses to be built beside Ktor's own shutdown hook, and the predicate form ofinstallShutdownRefusalis 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
koreref (0.1.14) forkore-core,kore-ktor,kore-mcpand the plugin.koreMcpis removed.startForKore()replacesstart(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 inmainand handed to bothinstallShutdownRefusal(throughmodule(…, draining)) andEngineDrain. The refusal now opens at the drain, not at the announce (kore B-61).module's new parameter has a default, soMcpEndpointTestis unchanged.reuseAddress = trueon the engine, and a pre-start bind of port 8080 with the same flag (HttpListener.kt,listenRefusal):SIGABRT(kore B-59);TIME_WAIT(kore B-62).awaitPort()used to wait out thatTIME_WAITfor 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_HOSTand 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), inRELEASE_CONSUMERS, beside the report queue and a stage before the pool closes. They used to stop inRELEASE_TELEMETRY, afterRELEASE_POOLS, so aSELECT 1could run against a closed pool. kore orders stages, not the participants inside a stage.RELEASE_TELEMETRYis now empty and still reportsCOMPLETED; the metrik agent flushes itself onApplicationStopping, inside the drain.The
Imagejob's shutdown step now also requiresRELEASE_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, chart0.7.6/appVersion 0.8.6.Verification
Local runs on macOS:
:server:jvmTest128/128 and:server:nativeTest(macosArm64) 128/128, plus:server:ktlintCheck. The new test isHttpListenerTest: with port 0.0.0.0:N held, the refusal names the port and not the synthetic key.w:lines in the log are the existingmacosX64notices in build scripts.io.ktor:coordinates in:server:dependenciesbefore and after, for bothjvmRuntimeClasspathandnativeCompileKlibraries, and they are identical: Ktor 3.6.0. The only exception isktor-server-websockets:3.5.1, which the MCP SDK brings in, exactly as onmain./health/ready, then sent SIGTERM. The process left by itself after about 2 s with exit code 0: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
Imagejob builds the static binary, runs the smoke test, and then runsdocker stopagainst the transcript check above.Refs: #95