Advertise Python daemon readiness capabilities
This commit is contained in:
parent
443fe1a6ae
commit
e181259db2
3 changed files with 37 additions and 13 deletions
|
|
@ -104,19 +104,22 @@ CultCache, CultNet, and CultMesh. It is evidence, not confetti.
|
|||
store beside the cache file by default. The `cultmesh-py-daemon` /
|
||||
`python -m cultmesh_py.daemon` entrypoint launches that same local TCP server
|
||||
body and emits a bounded readiness document for process supervisors while the
|
||||
served CultNet endpoint remains the capability owner. The daemon can register
|
||||
and seed the package interop-note document so launched processes advertise a
|
||||
real payload schema and serve both a real snapshot and a real shard-log entry
|
||||
over the same CultNet lane. When launched with a Verse id, it publishes its
|
||||
actual bound endpoint in the Verse and peer catalogs so discovery clients can
|
||||
find the running Python peer without embedding code-owned catalogs. With a
|
||||
cache file and durable shard-log path, a restarted daemon can rehydrate the
|
||||
persisted interop-note snapshot and shard-log entry without reseeding. The
|
||||
launched daemon also accepts raw puts over a live database subscription stream,
|
||||
emits the matching change notification, and records the mutation in the served
|
||||
shard log. If its durable shard log has been compacted, stale shard-log
|
||||
requests return the same explicit `compacted_history` resync boundary over
|
||||
the daemon wire endpoint instead of silently looking empty.
|
||||
served CultNet endpoint remains the capability owner. Readiness now mirrors
|
||||
the served hello capability metadata, shard ids, and configured snapshot
|
||||
limits so supervisors can inspect startup state without inventing a second
|
||||
protocol truth. The daemon can register and seed the package interop-note
|
||||
document so launched processes advertise a real payload schema and serve both
|
||||
a real snapshot and a real shard-log entry over the same CultNet lane. When
|
||||
launched with a Verse id, it publishes its actual bound endpoint in the Verse
|
||||
and peer catalogs so discovery clients can find the running Python peer
|
||||
without embedding code-owned catalogs. With a cache file and durable shard-log
|
||||
path, a restarted daemon can rehydrate the persisted interop-note snapshot and
|
||||
shard-log entry without reseeding. The launched daemon also accepts raw puts
|
||||
over a live database subscription stream, emits the matching change
|
||||
notification, and records the mutation in the served shard log. If its durable
|
||||
shard log has been compacted, stale shard-log requests return the same
|
||||
explicit `compacted_history` resync boundary over the daemon wire endpoint
|
||||
instead of silently looking empty.
|
||||
The daemon CLI snapshot document/byte limits feed the same public server edge;
|
||||
oversized daemon snapshot responses are returned as structured
|
||||
`cultnet.error.v0` peer errors rather than partial payloads.
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ from pathlib import Path
|
|||
from typing import Any
|
||||
|
||||
from cultcache_py.interop import INTEROP_SCHEMA_VERSION, interop_note_document
|
||||
from cultnet_py import hello
|
||||
|
||||
from .facade import CultMesh
|
||||
from .server import CultMeshLocalServer
|
||||
|
|
@ -133,14 +134,23 @@ def advertise_self(
|
|||
|
||||
|
||||
def daemon_ready_document(server: CultMeshLocalServer) -> dict[str, Any]:
|
||||
hello_response = server.handle_message(hello(runtime_id="daemon-ready-probe").to_wire()) or {}
|
||||
return {
|
||||
"schemaVersion": READY_SCHEMA_VERSION,
|
||||
"runtimeId": server.node.runtime_id,
|
||||
"runtimeKind": server.runtime_kind,
|
||||
"displayName": hello_response.get("displayName") or server.node.runtime_id,
|
||||
"host": server.host,
|
||||
"port": server.port,
|
||||
"endpoint": f"cultnet://{server.host}:{server.port}",
|
||||
"shardIds": server.node.database.shard_ids(),
|
||||
"supportedDocumentTypes": [document.type for document in server.node.documents],
|
||||
"supportedMessageVersions": list(hello_response.get("supportedMessageVersions") or ()),
|
||||
"supportedMutationContracts": list(hello_response.get("supportedMutationContracts") or ()),
|
||||
"snapshotLimits": {
|
||||
"maxSnapshotDocuments": server.max_snapshot_documents,
|
||||
"maxSnapshotBytes": server.max_snapshot_bytes,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3082,8 +3082,16 @@ class CultCacheTests(unittest.TestCase):
|
|||
ready = json.loads(ready_path.read_text(encoding="utf-8"))
|
||||
self.assertEqual(ready["schemaVersion"], READY_SCHEMA_VERSION)
|
||||
self.assertEqual(ready["runtimeId"], "daemon-test-peer")
|
||||
self.assertEqual(ready["runtimeKind"], "python")
|
||||
self.assertEqual(ready["displayName"], "Daemon Test Peer")
|
||||
self.assertEqual(ready["endpoint"], f"cultnet://127.0.0.1:{ready['port']}")
|
||||
self.assertEqual(ready["shardIds"], ["daemon-interop"])
|
||||
self.assertEqual(ready["supportedDocumentTypes"], ["cultcache.interop-note"])
|
||||
self.assertIn("cultnet.hello.v0", ready["supportedMessageVersions"])
|
||||
self.assertIn("cultnet.document_put_raw.v0", ready["supportedMessageVersions"])
|
||||
self.assertEqual(ready["supportedMutationContracts"][0]["documentType"], "cultcache.interop-note")
|
||||
self.assertIn("shardLog", ready["supportedMutationContracts"][0]["operations"])
|
||||
self.assertEqual(ready["snapshotLimits"], {"maxSnapshotBytes": None, "maxSnapshotDocuments": None})
|
||||
|
||||
client = CultMesh.create_client("127.0.0.1", int(ready["port"]), timeout_seconds=2.0)
|
||||
hello_response = client.request(
|
||||
|
|
@ -3096,6 +3104,8 @@ class CultCacheTests(unittest.TestCase):
|
|||
self.assertIn("cultnet.hello.v0", hello_response["supportedMessageVersions"])
|
||||
self.assertIn("cultnet.schema_catalog_request.v0", hello_response["supportedMessageVersions"])
|
||||
self.assertEqual(hello_response["supportedDocumentTypes"], ["cultcache.interop-note"])
|
||||
self.assertEqual(ready["supportedMessageVersions"], hello_response["supportedMessageVersions"])
|
||||
self.assertEqual(ready["supportedMutationContracts"], hello_response["supportedMutationContracts"])
|
||||
|
||||
schema_response = client.fetch_schema_catalog(schema_ids=["cultcache.interop-note"], include_schema_json=True)
|
||||
self.assertEqual(schema_response["schemas"][0]["schemaVersion"], INTEROP_SCHEMA_VERSION)
|
||||
|
|
@ -3556,6 +3566,7 @@ class CultCacheTests(unittest.TestCase):
|
|||
)
|
||||
try:
|
||||
ready = self._wait_for_ready_file(process, ready_path)
|
||||
self.assertEqual(ready["snapshotLimits"], {"maxSnapshotBytes": None, "maxSnapshotDocuments": 0})
|
||||
client = CultMesh.create_client("127.0.0.1", int(ready["port"]), timeout_seconds=2.0)
|
||||
|
||||
with self.assertRaisesRegex(CultNetPeerError, "Snapshot document limit exceeded") as raised:
|
||||
|
|
|
|||
Loading…
Reference in a new issue