Merge pull request #2111 from pikasTech/fix/2109-db-write-readiness
fix: 分离 Postgres 写入 readiness 与 durable read readiness
This commit is contained in:
@@ -966,6 +966,37 @@ test("configured postgres runtime allocates Workbench projectedSeq idempotently
|
|||||||
assert.ok(queryClient.calls.some((call) => call.sql.startsWith("SELECT pg_advisory_xact_lock")));
|
assert.ok(queryClient.calls.some((call) => call.sql.startsWith("SELECT pg_advisory_xact_lock")));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("configured postgres runtime writes Workbench facts without re-running blocked read readiness", async () => {
|
||||||
|
const queryClient = createFakePostgresClient({ migrationReady: true, countErrorCode: "53300" });
|
||||||
|
const store = createConfiguredCloudRuntimeStore({
|
||||||
|
env: {
|
||||||
|
HWLAB_CLOUD_RUNTIME_ADAPTER: "postgres",
|
||||||
|
HWLAB_CLOUD_RUNTIME_DURABLE: "true"
|
||||||
|
},
|
||||||
|
dbUrl: "postgres://hwlab_redacted@db.example.invalid:5432/hwlab",
|
||||||
|
queryClient,
|
||||||
|
now: () => "2026-06-25T02:50:00.000Z"
|
||||||
|
});
|
||||||
|
|
||||||
|
const readiness = await store.readiness();
|
||||||
|
assert.equal(readiness.blocker, RUNTIME_DURABLE_ADAPTER_QUERY_BLOCKED);
|
||||||
|
assert.equal(readiness.connection.queryResult, "query_blocked");
|
||||||
|
queryClient.calls.length = 0;
|
||||||
|
|
||||||
|
const write = await store.writeWorkbenchFacts({
|
||||||
|
facts: {
|
||||||
|
sessions: [{ sessionId: "ses_write_after_read_blocked", ownerUserId: "usr_write_after_read_blocked", status: "running", updatedAt: "2026-06-25T02:50:01.000Z" }]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(write.written, true);
|
||||||
|
assert.equal(queryClient.calls.filter((call) => isReadinessQuery(call.sql)).length, 0);
|
||||||
|
assert.equal(queryClient.calls.some((call) => call.sql.startsWith("CREATE INDEX IF NOT EXISTS")), false);
|
||||||
|
assert.ok(queryClient.calls.some((call) => call.sql === "BEGIN"));
|
||||||
|
assert.ok(queryClient.calls.some((call) => call.sql === "COMMIT"));
|
||||||
|
assert.ok(queryClient.calls.some((call) => call.sql.startsWith("INSERT INTO workbench_sessions")));
|
||||||
|
});
|
||||||
|
|
||||||
test("configured postgres runtime reuses proven readiness for Workbench durable reads", async () => {
|
test("configured postgres runtime reuses proven readiness for Workbench durable reads", async () => {
|
||||||
const queryClient = createFakePostgresClient({ migrationReady: true });
|
const queryClient = createFakePostgresClient({ migrationReady: true });
|
||||||
const store = createConfiguredCloudRuntimeStore({
|
const store = createConfiguredCloudRuntimeStore({
|
||||||
@@ -982,6 +1013,7 @@ test("configured postgres runtime reuses proven readiness for Workbench durable
|
|||||||
sessions: [{ sessionId: "ses_ready_cached", ownerUserId: "usr_ready", status: "running", updatedAt: "2026-06-20T10:00:01.000Z" }]
|
sessions: [{ sessionId: "ses_ready_cached", ownerUserId: "usr_ready", status: "running", updatedAt: "2026-06-20T10:00:01.000Z" }]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
await store.readiness();
|
||||||
queryClient.calls.length = 0;
|
queryClient.calls.length = 0;
|
||||||
|
|
||||||
const first = await store.queryWorkbenchFacts({ families: ["sessions"], limit: 10 });
|
const first = await store.queryWorkbenchFacts({ families: ["sessions"], limit: 10 });
|
||||||
@@ -1029,6 +1061,7 @@ test("configured postgres runtime can query thin Workbench session summaries", a
|
|||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
await store.readiness();
|
||||||
queryClient.calls.length = 0;
|
queryClient.calls.length = 0;
|
||||||
|
|
||||||
const loaded = await store.queryWorkbenchFacts({ families: ["sessions"], sessionProjection: "summary", limit: 10 });
|
const loaded = await store.queryWorkbenchFacts({ families: ["sessions"], sessionProjection: "summary", limit: 10 });
|
||||||
|
|||||||
@@ -1533,8 +1533,12 @@ export class PostgresCloudRuntimeStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async assertReadyForWrites() {
|
async assertReadyForWrites() {
|
||||||
const readiness = await this.readiness();
|
if (!this.dbUrl && !this.queryClient) {
|
||||||
if (readiness.ready !== true) {
|
const readiness = this.blockedSummary({
|
||||||
|
blocker: RUNTIME_DURABLE_ADAPTER_UNCONFIGURED,
|
||||||
|
reason: "Postgres runtime adapter is selected but HWLAB_CLOUD_DB_URL is not injected"
|
||||||
|
});
|
||||||
|
this.lastReadiness = readiness;
|
||||||
throw new HwlabProtocolError("Postgres durable runtime adapter is not ready for writes", {
|
throw new HwlabProtocolError("Postgres durable runtime adapter is not ready for writes", {
|
||||||
code: ERROR_CODES.internalError,
|
code: ERROR_CODES.internalError,
|
||||||
data: {
|
data: {
|
||||||
|
|||||||
Reference in New Issue
Block a user