Ctrl K
ComunidadGuías…

src/infrastructure/state/operational-metrics-storage.test.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import assert from 'node:assert/strict';
import { mkdtempSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import test from 'node:test';
import type { AppConfig } from '../../core/config/config';
import type { Job } from '../../core/contracts/types';
import { ObservabilityLedger } from '../config/config-observability-ledger';
import { JsonlStore } from './state-jsonl';
import { MysqlStore } from './state-mysql';

const NOW = Date.parse('2026-07-24T08:00:00.000Z');

function job(input: Partial<Job> & Pick<Job, 'job_id' | 'status'>): Job {
  return {
    request_id: `req-${input.job_id}`,
    profile: 'readonly',
    project: 'demo',
    source: 'test',
    input_preview: 'test',
    metadata: {},
    created_at: '2026-07-24T07:59:30.000Z',
    updated_at: '2026-07-24T07:59:30.000Z',
    ...input,
  };
}

test('JSONL operational snapshot: aggregates lifecycle, queue and lease health without exposing records', async () => {
  const root = mkdtempSync(join(tmpdir(), 'bailing-metrics-jsonl-'));
  try {
    const store = new JsonlStore(join(root, 'jobs.jsonl'));
    await store.init();
    await store.createJob(job({
      job_id: 'queued',
      status: 'queued',
      thread_id: 7,
      run_after: '2026-07-24T08:01:00.000Z',
    }));
    await store.createJob(job({
      job_id: 'monitor',
      status: 'queued',
      source: 'monitor',
      created_at: '2026-07-23T00:00:00.000Z',
    }));
    await store.createJob(job({
      job_id: 'running',
      status: 'running',
      thread_id: 7,
      lease_until: '2026-07-24T07:59:59.000Z',
    }));
    await store.createJob(job({ job_id: 'done', status: 'done', updated_at: '2026-07-24T07:55:00.000Z' }));
    await store.createJob(job({ job_id: 'error', status: 'error', updated_at: '2026-07-24T07:30:00.000Z' }));
    await store.createJob(job({ job_id: 'rejected', status: 'rejected', updated_at: '2026-07-24T07:59:00.000Z' }));

    const snapshot = await store.operationalMetricsSnapshot(NOW);
    assert.deepEqual(snapshot.byStatus, { queued: 2, running: 1, dispatched: 0, done: 1, error: 1, rejected: 1 });
    assert.deepEqual(snapshot.terminalLast15m, { done: 1, error: 0, rejected: 1 });
    assert.equal(snapshot.oldestQueuedAgeSeconds, 30);
    assert.equal(snapshot.delayedQueuedJobs, 1);
    assert.equal(snapshot.expiredLeases, 1);
    assert.equal(snapshot.blockedThreads, 1);
  } finally {
    rmSync(root, { recursive: true, force: true });
  }
});

test('MySQL operational snapshot: uses one aggregate query and maps the result', async () => {
  const calls: Array<{ sql: string; params: unknown[] }> = [];
  const store = new MysqlStore({} as AppConfig['state']['mysql']);
  Reflect.set(store, 'pool', {
    query: async (sql: string, params: unknown[]) => {
      calls.push({ sql, params });
      return [[{
        queued: 2, running: 1, dispatched: 3, done: 4, error: 5, rejected: 6,
        done_15m: 2, error_15m: 1, rejected_15m: 0,
        oldest_queued_at: '2026-07-24T07:59:30.000Z',
        delayed_queued: 1, expired_leases: 2, blocked_threads: 3,
      }], []];
    },
  });

  const snapshot = await store.operationalMetricsSnapshot(NOW);
  assert.equal(calls.length, 1);
  assert.match(calls[0]!.sql, /COUNT\(DISTINCT q\.thread_id\)/);
  assert.equal(calls[0]!.params.length, 5);
  assert.deepEqual(snapshot.byStatus, { queued: 2, running: 1, dispatched: 3, done: 4, error: 5, rejected: 6 });
  assert.deepEqual(snapshot.terminalLast15m, { done: 2, error: 1, rejected: 0 });
  assert.equal(snapshot.oldestQueuedAgeSeconds, 30);
  assert.equal(snapshot.blockedThreads, 3);
});

test('control-plane operational snapshot: counts approvals and executor heartbeat states in one query', async () => {
  const calls: Array<{ sql: string; params: unknown[] }> = [];
  const ledger = new ObservabilityLedger(() => ({
    query: async (sql: string, params: unknown[]) => {
      calls.push({ sql, params });
      return [[{ pending_approvals: 4, executors_online: 2, executors_offline: 5 }], []];
    },
  }));

  const snapshot = await ledger.operationalMetricsSnapshot(NOW);
  assert.deepEqual(snapshot, { pendingApprovals: 4, executorsOnline: 2, executorsOffline: 5 });
  assert.equal(calls.length, 1);
  assert.match(calls[0]!.sql, /bz_tool_approvals/);
  assert.match(calls[0]!.sql, /bz_executors/);
  assert.equal(calls[0]!.params.length, 2);
});