Skip to content

Commit f1eec6f

Browse files
committed
test(objectql): pin the predicate-delete cascade's refusal
Claude-Session: https://claude.ai/code/session_01ADHkmQQoWsHzMSsiaM89mr Co-authored-by: Claude <noreply@anthropic.com>
1 parent a5bc9c9 commit f1eec6f

1 file changed

Lines changed: 18 additions & 3 deletions

File tree

‎packages/objectql/src/engine-cascade-summary-rollback.test.ts‎

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@
1717
*
1818
* Pinned here: the parent delete refuses with an error that is NOT the
1919
* stale-roll-up refusal, on the atomic plan (nothing stored changes) and on a
20-
* runtime that cannot roll back (the parent is still stored); a refusal that
21-
* escapes a caller's own `transaction()` that rolls back is converted the same
22-
* way. Controls: a delete of the dependent itself — its own write landed, only
20+
* runtime that cannot roll back (the parent is still stored), by id and by
21+
* predicate; a refusal that
22+
* escapes a caller's own `transaction()` (engine or scoped context) that rolls
23+
* back is converted the same way. Controls: a delete of the dependent itself — its own write landed, only
2324
* its recompute failed — still answers `ERR_SUMMARY_RECOMPUTE` carrying its
2425
* result, and so does a caller's transaction that catches it and commits.
2526
*
@@ -81,6 +82,11 @@ function makeDriver(transactional: boolean) {
8182
return row;
8283
},
8384
async delete(o: string, id: string) { return storeFor(o).delete(String(id)); },
85+
async deleteMany(o: string, ast: any) {
86+
const doomed = Array.from(storeFor(o).values()).filter((r) => matches(r, ast?.where));
87+
for (const r of doomed) storeFor(o).delete(String(r.id));
88+
return doomed.length;
89+
},
8490
async count(o: string, ast: any) { return (await this.find(o, ast)).length; },
8591
async bulkCreate(o: string, rows: Row[]) { return Promise.all(rows.map((r) => this.create(o, r))); },
8692
async bulkUpdate() { return []; }, async bulkDelete() {},
@@ -157,6 +163,15 @@ describe('a cascade dependent\'s ERR_SUMMARY_RECOMPUTE never answers for a paren
157163
expect(ids(driver.rowsOf('line'))).toEqual(['l2']);
158164
});
159165

166+
it('a predicate delete (multi) on a runtime that cannot roll back: refused the same way, the parent still stored', async () => {
167+
const { engine, driver } = await makeEngine(false);
168+
const err: any = await engine.delete('acct', { where: { name: 'A' }, multi: true } as any).then(() => null, (e: unknown) => e);
169+
expect(err).toBeInstanceOf(Error);
170+
expect(err.code).toBeUndefined();
171+
expect(err.cause?.code).toBe('ERR_SUMMARY_RECOMPUTE');
172+
expect(ids(driver.rowsOf('acct'))).toEqual(['a1']);
173+
});
174+
160175
it('a caller\'s own transaction that the refusal rolls back: refused with another error, nothing stored', async () => {
161176
const { engine, driver } = await makeEngine(true);
162177
const err: any = await engine

0 commit comments

Comments
 (0)