Harden conversation replies and prioritize newest candidates
This commit is contained in:
1 parent
f98c5c732d
commit
b8e4a1bb88
23 files changed
+598
-113
No files matched your search
@@ -94,6 +94,42 @@ describe('CandidateQueueRepository', () => {
|
||||
expect(queue.countActive()).toBe(2);
|
||||
});
|
||||
|
||||
it('admits, screens, and sends the newest posts before older higher-priority posts', () => {
|
||||
queue.enqueue([
|
||||
post('old-high-priority', 'alice', 100),
|
||||
post('new-low-priority', 'bob', 300),
|
||||
], 'image', 1, 1_000, 1);
|
||||
|
||||
expect(queue.listActive().map((candidate) => candidate.postId)).toEqual(['new-low-priority']);
|
||||
|
||||
queue.enqueue([post('old-high-priority', 'alice', 100)], 'image', 10, 1_001);
|
||||
const newestScreening = queue.claimForScreening('screen-new', 100, 1_010)!;
|
||||
expect(newestScreening.postId).toBe('new-low-priority');
|
||||
queue.markReady(newestScreening.postId, 'screen-new', prepared(newestScreening.post), 1_011);
|
||||
|
||||
const olderScreening = queue.claimForScreening('screen-old', 100, 1_012)!;
|
||||
queue.markReady(olderScreening.postId, 'screen-old', prepared(olderScreening.post), 1_013);
|
||||
|
||||
expect(queue.claimReady('account-a', 'send', 100, 1_014)?.postId).toBe('new-low-priority');
|
||||
});
|
||||
|
||||
it('promotes the newest due delivery retry when ready capacity is limited', () => {
|
||||
queue.enqueue([post('new-low-priority', 'bob', 300)], 'image', 1, 1_000);
|
||||
queue.enqueue([post('old-high-priority', 'alice', 100)], 'image', 10, 1_001);
|
||||
|
||||
for (const worker of ['screen-new', 'screen-old']) {
|
||||
const candidate = queue.claimForScreening(worker, 100, 1_010)!;
|
||||
queue.markReady(candidate.postId, worker, prepared(candidate.post), 1_011);
|
||||
}
|
||||
for (const [accountId, worker] of [['account-a', 'send-new'], ['account-b', 'send-old']] as const) {
|
||||
const candidate = queue.claimReady(accountId, worker, 100, 1_012)!;
|
||||
queue.deferDelivery(candidate.postId, worker, 'Matrix rate limited', 1_100, 1_013);
|
||||
}
|
||||
|
||||
expect(queue.promoteDueRetries(1, 1_100)).toBe(1);
|
||||
expect(queue.claimReady('account-a', 'retry', 100, 1_101)?.postId).toBe('new-low-priority');
|
||||
});
|
||||
|
||||
it('excludes posts and recipients already handled anywhere', () => {
|
||||
db.prepare(`
|
||||
INSERT INTO processed_posts (account_id, id, subreddit, author, title, processed_at)
|
||||
@@ -140,13 +176,13 @@ describe('CandidateQueueRepository', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('lists only active candidates in actionable stage order', () => {
|
||||
it('lists only active candidates in newest-post order across stages', () => {
|
||||
queue.enqueue([
|
||||
post('waiting', 'alice'),
|
||||
post('screening', 'bob'),
|
||||
post('ready', 'carol'),
|
||||
post('sending', 'dana'),
|
||||
post('rejected', 'erin'),
|
||||
post('waiting', 'alice', 100),
|
||||
post('screening', 'bob', 500),
|
||||
post('ready', 'carol', 400),
|
||||
post('sending', 'dana', 300),
|
||||
post('rejected', 'erin', 200),
|
||||
], 'image', 1, 1_000);
|
||||
queue.claimForScreening('worker-1', 1_000, 1_010);
|
||||
const ready = queue.claimForScreening('worker-2', 1_000, 1_020)!;
|
||||
@@ -155,8 +191,9 @@ describe('CandidateQueueRepository', () => {
|
||||
const rejected = queue.claimForScreening('worker-4', 1_000, 1_040)!;
|
||||
queue.reject(rejected.postId, 'worker-4', 'Seller signals detected', 1_041);
|
||||
|
||||
expect(queue.listActive().map((candidate) => candidate.status)).toEqual([
|
||||
'sending', 'screening', 'discovered', 'discovered',
|
||||
const active = queue.listActive();
|
||||
expect(active.map((candidate) => candidate.postId)).toEqual([
|
||||
'screening', 'ready', 'rejected', 'waiting',
|
||||
]);
|
||||
expect(queue.listActive().map((candidate) => candidate.postId)).not.toContain(rejected.postId);
|
||||
expect(queue.getOldestActiveAt()).toBe(1_000);
|
||||
|
||||
Reference in new issue
Block a user