7.3 KiB
mishima-nexus-client-csharp
C# client SDK for a remote Mishima Nexus
server: connect via a nexus+*:// URI and get Robotico.Graph / Robotico.Time ports bound to a
logical database over gRPC, plus thin Document/Relational connect helpers.
- NuGet:
Robotico.Nexus.Client - Feed:
https://download.robotico.dev/nuget/v3/index.json - Brokkr:
https://brokkr.robotico.dev/mishima/mishima-nexus-client-csharp
This package does not reference Mishima.Nexus.Node.* (the server host assemblies) — it only
depends on the generated Mishima.Nexus.Wire.V1 gRPC stubs, Robotico.Graph, and Robotico.Time.
Uses
This repository uses:
flowchart LR
mishima_nexus_client_csharp["mishima-nexus-client-csharp"]
mishima_nexus["mishima-nexus"]
mishima_nexus_client_csharp --> mishima_nexus
Used by
This repository is used by:
flowchart LR
mishima_nexus_client_csharp["mishima-nexus-client-csharp"]
mishima_nexus["mishima-nexus"]
mishima_nexus_wpf["mishima-nexus-wpf"]
tanukiarmy_bot_ng["tanukiarmy-bot-ng"]
mishima_nexus_client_csharp --> mishima_nexus
mishima_nexus_client_csharp --> mishima_nexus_wpf
mishima_nexus_client_csharp --> tanukiarmy_bot_ng
Quick start
using Robotico.Nexus.Client;
Result<NexusClient> connected = NexusClient.Connect("nexus+graph://localhost:50051/pathways");
using NexusClient client = connected.ExpectSuccess();
client.CheckHealth().ExpectSuccess();
Result<IGraphSession> opened = client.Graph.Open("pathways");
using IGraphSession session = opened.ExpectSuccess();
session.RegisterLabel("Person").ExpectSuccess();
session.UpsertVertex(1, ["Person"]).ExpectSuccess();
Connection URIs
| Scheme | Plane | Default database (empty path) |
|---|---|---|
nexus+graph:// |
Graph | pathways |
nexus+time:// |
Time | telemetry |
nexus+document:// |
Document | catalog |
nexus+relational:// |
Relational | ledger |
nexus+sql:// |
— | rejected — use Mishima.Nexus.Sql directly |
- The URI host:port is the gRPC endpoint; the port is always explicit (no default port is ever inferred, so a typo can't silently connect to the wrong service).
- The URI path (e.g.
/pathways) is the logical database name, sent as thex-nexus-databasegRPC metadata header on every call — it is not a filesystem path, even though the underlyingIGraphStore/ITimeStoreport parameter is historically nameddatabaseFilePath. - One
NexusClientis bound to a single scheme + logical database from the connect URI. Open a second client to talk to another plane or database.
TLS / mTLS / bearer auth
NexusClientOptions mirrors Mishima.Nexus.Wire.Clients.WireTlsMaterial's environment variables
(same names, no shared assembly dependency):
| Variable | Purpose |
|---|---|
NEXUS_TLS_CA_FILE |
CA certificate PEM (trust root) |
NEXUS_TLS_CLIENT_CERT_FILE |
Client (machine credential) certificate |
NEXUS_TLS_CLIENT_KEY_FILE |
Client private key PEM |
NEXUS_TLS_MODE |
https (default) or insecure |
NEXUS_WIRE_BEARER |
Bearer token attached as Authorization |
NEXUS_WIRE_DEFAULT_BEARER |
Fallback bearer token |
Pass an explicit NexusTlsMaterial / BearerToken via NexusClientOptions to override the
environment. When no TLS material is present and UseHttps is unset, the client dials plaintext
h2c (loopback/dev only).
Create / Open / OpenOrCreate semantics (POLA)
Nexus provisions logical databases lazily — the host creates a database's on-disk state the first time an RPC actually touches it, not via a separate "create database" call on the Graph/Time wire services. This client documents that behavior explicitly rather than pretending otherwise:
Open(name)— pings the engine withx-nexus-database: nameand returns a session bound to that logical name. Succeeds even for a database the host hasn't materialized yet (the host creates it lazily on first write).OpenOrCreate(name)— identical toOpen(name). There is no separate provisioning step to race against, so "open if exists, else create" collapses to "open" once the engine is reachable.Create(name)— fails withNXS_ALREADY_EXISTSwhenPingagainstnamesucceeds, because Nexus'sPingis an engine-liveness probe, not a per-database existence check — once the Graph/Time engine is reachable at all,Createcannot distinguish "database already has data" from "database is merely reachable". UseOpenOrCreatefor greenfield databases instead.
Document / Relational
NexusClient.CreateDocumentClient() / CreateRelationalClient() return small façades (Ping plus,
for Document, single-document upsert/get/delete) — enough for MVP smoke usage. They are not a
full IMishimaDatabase façade. For the complete generated RPC surface, use
CreateDocumentWireClient() / CreateRelationalWireClient(), which return the raw
Mishima.Nexus.Wire.V1 gRPC clients bound to the same channel and x-nexus-database metadata.
Error codes
All failures map to Robotico.Result.Result with NXS_* codes (NexusErrors): NXS_URI_INVALID,
NXS_URI_UNSUPPORTED_SCHEME, NXS_CONNECT_FAILED, NXS_TLS_REJECTED, NXS_ALREADY_EXISTS,
NXS_NOT_FOUND, NXS_INVALID_ARGUMENT, NXS_DISPOSED, NXS_UNAVAILABLE, NXS_WIRE_FAILED.
Robotico.Graph (GR_*) and Robotico.Time (TM_*) codes surface unchanged from the ports.
Quality gate
Same Library 10 bar as other Robotico C# packages:
- Analyzers on (
TreatWarningsAsErrors, Meziantou MA0004/MA0042/MA0155, IDE0008/IDE0090/IDE0301/IDE0330) dotnet testwith coverlet ≥ 90% line coverage onRobotico.Nexus.Client, exercised against an in-process fake gRPC server (Kestrel + in-memory fakeNexusGraphEngineService/NexusTimeEngineService/NexusDocumentEngineService/NexusRelationalEngineService/NexusHealthService) — no live Nexus process required.- Woodpecker / GitHub CI run
bash scripts/woodpecker-verify.sh
Build
bash scripts/woodpecker-verify.sh
bash scripts/pack-release.sh