Skip to content

Commit 753a0d7

Browse files
cevianclaude
andcommitted
fix: use DATABASE_SCHEMA as single source of truth for DBOS schema name
The MCP listRuns/getRun/getTrace tools were resolving the DBOS schema via getSchemaName(getAppName()), which reads package.json from cwd and falls back to "crayon_dbos". On cloud machines the MCP server's cwd often lacks the right package.json, causing queries against the wrong schema and returning empty results. Now all paths (runtime, CLI, MCP tools) read DATABASE_SCHEMA from .env via getDbosSchema(). Removed the redundant getSchemaName() helper and made DBOSConfig.appName required. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8a9cdff commit 753a0d7

File tree

10 files changed

+23
-20
lines changed

10 files changed

+23
-20
lines changed

packages/core/src/__tests__/dbos.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@ vi.mock("@dbos-inc/dbos-sdk", () => ({
1313
describe("DBOS integration", () => {
1414
beforeEach(() => {
1515
vi.clearAllMocks();
16+
process.env.DATABASE_SCHEMA = "test";
1617
});
1718

1819
describe("initializeDBOS()", () => {
1920
it("configures and launches DBOS with database URL", async () => {
2021
const { DBOS } = await import("@dbos-inc/dbos-sdk");
2122
const { initializeDBOS } = await import("../dbos.js");
2223

23-
await initializeDBOS({ databaseUrl: "postgres://localhost/test" });
24+
await initializeDBOS({ databaseUrl: "postgres://localhost/test", appName: "test" });
2425

2526
expect(DBOS.setConfig).toHaveBeenCalledWith(
2627
expect.objectContaining({

packages/core/src/__tests__/factory.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ vi.mock("@dbos-inc/dbos-sdk", () => ({
2525
describe("createCrayon()", () => {
2626
beforeEach(() => {
2727
vi.clearAllMocks();
28+
process.env.DATABASE_SCHEMA = "test";
2829
// Clear globalThis singleton so each test gets a fresh createCrayon()
2930
delete (globalThis as Record<symbol, unknown>)[Symbol.for("crayon.crayonInstance")];
3031
// Clear workflow cache so Workflow.create() re-registers

packages/core/src/__tests__/integration.e2e.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { createCrayon, Workflow, Node, type Crayon } from "../index.js";
99

1010
const DATABASE_URL = process.env.DATABASE_URL;
1111

12-
// Schema used by tests (must match default from getSchemaName())
12+
// Schema used by tests (must match DATABASE_SCHEMA env or getDbosSchema())
1313
const TEST_SCHEMA = "crayon_dbos";
1414

1515
async function resetDatabase(): Promise<void> {
@@ -99,6 +99,7 @@ describe.skipIf(!DATABASE_URL)("crayon e2e", () => {
9999
let crayon: Crayon;
100100

101101
beforeAll(async () => {
102+
process.env.DATABASE_SCHEMA = "crayon";
102103
// Drop DBOS schema for clean test state
103104
await resetDatabase();
104105

packages/core/src/__tests__/integration.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ describe.skipIf(!DATABASE_URL)("crayon integration", () => {
8686
let crayon: Crayon;
8787

8888
beforeAll(async () => {
89+
process.env.DATABASE_SCHEMA = "integration_test";
8990
await resetDatabase();
9091

9192
crayon = await createCrayon({

packages/core/src/cli/__tests__/runs.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ describe.skipIf(!DATABASE_URL)("runs", () => {
4444
let crayon: Crayon;
4545

4646
beforeAll(async () => {
47+
process.env.DATABASE_SCHEMA = TEST_APP_NAME;
4748
await resetDatabase();
4849

4950
crayon = await createCrayon({

packages/core/src/cli/app.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,10 @@ export function getAppSchema(projectRoot?: string): string {
5959
);
6060
}
6161
}
62+
63+
/**
64+
* Get the DBOS system schema name (e.g. "my_app_dbos") from DATABASE_SCHEMA.
65+
*/
66+
export function getDbosSchema(projectRoot?: string): string {
67+
return `${getAppSchema(projectRoot)}_dbos`;
68+
}

packages/core/src/cli/runs.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// packages/cli/src/runs.ts
22
import pg from "pg";
3-
import { getSchemaName } from "../index.js";
4-
import { getAppName } from "./app.js";
3+
import { getDbosSchema } from "./app.js";
54

65
export interface WorkflowRun {
76
workflow_uuid: string;
@@ -27,7 +26,7 @@ export async function listRuns(
2726
options: ListRunsOptions = {}
2827
): Promise<WorkflowRun[]> {
2928
const { limit = 20, workflowName, schema: schemaOverride } = options;
30-
const schema = schemaOverride ?? getSchemaName(getAppName());
29+
const schema = schemaOverride ?? getDbosSchema();
3130
const client = new pg.Client({ connectionString: databaseUrl });
3231

3332
await client.connect();
@@ -69,7 +68,7 @@ export async function getRun(
6968
runId: string,
7069
schemaOverride?: string
7170
): Promise<GetRunResult> {
72-
const schema = schemaOverride ?? getSchemaName(getAppName());
71+
const schema = schemaOverride ?? getDbosSchema();
7372
const client = new pg.Client({ connectionString: databaseUrl });
7473

7574
await client.connect();

packages/core/src/cli/trace.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
// packages/cli/src/trace.ts
22
import pg from "pg";
33
import pc from "picocolors";
4-
import { getSchemaName } from "../index.js";
5-
import { getAppName } from "./app.js";
4+
import { getDbosSchema } from "./app.js";
65
import { getRun, type WorkflowRun } from "./runs.js";
76

87
export interface WorkflowTrace extends WorkflowRun {
@@ -56,7 +55,7 @@ async function getTraceData(
5655
workflowUuid: string,
5756
schemaOverride?: string
5857
): Promise<TraceResult> {
59-
const schema = schemaOverride ?? getSchemaName(getAppName());
58+
const schema = schemaOverride ?? getDbosSchema();
6059
const client = new pg.Client({ connectionString: databaseUrl });
6160

6261
await client.connect();

packages/core/src/dbos.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,20 @@
11
// packages/core/src/dbos.ts
22
import { DBOS } from "@dbos-inc/dbos-sdk";
3+
import { getDbosSchema } from "./cli/app.js";
34

45
export interface DBOSConfig {
56
databaseUrl: string;
6-
appName?: string;
7-
}
8-
9-
/** Get the schema name for a given app */
10-
export function getSchemaName(appName?: string): string {
11-
const name = appName ?? "crayon";
12-
// Convert to valid schema name: lowercase, replace non-alphanumeric with underscore
13-
return `${name.toLowerCase().replace(/[^a-z0-9]/g, "_")}_dbos`;
7+
appName: string;
148
}
159

1610
/**
1711
* Initialize DBOS with the given configuration
1812
*/
1913
export async function initializeDBOS(config: DBOSConfig): Promise<void> {
2014
DBOS.setConfig({
21-
name: config.appName ?? "crayon",
15+
name: config.appName,
2216
systemDatabaseUrl: config.databaseUrl,
23-
systemDatabaseSchemaName: getSchemaName(config.appName),
17+
systemDatabaseSchemaName: getDbosSchema(),
2418
logLevel: process.env.LOG_LEVEL ?? "info",
2519
});
2620
await DBOS.launch();

packages/core/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ export const VERSION = "0.1.0";
44

55
// Factory
66
export { createCrayon } from "./factory.js";
7-
export { getSchemaName } from "./dbos.js";
87

98
// Discovery (CLI / non-bundled environments)
109
export { discover } from "./discover.js";

0 commit comments

Comments
 (0)