Chapter 2 โ Start the First Runtime
Chapter objective: After completing this chapter, a developer can build a single-node
DsmRuntime, registerroute-hints, and explain exactly what a successful local write means.
Learning objectives
- Identify the responsibilities of Runtime, membership, and collection spec.
- Apply the build, register, start, and close order.
- Write and read the first
RouteHint. - Distinguish local API success from remote visibility.
Prerequisites
- Completion of the Chapter 1 responsibility classification.
- JDK 25; the example repository already includes Maven Wrapper.
Case progress
The fulfillment gateway publishes
fulfillment-primary โ 10.0.0.8:8080. This chapter stores
and reads the hint on one node. Network propagation comes later.
Four lifecycle steps
DsmRuntimeBuilder assembles the runtime.
ClusterMembership supplies node identity and communication.
CollectionSpec gives a collection a stable locator and
schema. DsmRegister is the business-facing typed
handle.
NodeInfo self = new NodeInfo("gateway-a", "127.0.0.1", 19090);
DsmRuntime runtime = DsmRuntimeBuilder.builder()
.clusterId("fulfillment-local")
.serviceId("gateway")
.membership(new StandaloneClusterMembership(self))
.build();
CollectionSpec<RouteHint> routes =
CollectionSpecBuilder.<RouteHint>register("demo", "gateway", "route-hints")
.schemaId("route-hints/v1")
.recordCodec(RouteHint.class)
.build();
DsmRegister<RouteHint> register = runtime.register(routes);
runtime.start();Register collections before startup so the Runtime knows the schema
when it enters RUNNING. Call close() after
use. Tests and examples should use try/finally or an
equivalent resource boundary.
First local commit
register.put(new RouteHint(
"fulfillment-primary",
EntityMetadata.empty(),
"10.0.0.8:8080"));
String address = register.get("fulfillment-primary")
.orElseThrow()
.address();The return from put means that this node accepted the
local change. It does not report a replication acknowledgement count or
promise that another node can already read the value. Single-node
membership creates no remote replica.
Counterexample and fault injection
Treat the Runtime as externally ready before
runtime.start(), or omit close(). The first
mistake confuses completed configuration with an operational Runtime.
The second leaks threads and resources. A successful local
get also does not establish cluster-wide agreement.
Experiment
Run the upstream Runtime/REPL example test:
cd submodule/dsm-examples/basic-usage-examples
./mvnw -q -Dtest=DsmReplTest testThe command handler can store and list entries while the test creates and closes the Runtime explicitly. It uses controlled fake peers, so success proves the in-process path only, not real networking.
Experiment acceptance card
| Field | Content |
|---|---|
| Command | cd submodule/dsm-examples/basic-usage-examples && ./mvnw -q -Dtest=DsmReplTest test |
| Input or fault | Single-node reads/writes and controlled test peers |
| Observable result | All three DsmReplTest cases pass and Runtime closes
explicitly |
| Evidence level | E2: fixed-source in-process behavior |
| Not proven | Real networking, production discovery, remote write acknowledgement, or capacity |
Review
- Runtime owns the lifecycle of collections and node cooperation.
- Collection specs are registered before
start()and accessed through typed handles. - Local
putsuccess proves a local commit, not remote visibility. - Examples close Runtime so resource leaks do not hide behind a green test.
Next
Chapter 3 divides RouteHint into entry identity, entity
fields, metadata, codec, and schema so both sides of replication
interpret the same state.