mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-31 06:04:11 +01:00
fix(server): load task bindings only for progress events
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
3447973f6f
commit
6c40618ec1
3 files changed
+49
-8
No files matched your search
@@ -172,3 +172,25 @@ evidence. Fresh CI must verify those native consumers. Before/after logs:
|
||||
`/tmp/sleep29-notification-fix-workers.log`,
|
||||
`/tmp/sleep29-notification-fix-typecheck.log`, and
|
||||
`/tmp/sleep29-native-finalization-acceptance.log`.
|
||||
|
||||
## CI repair: keep non-progress event admission narrow (2026-10-25)
|
||||
|
||||
CI at `3447973f6f` clears the prior finalization failures. Its sole failing test
|
||||
file is `heartbeat-run-event-atomic-append.test.ts`: native lifecycle and retry
|
||||
exhaustion events unnecessarily select runtime mode and the task-binding SQL,
|
||||
which can read a large context snapshot. Those events do not project progress.
|
||||
The lock query now selects the extra binding only for allowlisted progress
|
||||
kinds. Keep the existing strict SQL/payload regression assertions unchanged.
|
||||
|
||||
The atomic-event suite now supports the repository's guarded external test DB
|
||||
convention, allowing its actual PostgreSQL SQL assertions to run locally despite
|
||||
embedded bootstrap failure. The original implementation reproduces both CI
|
||||
failures in `/tmp/sleep29-atomic-events-before.log`. That first external run also
|
||||
exposed fixture cleanup ordering; cleanup now removes event/run/agent rows before
|
||||
companies and always closes its pools. The repaired atomic-event and progress
|
||||
worker suites pass all 25 cases in `/tmp/sleep29-atomic-progress-fixed.log`;
|
||||
server typecheck passes in `/tmp/sleep29-atomic-progress-typecheck.log`.
|
||||
|
||||
Greptile reviewed `3447973f6f` at 5/5 with no threads. A new full CI/review pass
|
||||
is required for this second repair; do not carry forward readiness from its
|
||||
parent head.
|
||||
@@ -1,16 +1,18 @@
|
||||
import { resolveExternalTestDatabaseUrl } from "./helpers/external-test-database.js";
|
||||
import { randomBytes } from "node:crypto";
|
||||
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
||||
import { eq, sql } from "drizzle-orm";
|
||||
import { eq, inArray, sql } from "drizzle-orm";
|
||||
import { drizzle } from "drizzle-orm/postgres-js";
|
||||
import { agents, companies, createDb, heartbeatRunEvents, heartbeatRuns } from "@paperclipai/db";
|
||||
import { appendHeartbeatRunEvent } from "../services/heartbeat-run-events.js";
|
||||
import { getEmbeddedPostgresTestSupport, startEmbeddedPostgresTestDatabase } from "./helpers/embedded-postgres.js";
|
||||
|
||||
const embeddedPostgresSupport = await getEmbeddedPostgresTestSupport();
|
||||
const externalTestDatabaseUrl = resolveExternalTestDatabaseUrl("PAPERCLIP_ATOMIC_EVENTS_TEST_DATABASE_URL");
|
||||
const embeddedPostgresSupport = externalTestDatabaseUrl ? { supported: true } : await getEmbeddedPostgresTestSupport();
|
||||
const describeEmbeddedPostgres = embeddedPostgresSupport.supported ? describe : describe.skip;
|
||||
|
||||
describeEmbeddedPostgres("atomic ordinary run events", () => {
|
||||
let temporary: Awaited<ReturnType<typeof startEmbeddedPostgresTestDatabase>>;
|
||||
let temporary: Awaited<ReturnType<typeof startEmbeddedPostgresTestDatabase>> | undefined;
|
||||
let db: ReturnType<typeof createDb>;
|
||||
let otherDb: ReturnType<typeof createDb>;
|
||||
const companyId = "30000000-0000-4000-8000-000000000001";
|
||||
@@ -30,9 +32,10 @@ describeEmbeddedPostgres("atomic ordinary run events", () => {
|
||||
.where(eq(heartbeatRunEvents.runId, id)).orderBy(heartbeatRunEvents.seq);
|
||||
|
||||
beforeAll(async () => {
|
||||
temporary = await startEmbeddedPostgresTestDatabase("paperclip-atomic-events-");
|
||||
db = createDb(temporary.connectionString);
|
||||
otherDb = createDb(temporary.connectionString);
|
||||
if (!externalTestDatabaseUrl) temporary = await startEmbeddedPostgresTestDatabase("paperclip-atomic-events-");
|
||||
const connectionString = externalTestDatabaseUrl ?? temporary!.connectionString;
|
||||
db = createDb(connectionString);
|
||||
otherDb = createDb(connectionString);
|
||||
await db.insert(companies).values([
|
||||
{ id: companyId, name: "Atomic events", issuePrefix: "ATM" },
|
||||
{ id: otherCompanyId, name: "Other events", issuePrefix: "OTH" },
|
||||
@@ -42,7 +45,21 @@ describeEmbeddedPostgres("atomic ordinary run events", () => {
|
||||
{ id: otherAgentId, companyId: otherCompanyId, name: "Other agent" },
|
||||
]);
|
||||
}, 60_000);
|
||||
afterAll(async () => { await temporary?.cleanup(); });
|
||||
afterAll(async () => {
|
||||
try {
|
||||
if (externalTestDatabaseUrl && db) {
|
||||
const fixtureCompanies = [companyId, otherCompanyId];
|
||||
await db.delete(heartbeatRunEvents).where(inArray(heartbeatRunEvents.companyId, fixtureCompanies));
|
||||
await db.delete(heartbeatRuns).where(inArray(heartbeatRuns.companyId, fixtureCompanies));
|
||||
await db.delete(agents).where(inArray(agents.companyId, fixtureCompanies));
|
||||
await db.delete(companies).where(inArray(companies.id, fixtureCompanies));
|
||||
}
|
||||
} finally {
|
||||
await otherDb?.$client.end({ timeout: 1 });
|
||||
await db?.$client.end({ timeout: 1 });
|
||||
await temporary?.cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
it("persists a decoded receipt in one executed statement", async () => {
|
||||
const runId = await makeRun();
|
||||
|
||||
@@ -99,7 +99,9 @@ export async function appendHeartbeatRunEvent(
|
||||
return db.transaction(async (tx) => {
|
||||
const run = await tx
|
||||
.select({ companyId: heartbeatRuns.companyId, agentId: heartbeatRuns.agentId,
|
||||
runtimeMode: heartbeatRuns.runtimeMode, issueId: boundRunIssueIdSql() })
|
||||
// Only progress needs the task binding. Other native/recovery events
|
||||
// must not read a potentially large context snapshot to append a log.
|
||||
...(projectsProgress ? { runtimeMode: heartbeatRuns.runtimeMode, issueId: boundRunIssueIdSql() } : {}) })
|
||||
.from(heartbeatRuns)
|
||||
.where(eq(heartbeatRuns.id, input.runId))
|
||||
.for("update")
|
||||
|
||||
Reference in new issue
Block a user