Name the engine already on the port instead of quietly taking the next one
`serve` moved off a port something else held and said so, which made starting a second engine for one installation look like it had worked — two engines on one SQLite file, which is not a supported shape. A serving engine now records its pid beside its data, and a taken default port is asked who it is: this directory's own engine is named and nothing is started, another installation's Fluksio is named and the move happens anyway, and anything else reads as it did before. Whose engine it is is settled by the token, which is signed with this directory's secret key — so a foreign one is only ever named, never stopped from here. A directory with no credential yet asks unauthenticated, and its answer is foreign, which is the side that stops nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019Hra4ndWMCLU5F3KjUuVAc
This commit is contained in:
@@ -567,6 +567,58 @@ def test_run_and_sweep_take_what_to_sync() -> None:
|
||||
assert parser.parse_args(["sweep", "train"]).sync == []
|
||||
|
||||
|
||||
def test_a_serving_engine_records_itself_until_it_stops(tmp_path) -> None:
|
||||
"""A pid nobody is running is the same as no pidfile at all."""
|
||||
import os
|
||||
|
||||
from fluksio.cli import PIDFILE, read_pidfile, write_pidfile
|
||||
|
||||
assert read_pidfile(tmp_path) is None
|
||||
|
||||
written = write_pidfile(tmp_path, 8000)
|
||||
assert read_pidfile(tmp_path) == {"pid": os.getpid(), "port": 8000}
|
||||
|
||||
# Killed outright: the file outlives the process it names.
|
||||
written.write_text('{"pid": 2147483646, "port": 8000}')
|
||||
assert read_pidfile(tmp_path) is None
|
||||
|
||||
written.write_text("not json")
|
||||
assert read_pidfile(tmp_path) is None
|
||||
|
||||
|
||||
def test_who_holds_the_port_is_told_apart_by_the_token(tmp_path) -> None:
|
||||
"""Only this directory's own engine may be reported as already up.
|
||||
|
||||
The token is signed with this directory's secret key, so an engine that
|
||||
accepts it is one reading this directory's database. Another
|
||||
installation's Fluksio answers the health check and refuses it.
|
||||
"""
|
||||
import httpx
|
||||
|
||||
from fluksio.cli import probe_engine
|
||||
|
||||
def engine(health: int, summary: int):
|
||||
def handle(request: httpx.Request) -> httpx.Response:
|
||||
if request.url.path.endswith("/health-check/"):
|
||||
return httpx.Response(health)
|
||||
return httpx.Response(summary)
|
||||
|
||||
return httpx.Client(transport=httpx.MockTransport(handle))
|
||||
|
||||
with engine(200, 200) as client:
|
||||
assert probe_engine("http://x", "t", client) == "ours"
|
||||
with engine(200, 401) as client:
|
||||
assert probe_engine("http://x", "t", client) == "foreign"
|
||||
# A directory with no credential yet cannot prove anything is its own, and
|
||||
# `Bearer ` is not a legal header value — so it asks without one.
|
||||
with engine(200, 401) as client:
|
||||
assert probe_engine("http://x", "", client) == "foreign"
|
||||
# Somebody else's dev server, or nothing listening at all.
|
||||
with engine(404, 404) as client:
|
||||
assert probe_engine("http://x", "t", client) == "other"
|
||||
assert probe_engine("http://127.0.0.1:1", "t") == "other"
|
||||
|
||||
|
||||
def test_serve_moves_off_a_port_that_is_taken() -> None:
|
||||
"""A first start should not die on somebody else's dev server."""
|
||||
import socket
|
||||
|
||||
Reference in New Issue
Block a user