Moved reconciliation row selection and order/listing status evaluation into the worker thread
This commit is contained in:
@@ -291,11 +291,15 @@ test('worker-backed reconciliation commits reorg holds atomically and resumes af
|
||||
db.exec("CREATE TRIGGER fail_worker_review BEFORE UPDATE ON orders WHEN json_extract(NEW.data,'$.status')='review' BEGIN SELECT RAISE(ABORT,'injected worker batch failure'); END");
|
||||
} finally { db.close(); }
|
||||
f.market.browse();
|
||||
assert.equal(f.market.isReconciliationWorkerBusy(), true);
|
||||
assert.equal(f.market.diagnostics().eventBacklog, true);
|
||||
for (let i = 0; i < 100 && (f.market.isReconciliationWorkerBusy() || !f.market.diagnostics().reconciliationWorkerFailed); i++) {
|
||||
await new Promise(resolve => setTimeout(resolve, 1));
|
||||
}
|
||||
assert.equal(f.market.diagnostics().reconciliationWorkerFailed, true);
|
||||
assert.equal(f.market.isReconciliationWorkerBusy(), false);
|
||||
await assert.rejects(f.list(), /catching up/); // Do not admit new business while the worker commit is uncertain.
|
||||
assert.equal(f.market.isReconciliationWorkerBusy(), false); // Failure stays paused instead of hot-loop retrying.
|
||||
const check = new DatabaseSync(join(f.dir, 'testnet', 'market.sqlite'));
|
||||
try {
|
||||
assert.equal(JSON.parse((check.prepare('SELECT data FROM orders WHERE id=?').get(order.id) as { data: string }).data).status, 'complete');
|
||||
@@ -311,6 +315,32 @@ test('worker-backed reconciliation commits reorg holds atomically and resumes af
|
||||
assert.equal(f.market.hasReconciliationBacklog(), false);
|
||||
});
|
||||
|
||||
test('worker reconciliation re-fences a canonical event appended during an in-flight batch', async t => {
|
||||
const f = await fixture(t, true, true), db = new DatabaseSync(join(f.dir, 'testnet', 'market.sqlite'));
|
||||
const ids = Array.from({ length: 70 }, (_, i) => `20000000-0000-4000-8000-${(i + 1).toString(16).padStart(12, '0')}`);
|
||||
try {
|
||||
const insertListing = db.prepare('INSERT INTO listings VALUES(?,?,?,?)');
|
||||
const insertOrder = db.prepare('INSERT INTO orders VALUES(?,?)');
|
||||
for (const [i, id] of ids.entries()) {
|
||||
const listingId = `30000000-0000-4000-8000-${(i + 1).toString(16).padStart(12, '0')}`;
|
||||
const cardHash = (i + 1).toString(16).padStart(64, '0');
|
||||
insertListing.run(listingId, cardHash, 'cancelled', JSON.stringify({ id: listingId, cardHash, seller: alice.actor,
|
||||
sequence: 0, kind: 'fixed', status: 'cancelled' }));
|
||||
insertOrder.run(id, JSON.stringify({ id, listingId, seller: alice.actor, buyer: bob.actor, cardHash,
|
||||
sequence: 0, status: 'refunded' }));
|
||||
}
|
||||
} finally { db.close(); }
|
||||
f.events.push({ sequence: 1, type: 'connect', height: 1, hash: 'd'.repeat(64), previousHash: GENESIS_HASH,
|
||||
transactionIds: [], eventHash: '1'.repeat(64) });
|
||||
f.market.browse();
|
||||
assert.equal(f.market.isReconciliationWorkerBusy(), true);
|
||||
f.events.push({ sequence: 2, type: 'connect', height: 2, hash: 'e'.repeat(64), previousHash: 'd'.repeat(64),
|
||||
transactionIds: [], eventHash: '2'.repeat(64) });
|
||||
await drainWorkerReconciliation(f, 100);
|
||||
assert.equal(f.market.diagnostics().canonicalEventCursor, 2);
|
||||
assert.equal(f.market.hasReconciliationBacklog(), false);
|
||||
});
|
||||
|
||||
test('USD and mock XMR accounting use bounded integer amounts and exact fee splitting', () => {
|
||||
assert.equal(parseUsd('15.01'), 1501); assert.equal(parseUsd('0.01'), 1);
|
||||
for (const invalid of ['0', '-1', '1e3', '1.001', ' 1', 'NaN', '1000001', '01.00']) assert.throws(() => parseUsd(invalid));
|
||||
|
||||
Reference in New Issue
Block a user