mirror of
https://github.com/melgarafael/DeskcommCRM.git
synced 2026-10-02 01:28:34 +08:00
feat(harness-f0): drain pula orgs em ai_dispatch_mode=external (spec 14)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QLrVxFCDjcRDCdWUSPftbZ
This commit is contained in:
co-authored by
Claude Fable 5
parent
4efd340b51
commit
028ac190b0
@@ -0,0 +1,33 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import type pg from 'pg';
|
||||
|
||||
import { drainTick } from './drain';
|
||||
|
||||
const knobs = { batchSize: 10, intervalMs: 0, idleIntervalMs: 0, debounceMs: 0, reapTimeoutMs: 60000 };
|
||||
const log = { info: vi.fn(), warn: vi.fn(), error: vi.fn() } as never;
|
||||
const event = {
|
||||
id: 'e1', organization_id: 'org1', attempts: 1,
|
||||
payload: {
|
||||
conversation_id: '11111111-1111-4111-8111-111111111111',
|
||||
contact_id: '22222222-2222-4222-8222-222222222222',
|
||||
channel_session_id: '33333333-3333-4333-8333-333333333333',
|
||||
inbound_message_id: '44444444-4444-4444-8444-444444444444',
|
||||
},
|
||||
};
|
||||
|
||||
it('org em ai_dispatch_mode=external: evento vira done SEM enfileirar job', async () => {
|
||||
const calls: string[] = [];
|
||||
const query = vi.fn().mockImplementation((sql: string) => {
|
||||
calls.push(sql);
|
||||
if (sql.includes('returning e.id')) return { rows: [event] }; // claim
|
||||
if (sql.includes("ai_dispatch_mode")) return { rows: [{ mode: 'external' }] }; // guard
|
||||
if (sql.includes('is_group')) return { rows: [{ is_group: false }] };
|
||||
return { rows: [] }; // reaper / done
|
||||
});
|
||||
await drainTick({ query } as unknown as pg.Pool, knobs, log);
|
||||
// o guard TEM que consultar o modo (garante FAIL antes da implementação)...
|
||||
expect(calls.some((s) => s.includes('ai_dispatch_mode'))).toBe(true);
|
||||
// ...e nenhum job pode ser enfileirado (enqueueJob nunca roda).
|
||||
expect(calls.some((s) => s.includes('job_queue'))).toBe(false);
|
||||
expect(calls.some((s) => s.includes("status = 'done'"))).toBe(true);
|
||||
});
|
||||
@@ -120,6 +120,17 @@ async function processEvent(
|
||||
}
|
||||
const p = parsed.data;
|
||||
|
||||
// Spec 14: org em modo 'external' tem agente EXTERNO como dono da conversa —
|
||||
// o engine não responde por cima. Evento é consumido (done) sem job.
|
||||
const { rows: modeRows } = await pool.query<{ mode: string | null }>(
|
||||
`select settings->>'ai_dispatch_mode' as mode from organizations where id = $1`,
|
||||
[event.organization_id],
|
||||
);
|
||||
if (modeRows[0]?.mode === 'external') {
|
||||
log.info('drain: org em modo external (spec 14) — evento pulado', { event_id: event.id });
|
||||
return;
|
||||
}
|
||||
|
||||
// Grupos: skip, sem exceção (regra dura nº 12).
|
||||
const { rows: convRows } = await pool.query<{ is_group: boolean }>(
|
||||
'select is_group from conversations where organization_id = $1 and id = $2',
|
||||
|
||||
Reference in New Issue
Block a user