From afdbeb7d03f0a3867513eb50f518f4e3aa091c2a Mon Sep 17 00:00:00 2001 From: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Date: Tue, 23 Jun 2026 00:39:36 +0800 Subject: [PATCH] feat(cli): forward env-driven cluster driver to the runtime in `os serve` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `os serve` constructed the Runtime without a cluster config, so it always used the in-memory cluster driver — a multi-replica deployment could not coordinate (and the split-brain guard blocked it). `os serve` now reads OS_CLUSTER_DRIVER (+ OS_REDIS_URL), dynamically imports the matching remote driver package (so it works in both config-boot and compiled-artifact mode), and forwards the cluster config to the Runtime. Open-core ships only the in-memory driver; remote drivers (e.g. @objectstack/service-cluster-redis) are provided by the EE distribution — absent ⇒ graceful fallback to in-memory. Verified via A/B boot (local redis): with OS_CLUSTER_DRIVER=redis + replicas=2 the server boots (guard passes = redis active); without it, replicas=2 trips the split-brain guard (memory). Enables the EE multi-node activation (cloud ADR-0018) of the cache-invalidation (#2213) and scheduler-leader-election (#2219) seams. Co-Authored-By: Claude Opus 4.8 --- packages/cli/src/commands/serve.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/commands/serve.ts b/packages/cli/src/commands/serve.ts index c7a6d3a07f..626c9857f5 100644 --- a/packages/cli/src/commands/serve.ts +++ b/packages/cli/src/commands/serve.ts @@ -531,10 +531,23 @@ export default class Serve extends Command { }), }; + // Cluster wiring: env-driven driver selection (mirrors OS_DATABASE_URL). + // The remote driver self-registers on import; import it dynamically so it + // works in BOTH config-boot and compiled-artifact mode. Open-core ships + // only the in-memory driver — remote drivers (e.g. redis) come from the EE + // distribution; if absent we fall back to the in-memory cluster. + let clusterConfig: { driver: string; url?: string } | undefined; + const __clusterDriver = process.env.OS_CLUSTER_DRIVER?.trim(); + if (__clusterDriver && __clusterDriver !== 'memory') { + try { await import(`@objectstack/service-cluster-${__clusterDriver}`); } + catch { /* may already be registered by the loaded config */ } + clusterConfig = { driver: __clusterDriver, url: process.env.OS_REDIS_URL }; + } const runtime = new Runtime({ kernel: { logger: loggerConfig - } + }, + cluster: clusterConfig as any, }); const kernel = runtime.getKernel();