Add Python CultMesh client facade parity
This commit is contained in:
parent
87f7868af1
commit
bd50ecd15b
7 changed files with 74 additions and 3 deletions
|
|
@ -17,6 +17,10 @@ CultCache, CultNet, and CultMesh. It is evidence, not confetti.
|
|||
- Python CultMesh discovery client:
|
||||
Fetches Verse catalogs and peer exchange responses from the live Python
|
||||
endpoint over CultNet frames.
|
||||
- Python CultMesh facade:
|
||||
Exposes C#-matching client entrypoints for Verse discovery, peer exchange,
|
||||
raw CultNet client construction, local nodes, catalogs, sessions, streams,
|
||||
authority leases, and simulation fact commits.
|
||||
- Python CultMesh committed simulation facts:
|
||||
The live interop harness sends Python a simulation observation, receives a
|
||||
consensus candidate, then requests the committed `gamecult.mesh.simulation_fact`
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ local prediction reconciliation:
|
|||
```python
|
||||
from cultcache_py import define_database_entry_type
|
||||
from cultnet_py import CultNetClientAuthorityScope, CultNetRawClient
|
||||
from cultmesh_py import CultMesh, CultMeshDiscoveryClient, CultMeshGameSessionOptions, peer_exchange_request
|
||||
from cultmesh_py import CultMesh, CultMeshGameSessionOptions, peer_exchange_request
|
||||
|
||||
note_doc = define_database_entry_type("mesh.note", [("body", 0)])
|
||||
node = CultMesh.start_node("mesh.cc", runtime_id="python-runtime")
|
||||
|
|
@ -232,7 +232,7 @@ delete_message = node.delete_raw_message(note_doc, "note:2", shard_id="interop",
|
|||
peers = CultMesh.create_peer_catalog()
|
||||
response = peers.create_response(peer_exchange_request("pex-1", verse_id="local"))
|
||||
|
||||
client = CultMeshDiscoveryClient("127.0.0.1", 3075)
|
||||
client = CultMesh.create_verse_discovery_client("127.0.0.1", 3075)
|
||||
verses = client.fetch_verses(transport_version="cultmesh.v0")
|
||||
mesh_peers = client.fetch_peers(verse_id="python-interop", roles=["read-replica"])
|
||||
client.sync_peer_catalog(peers, verse_id="python-interop", roles=["read-replica"])
|
||||
|
|
|
|||
|
|
@ -30,8 +30,10 @@ EXPECTED_EXPORTS: dict[str, tuple[str, ...]] = {
|
|||
"cultmesh_py": (
|
||||
"CultMesh",
|
||||
"CultMeshGameSession",
|
||||
"CultMeshPeerExchangeClient",
|
||||
"CultMeshSimulationFact",
|
||||
"CultMeshStreamCatalog",
|
||||
"CultMeshVerseDiscoveryClient",
|
||||
"simulation_fact_document",
|
||||
),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from .client import CultMeshDiscoveryClient
|
||||
from .client import CultMeshDiscoveryClient, CultMeshPeerExchangeClient, CultMeshVerseDiscoveryClient
|
||||
from .facade import CultMesh
|
||||
from .node import CultMeshNode, create_node
|
||||
from .session import (
|
||||
|
|
@ -53,6 +53,8 @@ __all__ = [
|
|||
"CultMeshAuthorityLease",
|
||||
"CultMeshAuthorityLeaseCatalog",
|
||||
"CultMeshDiscoveryClient",
|
||||
"CultMeshPeerExchangeClient",
|
||||
"CultMeshVerseDiscoveryClient",
|
||||
"CultMeshStreamCatalog",
|
||||
"CultMeshStreamConsumerProfile",
|
||||
"CultMeshStreamDescriptor",
|
||||
|
|
|
|||
|
|
@ -114,3 +114,11 @@ class CultMeshDiscoveryClient:
|
|||
limit=limit,
|
||||
)
|
||||
return catalog.apply_response(response)
|
||||
|
||||
|
||||
class CultMeshVerseDiscoveryClient(CultMeshDiscoveryClient):
|
||||
pass
|
||||
|
||||
|
||||
class CultMeshPeerExchangeClient(CultMeshDiscoveryClient):
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@ from __future__ import annotations
|
|||
|
||||
from pathlib import Path
|
||||
|
||||
from cultnet_py import CultNetRawClient
|
||||
|
||||
from .client import CultMeshPeerExchangeClient, CultMeshVerseDiscoveryClient
|
||||
from .node import CultMeshNode, create_node
|
||||
from .session import CultMeshGameSession, CultMeshGameSessionOptions
|
||||
from .simulation import CultMeshSimulationFactCommitter
|
||||
|
|
@ -38,6 +41,24 @@ class CultMesh:
|
|||
def create_stream_catalog() -> CultMeshStreamCatalog:
|
||||
return CultMeshStreamCatalog()
|
||||
|
||||
@staticmethod
|
||||
def create_verse_discovery_client(
|
||||
host: str = "localhost",
|
||||
port: int = 3075,
|
||||
*,
|
||||
timeout_seconds: float = 4.0,
|
||||
) -> CultMeshVerseDiscoveryClient:
|
||||
return CultMeshVerseDiscoveryClient(host, port, timeout_seconds)
|
||||
|
||||
@staticmethod
|
||||
def create_peer_exchange_client(
|
||||
host: str = "localhost",
|
||||
port: int = 3075,
|
||||
*,
|
||||
timeout_seconds: float = 4.0,
|
||||
) -> CultMeshPeerExchangeClient:
|
||||
return CultMeshPeerExchangeClient(host, port, timeout_seconds)
|
||||
|
||||
@staticmethod
|
||||
def create_simulation_fact_committer(node: CultMeshNode) -> CultMeshSimulationFactCommitter:
|
||||
return CultMeshSimulationFactCommitter(node)
|
||||
|
|
@ -48,3 +69,21 @@ class CultMesh:
|
|||
options: CultMeshGameSessionOptions | None = None,
|
||||
) -> CultMeshGameSession:
|
||||
return CultMeshGameSession(node, options)
|
||||
|
||||
@staticmethod
|
||||
def create_client(
|
||||
host: str = "localhost",
|
||||
port: int = 3075,
|
||||
*,
|
||||
timeout_seconds: float = 4.0,
|
||||
) -> CultNetRawClient:
|
||||
return CultNetRawClient(host, port, timeout_seconds)
|
||||
|
||||
@staticmethod
|
||||
def connect_client(
|
||||
host: str = "localhost",
|
||||
port: int = 3075,
|
||||
*,
|
||||
timeout_seconds: float = 4.0,
|
||||
) -> CultNetRawClient:
|
||||
return CultNetRawClient(host, port, timeout_seconds)
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ from cultmesh_py import (
|
|||
CultMeshAuthorityLease,
|
||||
CultMeshAuthorityLeaseCatalog,
|
||||
CultMeshDiscoveryClient,
|
||||
CultMeshPeerExchangeClient,
|
||||
CultMeshStreamCatalog,
|
||||
CultMeshStreamConsumerProfile,
|
||||
CultMeshStreamDescriptor,
|
||||
|
|
@ -61,6 +62,7 @@ from cultmesh_py import (
|
|||
CultMeshVerseCatalog,
|
||||
CultMeshVerseCompatibility,
|
||||
CultMeshVerseDescriptor,
|
||||
CultMeshVerseDiscoveryClient,
|
||||
peer_exchange_request,
|
||||
simulation_fact_document,
|
||||
verse_catalog_request,
|
||||
|
|
@ -884,6 +886,20 @@ class CultCacheTests(unittest.TestCase):
|
|||
self.assertIsInstance(CultMesh.create_peer_catalog(), CultMeshPeerCatalog)
|
||||
self.assertIsInstance(CultMesh.create_authority_lease_catalog(), CultMeshAuthorityLeaseCatalog)
|
||||
self.assertIsInstance(CultMesh.create_stream_catalog(), CultMeshStreamCatalog)
|
||||
verse_client = CultMesh.create_verse_discovery_client("127.0.0.1", 4010, timeout_seconds=1.5)
|
||||
peer_client = CultMesh.create_peer_exchange_client("127.0.0.1", 4011, timeout_seconds=1.5)
|
||||
raw_client = CultMesh.create_client("127.0.0.1", 4012, timeout_seconds=1.5)
|
||||
connected_client = CultMesh.connect_client("127.0.0.1", 4013, timeout_seconds=1.5)
|
||||
self.assertIsInstance(verse_client, CultMeshVerseDiscoveryClient)
|
||||
self.assertIsInstance(peer_client, CultMeshPeerExchangeClient)
|
||||
self.assertIsInstance(verse_client, CultMeshDiscoveryClient)
|
||||
self.assertIsInstance(peer_client, CultMeshDiscoveryClient)
|
||||
self.assertIsInstance(raw_client, CultNetRawClient)
|
||||
self.assertIsInstance(connected_client, CultNetRawClient)
|
||||
self.assertEqual((verse_client.host, verse_client.port, verse_client.timeout_seconds), ("127.0.0.1", 4010, 1.5))
|
||||
self.assertEqual((peer_client.host, peer_client.port, peer_client.timeout_seconds), ("127.0.0.1", 4011, 1.5))
|
||||
self.assertEqual((raw_client.host, raw_client.port, raw_client.timeout_seconds), ("127.0.0.1", 4012, 1.5))
|
||||
self.assertEqual((connected_client.host, connected_client.port, connected_client.timeout_seconds), ("127.0.0.1", 4013, 1.5))
|
||||
|
||||
def test_cultmesh_simulation_fact_uses_csharp_slot_contract(self) -> None:
|
||||
import msgpack # type: ignore
|
||||
|
|
|
|||
Loading…
Reference in a new issue