feat: aplicar gating en syncMembersForActiveGroups y añadir pruebas

Co-authored-by: aider (openrouter/openai/gpt-5) <aider@aider.chat>
pull/1/head
borja 1 month ago
parent 37db7b283d
commit 302ba6daa8

@ -605,9 +605,28 @@ export class GroupSyncService {
if (this.activeGroupsCache.size === 0) { if (this.activeGroupsCache.size === 0) {
this.cacheActiveGroups(); this.cacheActiveGroups();
} }
// Etapa 3: gating también en el scheduler masivo
const mode = String(process.env.GROUP_GATING_MODE || 'off').toLowerCase();
const enforce = mode === 'enforce';
if (enforce) {
try { (AllowedGroups as any).dbInstance = this.dbInstance; } catch {}
}
let groups = 0, added = 0, updated = 0, deactivated = 0; let groups = 0, added = 0, updated = 0, deactivated = 0;
for (const [groupId] of this.activeGroupsCache.entries()) { for (const [groupId] of this.activeGroupsCache.entries()) {
try { try {
if (enforce) {
try {
if (!AllowedGroups.isAllowed(groupId)) {
// Saltar grupos no permitidos en modo enforce
continue;
}
} catch {
// Si falla el check, no bloquear el grupo
}
}
const snapshot = await this.fetchGroupMembersFromAPI(groupId); const snapshot = await this.fetchGroupMembersFromAPI(groupId);
const res = this.reconcileGroupMembers(groupId, snapshot); const res = this.reconcileGroupMembers(groupId, snapshot);
groups++; groups++;

@ -0,0 +1,46 @@
import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
import { makeMemDb } from '../../helpers/db';
import { GroupSyncService } from '../../../src/services/group-sync';
import { AllowedGroups } from '../../../src/services/allowed-groups';
describe('GroupSyncService - gating en scheduler de miembros (enforce)', () => {
const envBackup = process.env;
const calls: string[] = [];
beforeEach(() => {
process.env = { ...envBackup, NODE_ENV: 'ci', GROUP_GATING_MODE: 'enforce' };
const memdb = makeMemDb();
(GroupSyncService as any).dbInstance = memdb;
(AllowedGroups as any).dbInstance = memdb;
// Preparar caché de grupos activos (2 grupos: uno allowed y otro no)
GroupSyncService.activeGroupsCache.clear();
GroupSyncService.activeGroupsCache.set('ok@g.us', 'OK Group');
GroupSyncService.activeGroupsCache.set('na@g.us', 'NA Group');
// Sembrar allowed solo para 'ok@g.us'
AllowedGroups.setStatus('ok@g.us', 'allowed', 'OK Group');
// Stub de fetch para no hacer red y registrar llamadas
(GroupSyncService as any).fetchGroupMembersFromAPI = async (gid: string) => {
calls.push(gid);
// Snapshot vacía para no escribir en DB
return [];
};
});
afterEach(() => {
process.env = envBackup;
calls.length = 0;
});
it('salta grupos no allowed y solo procesa los allowed', async () => {
const summary = await GroupSyncService.syncMembersForActiveGroups();
// Debe haber procesado solo 1 grupo (el allowed)
expect(summary.groups).toBe(1);
expect(calls).toEqual(['ok@g.us']);
expect(calls).not.toContain('na@g.us');
});
});
Loading…
Cancel
Save