Files
orca/src/main/usage/usage-breakdown-scaling.test.ts
T
0f4bca26d4 perf: index usage session breakdowns during aggregation and merge (#19487)
* perf: index usage session breakdowns during aggregation and merge

* test(usage): cover key injectivity and merge-index freshness

Also restore both module docstrings to the top of their files.

Quote/backslash location and model keys prove the JSON tuple key stays
injective, and a second source carrying a location/model the merge itself
appended must fold into that row rather than duplicate it.

---------

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-09-08 19:43:25 -07:00

131 lines
4.9 KiB
TypeScript

import { expect, it } from 'vitest'
import { createUsageEventAggregation } from './usage-event-aggregation'
import type { UsageAttributedEventFields } from './usage-rollup-records'
type Event = UsageAttributedEventFields & { cost: number }
const aggregation = createUsageEventAggregation<Event, { cost: number }>({
metric: {
empty: () => ({ cost: 0 }),
fromEvent: (event) => ({ cost: event.cost }),
fold: (target, source) => {
target.cost += source.cost
}
},
cloneSessionForMerge: (session) => structuredClone(session)
})
function events(count: number): Event[] {
return Array.from({ length: count }, (_, index) => ({
sessionId: 'session',
timestamp: '2026-09-07T00:00:00Z',
day: '2026-09-07',
model: `model-${index % 5}`,
projectKey: `path-${index}`,
projectLabel: `Path ${index}`,
repoId: null,
worktreeId: null,
inputTokens: 1,
cachedInputTokens: 0,
outputTokens: 2,
reasoningOutputTokens: 0,
totalTokens: 3,
cost: 0.5
}))
}
it('folds events without rescanning accumulated location breakdowns', () => {
let reads = 0
const input = events(1000)
input.forEach((event, index) =>
Object.defineProperty(event, 'projectKey', {
get() {
reads += 1
return `path-${index}`
}
})
)
const result = aggregation.aggregate([...input, ...input])
expect(reads).toBeLessThan(30000)
const session = result.sessions[0]
expect(session.totalTokens).toBe(6000)
expect(session.cost).toBe(1000)
expect(session.locationBreakdown).toHaveLength(1000)
expect(session.locationBreakdown.every((entry) => entry.eventCount === 2)).toBe(true)
expect(session.modelBreakdown).toHaveLength(5)
expect(result.dailyAggregates).toHaveLength(1000)
})
it('merges rollups using first-match indexes without mutating source breakdowns', () => {
const source = aggregation.aggregate(events(1000)).sessions[0]
const existing = structuredClone(source)
let reads = 0
for (const entry of [...existing.locationBreakdown, ...existing.locationModelBreakdown]) {
const key = entry.locationKey
Object.defineProperty(entry, 'locationKey', {
get() {
reads += 1
return key
}
})
}
const target = new Map([['session', existing]])
aggregation.mergeSessions(target, [source, source])
expect(reads).toBeLessThan(10000)
expect(existing.totalTokens).toBe(9000)
expect(existing.cost).toBe(1500)
expect(source.totalTokens).toBe(3000)
expect(existing.locationBreakdown.every((entry) => entry.eventCount === 3)).toBe(true)
})
it('preserves first-wins duplicate rows and exact location/model tuple identity', () => {
const source = aggregation.aggregate(events(1)).sessions[0]
const existing = structuredClone(source)
existing.locationBreakdown.push({ ...existing.locationBreakdown[0], eventCount: 42 })
aggregation.mergeSessions(new Map([['session', existing]]), [source])
expect(existing.locationBreakdown.map((entry) => entry.eventCount)).toEqual([2, 42])
const input = events(2)
input[0].projectKey = 'a::b'
input[0].model = 'c'
input[1].projectKey = 'a'
input[1].model = 'b::c'
expect(aggregation.aggregate(input).sessions[0].locationModelBreakdown).toHaveLength(2)
})
// Quotes and backslashes are the shapes a plain `::` separator would still collapse.
it('keeps location/model tuples distinct under quote and backslash keys', () => {
const input = events(4)
input[0].projectKey = 'a"'
input[0].model = 'b'
input[1].projectKey = 'a'
input[1].model = '"b'
input[2].projectKey = 'a\\'
input[2].model = 'b'
input[3].projectKey = 'a'
input[3].model = '\\b'
const session = aggregation.aggregate(input).sessions[0]
expect(session.locationModelBreakdown).toHaveLength(4)
expect(session.locationModelBreakdown.every((entry) => entry.eventCount === 1)).toBe(true)
})
// The merge index must learn the rows it appends, or a second source carrying the same
// location/model would append a duplicate row instead of folding into the first.
it('folds later sources into rows the merge itself appended', () => {
const [first] = events(1)
first.projectKey = 'new-location'
first.projectLabel = 'New location'
first.model = 'new-model'
const incoming = aggregation.aggregate([first]).sessions[0]
const existingOnly = events(1)
existingOnly[0].projectKey = 'other'
const existing = aggregation.aggregate(existingOnly).sessions[0]
aggregation.mergeSessions(new Map([['session', existing]]), [incoming, structuredClone(incoming)])
const rows = existing.locationBreakdown.filter((entry) => entry.locationKey === 'new-location')
expect(rows.map((entry) => entry.eventCount)).toEqual([2])
const models = existing.modelBreakdown.filter((entry) => entry.modelKey === 'new-model')
expect(models.map((entry) => entry.eventCount)).toEqual([2])
const tuples = existing.locationModelBreakdown.filter(
(entry) => entry.locationKey === 'new-location' && entry.modelKey === 'new-model'
)
expect(tuples.map((entry) => entry.eventCount)).toEqual([2])
})