File size: 4,844 Bytes
cd8bd0a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/**
 * TDD regression for port of https://github.com/decolua/9router/pull/2044:
 * "Fix usage logging dedupe and reduce stats churn"
 *
 * Asserts:
 * 1. Inserting the same request usage entry twice results in exactly ONE row
 *    in usage_history (dedup guard).
 * 2. emitUsageRecorded fires only when a row is actually inserted β€” not on
 *    a duplicate.
 */

import { test } from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";

// Isolate the DB from other tests and from the real data dir.
const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-usage-dedup-"));
process.env.DATA_DIR = TEST_DATA_DIR;

// Dynamic imports so DATA_DIR is set before any module initialises the DB.
const { resetDbInstance, getDbInstance } = await import("../../../src/lib/db/core.ts");
const { onUsageRecorded } = await import("../../../src/lib/usage/usageEvents.ts");
const { saveRequestUsage } = await import("../../../src/lib/usage/usageHistory.ts");

// Cleanup: close DB handle and temp directory so the test runner doesn't hang.
test.after(() => {
  resetDbInstance();
  fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
});

// ── helpers ──────────────────────────────────────────────────────────────────

let entrySeq = 0;

function makeEntry(overrides: Record<string, unknown> = {}) {
  entrySeq++;
  const timestamp = new Date(Date.now() + entrySeq).toISOString();

  return {
    provider: "test-provider",
    model: "test-model",
    connectionId: `conn-abc123-${entrySeq}`,
    apiKeyId: null,
    apiKeyName: null,
    tokens: { input_tokens: 10, output_tokens: 20 },
    status: "success",
    success: true,
    latencyMs: 100,
    timeToFirstTokenMs: 50,
    errorCode: null,
    comboStrategy: null,
    endpoint: "/v1/chat/completions",
    timestamp,
    ...overrides,
  };
}

function countRows(db: ReturnType<typeof getDbInstance>): number {
  const row = db.prepare("SELECT COUNT(*) AS cnt FROM usage_history").get() as { cnt: number };
  return row.cnt;
}

// ── tests ─────────────────────────────────────────────────────────────────────

test("saveRequestUsage: first insert creates exactly one row", async () => {
  const db = getDbInstance();
  const before = countRows(db);
  const entry = makeEntry({ timestamp: new Date().toISOString() });

  await saveRequestUsage(entry);

  assert.equal(countRows(db), before + 1, "Expected exactly one new row after first insert");
});

test("saveRequestUsage: duplicate entry (same key fields) inserts only ONE row", async () => {
  const db = getDbInstance();
  const ts = new Date().toISOString();
  const entry = makeEntry({ timestamp: ts });

  await saveRequestUsage(entry);
  const afterFirst = countRows(db);

  // Insert identical entry a second time β€” should be a no-op.
  await saveRequestUsage(entry);
  const afterSecond = countRows(db);

  assert.equal(
    afterSecond,
    afterFirst,
    "Duplicate insert must not create a second row (dedup guard)"
  );
});

test("saveRequestUsage: emitUsageRecorded fires on real insert but NOT on duplicate", async () => {
  const ts = new Date().toISOString();
  const entry = makeEntry({ timestamp: ts });

  let fireCount = 0;
  const unsub = onUsageRecorded(() => {
    fireCount++;
  });

  try {
    await saveRequestUsage(entry); // real insert β†’ should fire
    await saveRequestUsage(entry); // duplicate β†’ must NOT fire

    assert.equal(fireCount, 1, "emitUsageRecorded should fire exactly once (not on duplicate)");
  } finally {
    unsub();
  }
});

test("saveRequestUsage: two entries with different timestamps are both inserted", async () => {
  const db = getDbInstance();
  const before = countRows(db);

  await saveRequestUsage(makeEntry({ timestamp: new Date(Date.now() - 5000).toISOString() }));
  await saveRequestUsage(makeEntry({ timestamp: new Date(Date.now() - 4000).toISOString() }));

  assert.equal(
    countRows(db),
    before + 2,
    "Two distinct entries (different timestamps) should both be inserted"
  );
});

test("saveRequestUsage: two entries with different providers are both inserted", async () => {
  const db = getDbInstance();
  const before = countRows(db);
  const ts = new Date().toISOString();

  await saveRequestUsage(makeEntry({ timestamp: ts, provider: "provider-A" }));
  await saveRequestUsage(makeEntry({ timestamp: ts, provider: "provider-B" }));

  assert.equal(
    countRows(db),
    before + 2,
    "Two entries with different providers should both be inserted"
  );
});