Add Rust CultMesh catalog factories
This commit is contained in:
parent
6229167992
commit
0308167c3e
5 changed files with 98 additions and 13 deletions
|
|
@ -362,11 +362,12 @@ Current progress:
|
|||
Android clients can react to lease changes without treating peer-card contact
|
||||
hints as trust.
|
||||
- Rust now has a small `CultMesh` facade for its substrate role: peer cards,
|
||||
sorted peer catalogs, authority lease catalogs, `rudp://host:port` endpoint
|
||||
parsing, and RUDP client/server construction from endpoint or peer-card
|
||||
contact hints. The facade delegates to the existing Rust RUDP socket
|
||||
transport; discovery contact remains separate from trust, which is still
|
||||
gated by the authority lease catalog.
|
||||
sorted peer catalogs, authority lease catalogs, schema registry factories,
|
||||
shard catalog factories, `rudp://host:port` endpoint parsing, and RUDP
|
||||
client/server construction from endpoint or peer-card contact hints. The
|
||||
facade delegates to the existing Rust schema registry, shard catalog, and RUDP
|
||||
socket transport owners; discovery contact remains separate from trust, which
|
||||
is still gated by the authority lease catalog.
|
||||
- Rust now also has substrate-shaped shard catalog helpers:
|
||||
`CultNetShardDescriptor`, `CultNetShardCatalog`, request filtering by schema
|
||||
id and record key, response creation, response application, and built-in
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ CultMesh.
|
|||
| C# | Reference implementation and production game/server substrate | CultCache typed documents and SoA, CultNet schema-v0, LiteNetLib production path with adapter profile, shared transport profiles, shared RUDP socket transport, RUDP reconnect policy/controller and reconnect-loop helper, LiteNetLib client reconnect-controller adoption, schema-client transport port for service request/response clients, CultMesh node/session/catalog/stream/simulation surfaces | No need to abandon LiteNetLib before the CultNet adapter fully owns production service adoption |
|
||||
| Python | Package runtime, local daemon endpoint, raw interop peer, typed state participant | CultCache/CultNet/CultMesh package surface, schema catalogs, shard catalogs/logs, schema-transport factory for raw client request/subscription flows, local TCP CultMesh server, session/prediction/simulation fact helpers, authority leases, streams, RUDP codec/session/socket transport, RUDP reconnect policy/controller and reconnect-loop helper, schema-v0 MessagePack over RUDP evidence, benchmark evidence against C# cache paths | Universal C# throughput, full C# daemon/server stack, and RUDP as the only public service pipe |
|
||||
| TypeScript | Node/browser-adjacent projection and interop runtime | CultCache parity tests, CultNet schema-v0 peer, advertised schema/shard catalog wire contracts plus request/sync helpers, transport profiles, TCP-framed transport port and peer helper, shared RUDP socket transport, RUDP reconnect policy/controller, RUDP reconnect-loop helper, branded CultMesh node/schema/shard/Verse/peer/authority/stream ergonomics | Full C# game session/server stack |
|
||||
| Rust | Low-level cache/transport/runtime substrate | CultCache/CultNet interop lane, schema and shard catalog helpers, transport profiles, TCP-framed port, shared RUDP codec/session/socket transport, RUDP reconnect policy/controller and reconnect-loop helper, schema-v0 MessagePack over RUDP evidence, small CultMesh facade for peer cards, authority leases, RUDP endpoint parsing, and peer-card RUDP client construction | Full CultMesh game-session/server facade, stream catalog, or production game-session server |
|
||||
| Rust | Low-level cache/transport/runtime substrate | CultCache/CultNet interop lane, schema and shard catalog helpers, transport profiles, TCP-framed port, shared RUDP codec/session/socket transport, RUDP reconnect policy/controller and reconnect-loop helper, schema-v0 MessagePack over RUDP evidence, small CultMesh facade for schema registry, shard catalog, peer cards, authority leases, RUDP endpoint parsing, and peer-card RUDP client construction | Full CultMesh game-session/server facade, stream catalog, or production game-session server |
|
||||
| Kotlin | JVM/Android client substrate | Typed MessagePack cache, built-in schema catalog advertisement, schema/shard catalogs with shared schema-message transport fetch/sync helpers, authority leases, stream catalog, branded `CultMesh` facade, WebSocket transport profile/connection helper, RUDP client/server sugar, RUDP reconnect policy/controller and reconnect-loop helper, schema-v0 MessagePack over RUDP evidence | C# SoA store, full C# server daemon, or Unity hot-loop memory layout |
|
||||
|
||||
## Evidence Gates
|
||||
|
|
|
|||
|
|
@ -56,10 +56,11 @@ surface:
|
|||
- shard catalog request/response messages
|
||||
- the canonical `ghostlight.agent-state` document payload schema
|
||||
|
||||
Use `builtin_schema_registry()` when you want the standard catalog, or register
|
||||
your own closed-world schema set with `CultNetSchemaRegistry`. Discovery stays
|
||||
explicit on purpose: peers advertise only the contracts they were compiled to
|
||||
understand, the same way CultCache only consumes the document types you
|
||||
Use `builtin_schema_registry()` or `CultMesh::create_builtin_schema_registry()`
|
||||
when you want the standard catalog, or register your own closed-world schema set
|
||||
with `CultNetSchemaRegistry` / `CultMesh::create_schema_registry()`. Discovery
|
||||
stays explicit on purpose: peers advertise only the contracts they were compiled
|
||||
to understand, the same way CultCache only consumes the document types you
|
||||
registered instead of pretending polymorphism is a public park.
|
||||
|
||||
## Shard Catalogs
|
||||
|
|
@ -68,9 +69,9 @@ Rust now exposes the same shard topology vocabulary as the other runtimes
|
|||
without claiming to be the full C# service body:
|
||||
|
||||
```rust
|
||||
use cultnet_rs::{CultNetMessage, CultNetShardCatalog, CultNetShardDescriptor};
|
||||
use cultnet_rs::{CultMesh, CultNetMessage, CultNetShardDescriptor};
|
||||
|
||||
let mut catalog = CultNetShardCatalog::new();
|
||||
let mut catalog = CultMesh::create_shard_catalog();
|
||||
catalog.upsert(CultNetShardDescriptor {
|
||||
shard_id: "notes-a".to_string(),
|
||||
owner_runtime_id: "rust-primary".to_string(),
|
||||
|
|
@ -123,9 +124,16 @@ contact and authority ergonomics:
|
|||
|
||||
```rust
|
||||
use cultnet_rs::{
|
||||
CultMesh, CultMeshPeerCard, CultMeshRudpSocketOptions,
|
||||
CultMesh, CultMeshPeerCard, CultMeshRudpSocketOptions, CultNetSchemaKind,
|
||||
};
|
||||
|
||||
let schemas = CultMesh::create_builtin_schema_registry()?;
|
||||
let shared_contracts = schemas.list(&cultnet_rs::CultNetSchemaCatalogOptions {
|
||||
include_schema_json: false,
|
||||
schema_ids: None,
|
||||
kinds: Some(vec![CultNetSchemaKind::SharedContract]),
|
||||
});
|
||||
|
||||
let mut server = CultMesh::create_rudp_server(
|
||||
"rust-server",
|
||||
0x1020_3040,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ use std::time::Duration;
|
|||
use crate::CultNetRudpSocketMode;
|
||||
use crate::CultNetRudpSocketTransportConnection;
|
||||
use crate::CultNetRudpSocketTransportOptions;
|
||||
use crate::CultNetSchemaRegistry;
|
||||
use crate::CultNetShardCatalog;
|
||||
use crate::builtin_schema_registry;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct CultMeshPeerCard {
|
||||
|
|
@ -236,6 +239,18 @@ impl Default for CultMeshRudpSocketOptions {
|
|||
pub struct CultMesh;
|
||||
|
||||
impl CultMesh {
|
||||
pub fn create_schema_registry() -> CultNetSchemaRegistry {
|
||||
CultNetSchemaRegistry::new()
|
||||
}
|
||||
|
||||
pub fn create_builtin_schema_registry() -> Result<CultNetSchemaRegistry> {
|
||||
builtin_schema_registry()
|
||||
}
|
||||
|
||||
pub fn create_shard_catalog() -> CultNetShardCatalog {
|
||||
CultNetShardCatalog::new()
|
||||
}
|
||||
|
||||
pub fn create_peer_catalog() -> CultMeshPeerCatalog {
|
||||
CultMeshPeerCatalog::new()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ use cultnet_rs::CultNetRudpSocketMode;
|
|||
use cultnet_rs::CultNetRudpSocketTransportConnection;
|
||||
use cultnet_rs::CultNetRudpSocketTransportOptions;
|
||||
use cultnet_rs::CultNetSchemaKind;
|
||||
use cultnet_rs::CultNetSchemaRegistration;
|
||||
use cultnet_rs::CultNetSchemaRegistry;
|
||||
use cultnet_rs::CultNetSecret;
|
||||
use cultnet_rs::CultNetServerSecurityOptions;
|
||||
|
|
@ -1184,6 +1185,66 @@ fn cultmesh_facade_creates_rudp_client_from_peer_endpoint() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cultmesh_facade_exposes_schema_registry_and_shard_catalog_owners() -> Result<()> {
|
||||
let mut schemas = CultMesh::create_schema_registry();
|
||||
schemas.register(CultNetSchemaRegistration {
|
||||
schema_id: "rust.cultmesh.note.v1".to_string(),
|
||||
kind: CultNetSchemaKind::DocumentPayload,
|
||||
wire_contracts: vec![CultNetWireContract::CultNetSchemaV0],
|
||||
schema_version: Some("rust.cultmesh.note.v1".to_string()),
|
||||
document_type: Some("rust.cultmesh.note".to_string()),
|
||||
title: Some("Rust CultMesh Note".to_string()),
|
||||
schema_json: Some(
|
||||
r#"{"$id":"rust.cultmesh.note.v1","type":"object","properties":{"body":{"type":"string"}}}"#
|
||||
.to_string(),
|
||||
),
|
||||
})?;
|
||||
assert_eq!(
|
||||
schemas
|
||||
.get("rust.cultmesh.note.v1", false)
|
||||
.expect("registered schema is discoverable")
|
||||
.document_type
|
||||
.as_deref(),
|
||||
Some("rust.cultmesh.note")
|
||||
);
|
||||
|
||||
let builtins = CultMesh::create_builtin_schema_registry()?;
|
||||
let shared_contracts = builtins.list(&cultnet_rs::CultNetSchemaCatalogOptions {
|
||||
include_schema_json: false,
|
||||
schema_ids: None,
|
||||
kinds: Some(vec![CultNetSchemaKind::SharedContract]),
|
||||
});
|
||||
assert!(shared_contracts.iter().any(|schema| {
|
||||
schema.schema_id
|
||||
== "https://github.com/GameCult/cultnet-ts/contracts/cultnet.transport-profile.schema.json"
|
||||
&& schema.schema_version.as_deref() == Some("cultnet.transport_profile.v0")
|
||||
}));
|
||||
|
||||
let mut shards = CultMesh::create_shard_catalog();
|
||||
shards.upsert(CultNetShardDescriptor {
|
||||
shard_id: "rust-notes-a".to_string(),
|
||||
owner_runtime_id: "rust-cultmesh".to_string(),
|
||||
epoch: 7,
|
||||
is_primary: Some(true),
|
||||
schema_ids: vec!["rust.cultmesh.note.v1".to_string()],
|
||||
key_prefix: Some("note:".to_string()),
|
||||
primary_endpoints: vec!["rudp://127.0.0.1:4100".to_string()],
|
||||
replica_endpoints: Vec::new(),
|
||||
read_replica_endpoints: Vec::new(),
|
||||
region: None,
|
||||
authority_lease_id: Some("lease:rust-notes-a".to_string()),
|
||||
})?;
|
||||
let matching = shards.list(&cultnet_rs::CultNetShardCatalogOptions {
|
||||
schema_ids: Some(vec!["rust.cultmesh.note.v1".to_string()]),
|
||||
record_keys: Some(vec!["note:1".to_string()]),
|
||||
});
|
||||
assert_eq!(matching.len(), 1);
|
||||
assert_eq!(matching[0].shard_id, "rust-notes-a");
|
||||
assert!(shards.get("rust-notes-a").is_some());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cultmesh_authority_leases_gate_peer_contact_hints() -> Result<()> {
|
||||
let now = Utc::now();
|
||||
|
|
|
|||
Loading…
Reference in a new issue