feat: 🎸 cleanup gitdiff

This commit is contained in:
amianthus
2026-05-18 13:51:20 +01:00
parent 53dc4a96ab
commit 2b16124d07
16 changed files with 0 additions and 4278 deletions

View File

@@ -1,153 +0,0 @@
import { AppEnv, RELEVANT_STATUSES } from "@autumn/shared";
import chalk from "chalk";
import { sql } from "drizzle-orm";
import { CusBatchService } from "../src/internal/customers/CusBatchService";
import { CusSearchService } from "../src/internal/customers/CusSearchService";
import { getCursorPaginatedFullCusQuery } from "../src/internal/customers/cursorPaginatedFullCusQuery";
import { initDrizzle } from "../src/db/initDrizzle";
import {
type FlattenedCustomerRow,
reassembleFlattenedCustomer,
} from "../src/internal/customers/reassembleFlattenedCustomer";
import { loadLocalEnv } from "../src/utils/envUtils";
loadLocalEnv();
const ORG_ID = "org_2sWv2S8LJ9iaTjLI6UtNsfL88Kt";
const ENV = AppEnv.Sandbox;
const REPEATS = 5;
const LIMIT = parseInt(process.env.LIMIT ?? "500", 10);
const OFFSET_PCT = parseInt(process.env.OFFSET_PCT ?? "95", 10);
const main = async () => {
console.log(
chalk.magentaBright(
"\n================ Dashboard Merge Bench ================\n",
),
);
const { db, client } = initDrizzle();
const ctx = {
db,
client,
org: { id: ORG_ID, slug: "unit-test-org" },
env: ENV,
logger: {
info: () => {},
error: () => {},
warn: () => {},
debug: () => {},
trace: () => {},
},
} as any;
try {
const total = (
(await db.execute(
sql`SELECT COUNT(*)::int AS n FROM customers WHERE org_id = ${ORG_ID} AND env = ${ENV}`,
)) as unknown as { n: number }[]
)[0].n;
const offset = Math.floor((total * OFFSET_PCT) / 100);
const row = (await db.execute(
sql`SELECT created_at, id FROM customers WHERE org_id = ${ORG_ID} AND env = ${ENV} ORDER BY created_at DESC, id DESC LIMIT 1 OFFSET ${offset}`,
)) as unknown as { created_at: number; id: string }[];
const cursor = { t: Number(row[0].created_at), id: row[0].id };
console.log(
chalk.gray(
` total=${total.toLocaleString()} cursor at ${OFFSET_PCT}%: ${cursor.id} limit=${LIMIT}\n`,
),
);
const measure = async (label: string, fn: () => Promise<void>) => {
for (let i = 0; i < 2; i++) await fn();
const samples: number[] = [];
for (let i = 0; i < REPEATS; i++) {
const t0 = performance.now();
await fn();
samples.push(performance.now() - t0);
}
samples.sort((a, b) => a - b);
const p50 = samples[Math.floor(samples.length / 2)];
const min = samples[0];
const max = samples[samples.length - 1];
console.log(
` ${chalk.cyan(label.padEnd(20))} p50=${p50.toFixed(0).padStart(4)}ms min=${min.toFixed(0).padStart(4)}ms max=${max.toFixed(0).padStart(4)}ms`,
);
return p50;
};
const oldPath = async () => {
const { internalIds } =
await CusSearchService.resolveInternalIdsByCursor({
db,
orgId: ORG_ID,
env: ENV,
search: "",
cursor,
limit: LIMIT,
});
if (internalIds.length === 0) return;
const query = getCursorPaginatedFullCusQuery({
orgId: ORG_ID,
env: ENV,
inStatuses: RELEVANT_STATUSES,
withSubs: true,
limit: internalIds.length,
internalCustomerIds: internalIds,
cusProductLimit: 15,
});
const rows = (await db.execute(query)) as unknown as Record<
string,
unknown
>[];
const flat = (rows[0] ?? {}) as unknown as FlattenedCustomerRow;
reassembleFlattenedCustomer(flat);
};
const newPath = async () => {
await CusBatchService.getDashboardCursorPage({
ctx,
search: "",
filters: undefined,
cursor,
limit: LIMIT,
});
};
const oldWithStatus = async () => {
// Call old path manually (resolve + fetch) with status filter for parity
await oldPath();
};
const newWithStatus = async () => {
await CusBatchService.getDashboardCursorPage({
ctx,
search: "",
filters: { status: ["active"] },
cursor,
limit: LIMIT,
});
};
const oldP50 = await measure("OLD (resolve+fetch)", oldPath);
const newP50 = await measure("NEW (no filters)", newPath);
const newStatusP50 = await measure(
"NEW (status=active)",
newWithStatus,
);
console.log();
console.log(chalk.magentaBright("================ Summary ================"));
const delta = (((newP50 - oldP50) / oldP50) * 100).toFixed(0);
console.log(
` old → new (no filters): ${oldP50.toFixed(0)}ms → ${newP50.toFixed(0)}ms (${delta}%)`,
);
console.log(
` new with status=active: ${newStatusP50.toFixed(0)}ms (uses resolve+fetch fallback)`,
);
} finally {
await client.end();
process.exit(0);
}
};
await main();

View File

@@ -1,24 +0,0 @@
import { sql } from "drizzle-orm";
import { initDrizzle } from "../src/db/initDrizzle";
import { loadLocalEnv } from "../src/utils/envUtils";
loadLocalEnv();
const main = async () => {
const { db, client } = initDrizzle();
try {
const rows = (await db.execute(sql`
SELECT indexname, indexdef
FROM pg_indexes
WHERE schemaname = 'public'
AND tablename = 'customer_products'
AND (indexname LIKE '%revenuecat%' OR indexdef LIKE '%revenuecat%')
`)) as any[];
console.log(JSON.stringify(rows, null, 2));
} finally {
await client.end();
process.exit(0);
}
};
await main();

View File

@@ -1,338 +0,0 @@
import type { AppEnv, CusProductStatus, ListCustomersV2Params } from "@autumn/shared";
import { sql } from "drizzle-orm";
import { getCustomerListFilterSql } from "../src/internal/customers/getFullCusQuery";
export type CursorPaginatedFullCusQueryArgs = {
orgId: string;
env: AppEnv;
inStatuses?: CusProductStatus[];
includeInvoices: boolean;
withEntities: boolean;
withTrialsUsed: boolean;
withSubs: boolean;
limit: number;
cursor?: { createdAt: number; id: string };
withEvents?: boolean;
internalCustomerIds?: string[];
plans?: ListCustomersV2Params["plans"];
processors?: ListCustomersV2Params["processors"];
search?: string;
cusProductLimit: number;
};
export const getCursorPaginatedFullCusQuery = ({
orgId,
env,
inStatuses,
includeInvoices,
withEntities,
withTrialsUsed,
withSubs,
limit,
cursor,
withEvents = false,
internalCustomerIds,
plans,
processors,
search,
cusProductLimit,
}: CursorPaginatedFullCusQueryArgs) => {
const withStatusFilter = () => {
return inStatuses?.length
? sql`AND cp.status = ANY(ARRAY[${sql.join(
inStatuses.map((status) => sql`${status}`),
sql`, `,
)}])`
: sql``;
};
const customerListFilterSql = getCustomerListFilterSql({
internalCustomerIds,
inStatuses,
plans,
processors,
search,
});
const cursorPredicate = cursor
? sql`AND (c.created_at, c.id) < (${cursor.createdAt}, ${cursor.id})`
: sql``;
const fetchLimit = limit + 1;
const extraEntitlementsCTE = sql`, extra_customer_entitlements AS (
SELECT
cr.internal_id AS internal_customer_id,
COALESCE(
json_agg(
to_jsonb(ce.*) || jsonb_build_object(
'entitlement', (
SELECT row_to_json(ent_with_feature)
FROM (
SELECT e.*, row_to_json(f) AS feature
FROM entitlements e
JOIN features f ON e.internal_feature_id = f.internal_id
WHERE e.id = ce.entitlement_id
) AS ent_with_feature
),
'replaceables', (
SELECT COALESCE(
json_agg(row_to_json(r)) FILTER (WHERE r.id IS NOT NULL),
'[]'::json
)
FROM replaceables r
WHERE r.cus_ent_id = ce.id
),
'rollovers', (
SELECT COALESCE(
json_agg(row_to_json(ro) ORDER BY ro.expires_at ASC NULLS LAST)
FILTER (WHERE ro.expires_at > EXTRACT(EPOCH FROM now()) * 1000 OR ro.expires_at IS NULL),
'[]'::json
)
FROM rollovers ro
WHERE ro.cus_ent_id = ce.id
)
)
ORDER BY ce.id DESC
) FILTER (WHERE ce.id IS NOT NULL),
'[]'::json
) AS extra_customer_entitlements
FROM customer_records cr
LEFT JOIN LATERAL (
SELECT *
FROM customer_entitlements ce
WHERE ce.internal_customer_id = cr.internal_id
AND ce.customer_product_id IS NULL
AND (ce.expires_at IS NULL OR ce.expires_at > EXTRACT(EPOCH FROM now()) * 1000)
ORDER BY ce.id DESC
LIMIT 30
) ce ON true
GROUP BY cr.internal_id
)`;
return sql`
WITH customer_records AS (
SELECT c.*
FROM customers c
WHERE c.org_id = ${orgId}
AND c.env = ${env}
${customerListFilterSql}
${cursorPredicate}
ORDER BY c.created_at DESC, c.id DESC
LIMIT ${fetchLimit}
),
customer_products_with_prices AS (
SELECT
cp.*,
row_to_json(prod) AS product,
cpr_data.customer_prices,
ce_data.customer_entitlements,
ft_data.free_trial
FROM customer_records cr
JOIN LATERAL (
SELECT *
FROM customer_products cp
WHERE cp.internal_customer_id = cr.internal_id
${withStatusFilter()}
ORDER BY (SELECT p.is_add_on FROM products p WHERE p.internal_id = cp.internal_product_id) ASC, cp.created_at DESC
LIMIT ${cusProductLimit}
) cp ON true
JOIN products prod ON cp.internal_product_id = prod.internal_id
LEFT JOIN LATERAL (
SELECT COALESCE(
json_agg(
to_jsonb(cpr.*) || jsonb_build_object('price', to_jsonb(p.*))
) FILTER (WHERE cpr.id IS NOT NULL),
'[]'::json
) AS customer_prices
FROM customer_prices cpr
LEFT JOIN prices p ON cpr.price_id = p.id
WHERE cpr.customer_product_id = cp.id
) cpr_data ON true
LEFT JOIN LATERAL (
SELECT COALESCE(
json_agg(
to_jsonb(ce.*) || jsonb_build_object(
'entitlement', (
SELECT row_to_json(ent_with_feature)
FROM (
SELECT e.*, row_to_json(f) AS feature
FROM entitlements e
JOIN features f ON e.internal_feature_id = f.internal_id
WHERE e.id = ce.entitlement_id
) AS ent_with_feature
),
'replaceables', (
SELECT COALESCE(
json_agg(row_to_json(r)) FILTER (WHERE r.id IS NOT NULL),
'[]'::json
)
FROM replaceables r
WHERE r.cus_ent_id = ce.id
),
'rollovers', (
SELECT COALESCE(
json_agg(row_to_json(ro) ORDER BY ro.expires_at ASC NULLS LAST) FILTER (WHERE ro.expires_at > EXTRACT(EPOCH FROM now()) * 1000 OR ro.expires_at IS NULL),
'[]'::json
)
FROM rollovers ro
WHERE ro.cus_ent_id = ce.id
)
)
) FILTER (WHERE ce.id IS NOT NULL),
'[]'::json
) AS customer_entitlements
FROM customer_entitlements ce
WHERE ce.customer_product_id = cp.id
) ce_data ON true
LEFT JOIN LATERAL (
SELECT row_to_json(ft) AS free_trial
FROM free_trials ft
WHERE ft.id = cp.free_trial_id
) ft_data ON true
),
customer_products_aggregated AS (
SELECT
cpwp.internal_customer_id,
json_agg(row_to_json(cpwp) ORDER BY cpwp.created_at DESC) AS customer_products
FROM customer_products_with_prices cpwp
GROUP BY cpwp.internal_customer_id
)
${
withSubs
? sql`, customer_subscriptions AS (
SELECT
s.internal_customer_id,
COALESCE(
json_agg(row_to_json(s)) FILTER (WHERE s.stripe_id IS NOT NULL),
'[]'::json
) AS subscriptions
FROM (
SELECT DISTINCT
cpwp.internal_customer_id,
s.*
FROM customer_products_with_prices cpwp
JOIN LATERAL unnest(cpwp.subscription_ids) AS cpwp_sub(stripe_id) ON true
JOIN subscriptions s ON s.stripe_id = cpwp_sub.stripe_id
) s
GROUP BY s.internal_customer_id
)`
: sql``
}
${
withEvents
? sql`, customer_events AS (
SELECT
e.internal_customer_id,
COALESCE(
json_agg(
json_build_object(
'id', e.id,
'event_name', e.event_name,
'value', e.value,
'timestamp', e.timestamp,
'properties', e.properties
)
ORDER BY e.timestamp DESC, e.id DESC
) FILTER (WHERE e.id IS NOT NULL),
'[]'::json
) AS events
FROM events e
WHERE e.internal_customer_id IN (SELECT internal_id FROM customer_records)
AND e.set_usage = false
GROUP BY e.internal_customer_id
)`
: sql``
}
${
withEntities
? sql`, customer_entities AS (
SELECT
cr.internal_id AS internal_customer_id,
COALESCE(
json_agg(row_to_json(e) ORDER BY e.internal_id DESC) FILTER (WHERE e.internal_id IS NOT NULL),
'[]'::json
) AS entities
FROM customer_records cr
LEFT JOIN LATERAL (
SELECT *
FROM entities e
WHERE e.internal_customer_id = cr.internal_id
ORDER BY e.internal_id DESC
LIMIT 300
) e ON true
GROUP BY cr.internal_id
)`
: sql``
}
${
includeInvoices
? sql`, customer_invoices AS (
SELECT
cr.internal_id AS internal_customer_id,
COALESCE(
json_agg(row_to_json(i) ORDER BY i.created_at DESC, i.id DESC) FILTER (WHERE i.id IS NOT NULL),
'[]'::json
) AS invoices
FROM customer_records cr
LEFT JOIN LATERAL (
SELECT *
FROM invoices i
WHERE i.internal_customer_id = cr.internal_id
ORDER BY i.created_at DESC, i.id DESC
LIMIT 10
) i ON true
GROUP BY cr.internal_id
)`
: sql``
}
${
withTrialsUsed
? sql`, customer_trials_used AS (
SELECT
cp.internal_customer_id,
json_agg(json_build_object(
'product_id', p.id,
'fingerprint', c.fingerprint,
'customer_id', c.id
)) AS trials_used
FROM customer_products cp
JOIN products p ON cp.internal_product_id = p.internal_id
JOIN customers c ON cp.internal_customer_id = c.internal_id
WHERE cp.internal_customer_id IN (SELECT internal_id FROM customer_records)
AND cp.free_trial_id IS NOT NULL
GROUP BY cp.internal_customer_id
)`
: sql``
}
${extraEntitlementsCTE}
SELECT
cr.*,
COALESCE(cpa.customer_products, '[]'::json) AS customer_products
${withSubs ? sql`, COALESCE(cs.subscriptions, '[]'::json) AS subscriptions` : sql``}
${withEntities ? sql`, COALESCE(ce.entities, '[]'::json) AS entities` : sql``}
${includeInvoices ? sql`, COALESCE(ci.invoices, '[]'::json) AS invoices` : sql``}
${withTrialsUsed ? sql`, COALESCE(ctu.trials_used, '[]'::json) AS trials_used` : sql``}
${withEvents ? sql`, COALESCE(cev.events, '[]'::json) AS events` : sql``}
, COALESCE(ece.extra_customer_entitlements, '[]'::json) AS extra_customer_entitlements
FROM customer_records cr
LEFT JOIN customer_products_aggregated cpa ON cpa.internal_customer_id = cr.internal_id
${withSubs ? sql`LEFT JOIN customer_subscriptions cs ON cs.internal_customer_id = cr.internal_id` : sql``}
${withEntities ? sql`LEFT JOIN customer_entities ce ON ce.internal_customer_id = cr.internal_id` : sql``}
${includeInvoices ? sql`LEFT JOIN customer_invoices ci ON ci.internal_customer_id = cr.internal_id` : sql``}
${withTrialsUsed ? sql`LEFT JOIN customer_trials_used ctu ON ctu.internal_customer_id = cr.internal_id` : sql``}
${withEvents ? sql`LEFT JOIN customer_events cev ON cev.internal_customer_id = cr.internal_id` : sql``}
LEFT JOIN extra_customer_entitlements ece ON ece.internal_customer_id = cr.internal_id
ORDER BY cr.created_at DESC, cr.id DESC
`;
};

View File

@@ -1,47 +0,0 @@
import { AppEnv } from "@autumn/shared";
import chalk from "chalk";
import { sql } from "drizzle-orm";
import { RELEVANT_STATUSES } from "../src/internal/customers/cusProducts/CusProductService";
import { initDrizzle } from "../src/db/initDrizzle";
import { loadLocalEnv } from "../src/utils/envUtils";
import { getOptimizedFullCusQuery } from "./optimizedFullCusQuery";
loadLocalEnv();
const ORG_ID = "org_2sWv2S8LJ9iaTjLI6UtNsfL88Kt";
const main = async () => {
const { db, client } = initDrizzle();
try {
const query = getOptimizedFullCusQuery({
orgId: ORG_ID,
env: AppEnv.Sandbox,
inStatuses: RELEVANT_STATUSES,
withSubs: false,
limit: 1000,
cusProductLimit: 15,
});
console.log(chalk.cyan("Running optimized first page..."));
try {
const r = await db.execute(query);
console.log(chalk.green(`OK: ${(r as any).length} row(s)`));
const first = (r as any)[0];
if (first) {
for (const [k, v] of Object.entries(first)) {
const arr = Array.isArray(v) ? v : v != null && typeof v === "object" && "length" in (v as any) ? (v as any[]) : null;
console.log(` ${k}: ${arr ? `${arr.length} items` : typeof v}`);
}
}
} catch (e: any) {
console.error(chalk.red(`SQL ERROR: ${e.message}`));
console.error(chalk.gray(`code: ${e.code}, where: ${e.where ?? "n/a"}, detail: ${e.detail ?? "n/a"}, hint: ${e.hint ?? "n/a"}`));
if (e.position) console.error(chalk.gray(`position: ${e.position}`));
}
} finally {
await client.end();
process.exit(0);
}
};
await main();

View File

@@ -1,305 +0,0 @@
import {
AppEnv,
type FullCustomer,
RELEVANT_STATUSES,
StandardCursor,
} from "@autumn/shared";
import chalk from "chalk";
import { sql } from "drizzle-orm";
import { CusBatchService } from "../src/internal/customers/CusBatchService";
import { CusSearchService } from "../src/internal/customers/CusSearchService";
import { getCursorPaginatedFullCusQuery } from "../src/internal/customers/cursorPaginatedFullCusQuery";
import { initDrizzle } from "../src/db/initDrizzle";
import {
type FlattenedCustomerRow,
reassembleFlattenedCustomer,
} from "../src/internal/customers/reassembleFlattenedCustomer";
import { loadLocalEnv } from "../src/utils/envUtils";
loadLocalEnv();
const ORG_ID = "org_2sWv2S8LJ9iaTjLI6UtNsfL88Kt";
const ENV = AppEnv.Sandbox;
type DashboardFilters = {
status?: string[];
version?: string[];
none?: boolean;
processor?: string[];
};
const runOldPath = async ({
ctx,
search,
filters,
cursor,
limit,
}: {
ctx: any;
search: string;
filters?: DashboardFilters;
cursor: { t: number; id: string } | null;
limit: number;
}): Promise<{
fullCustomers: FullCustomer[];
next_cursor: string | null;
}> => {
const { internalIds, peek } =
await CusSearchService.resolveInternalIdsByCursor({
db: ctx.db,
orgId: ORG_ID,
env: ENV,
search,
filters,
cursor,
limit,
});
if (internalIds.length === 0) {
return { fullCustomers: [], next_cursor: null };
}
const query = getCursorPaginatedFullCusQuery({
orgId: ORG_ID,
env: ENV,
inStatuses: RELEVANT_STATUSES,
withSubs: true,
limit: internalIds.length,
internalCustomerIds: internalIds,
cusProductLimit: 15,
});
const rows = (await ctx.db.execute(query)) as unknown as Record<
string,
unknown
>[];
const flat = (rows[0] ?? {
customers: [],
customer_products: [],
customer_entitlements: [],
extra_customer_entitlements: [],
customer_prices: [],
entitlements: [],
rollovers: [],
replaceables: [],
free_trials: [],
subscriptions: [],
}) as unknown as FlattenedCustomerRow;
const fullCustomers = reassembleFlattenedCustomer(flat);
const next_cursor = peek ? StandardCursor.encode(peek) : null;
return { fullCustomers, next_cursor };
};
const minimalCtx = () => {
const { db, client } = initDrizzle();
return {
db,
client,
org: { id: ORG_ID, slug: "unit-test-org" },
env: ENV,
logger: {
info: () => {},
error: () => {},
warn: () => {},
debug: () => {},
trace: () => {},
},
} as any;
};
const sortById = <T extends { internal_id?: string; id?: string | null }>(
arr: T[],
): T[] =>
[...arr].sort((a, b) =>
(a.internal_id ?? a.id ?? "").localeCompare(b.internal_id ?? b.id ?? ""),
);
const sortDeep = (obj: unknown): unknown => {
if (Array.isArray(obj)) {
const sorted = obj.map(sortDeep);
if (sorted.length > 0 && typeof sorted[0] === "object" && sorted[0] !== null) {
(sorted as any[]).sort((a, b) => {
const ka = (a as any).id ?? (a as any).internal_id ?? "";
const kb = (b as any).id ?? (b as any).internal_id ?? "";
return String(ka).localeCompare(String(kb));
});
}
return sorted;
}
if (obj && typeof obj === "object") {
return Object.fromEntries(
Object.entries(obj as Record<string, unknown>)
.map(([k, v]) => [k, sortDeep(v)] as const)
.sort(([a], [b]) => a.localeCompare(b)),
);
}
return obj;
};
const diffCustomers = (
a: FullCustomer[],
b: FullCustomer[],
label: string,
) => {
if (a.length !== b.length) {
console.log(
chalk.red(
` ${label} ✗ length mismatch: old=${a.length} new=${b.length}`,
),
);
return false;
}
const sa = sortById(a);
const sb = sortById(b);
let mismatches = 0;
for (let i = 0; i < sa.length; i++) {
const ja = JSON.stringify(sortDeep(sa[i]));
const jb = JSON.stringify(sortDeep(sb[i]));
if (ja !== jb) {
if (mismatches < 2) {
console.log(
chalk.red(
` ${label} ✗ customer #${i} (${(sa[i] as any).id}) differs`,
),
);
const keysA = Object.keys(sortDeep(sa[i]) as object);
for (const k of keysA) {
const va = JSON.stringify((sortDeep(sa[i]) as any)[k]);
const vb = JSON.stringify((sortDeep(sb[i]) as any)[k]);
if (va !== vb) {
console.log(
chalk.gray(` KEY ${k}\n old=${va?.slice(0, 160)}\n new=${vb?.slice(0, 160)}`),
);
}
}
}
mismatches++;
}
}
if (mismatches > 0) {
console.log(
chalk.red(` ${label}${mismatches}/${sa.length} customers differ`),
);
return false;
}
console.log(chalk.green(` ${label}${sa.length} customers identical`));
return true;
};
type Case = {
name: string;
search?: string;
filters?: DashboardFilters;
cursor?: { t: number; id: string } | null;
limit?: number;
};
const main = async () => {
console.log(
chalk.magentaBright(
"\n================ Dashboard Merge Parity ================\n",
),
);
const ctx = minimalCtx();
const total = (
(await ctx.db.execute(
sql`SELECT COUNT(*)::int AS n FROM customers WHERE org_id = ${ORG_ID} AND env = ${ENV}`,
)) as unknown as { n: number }[]
)[0].n;
const deepOffset = Math.floor(total * 0.95);
const deepRow = (await ctx.db.execute(
sql`SELECT created_at, id FROM customers WHERE org_id = ${ORG_ID} AND env = ${ENV} ORDER BY created_at DESC, id DESC LIMIT 1 OFFSET ${deepOffset}`,
)) as unknown as { created_at: number; id: string }[];
const deepCursor = {
t: Number(deepRow[0].created_at),
id: deepRow[0].id,
};
console.log(
chalk.gray(
` total=${total.toLocaleString()} deep_cursor=${deepCursor.id} (offset ~95%)\n`,
),
);
const cases: Case[] = [
{ name: "baseline", limit: 200 },
{ name: "search 'bench_000450'", search: "bench_000450", limit: 100 },
{ name: "status=active", filters: { status: ["active"] }, limit: 200 },
{ name: "status=past_due", filters: { status: ["past_due"] }, limit: 200 },
{ name: "status=canceled", filters: { status: ["canceled"] }, limit: 200 },
{
name: "status=free_trial",
filters: { status: ["free_trial"] },
limit: 200,
},
{ name: "status=expired", filters: { status: ["expired"] }, limit: 200 },
{
name: "status=active,past_due",
filters: { status: ["active", "past_due"] },
limit: 200,
},
{ name: "none=true", filters: { none: true }, limit: 200 },
{
name: "processor=stripe",
filters: { processor: ["stripe"] },
limit: 200,
},
{ name: "deep cursor (95%)", cursor: deepCursor, limit: 200 },
{
name: "deep cursor + status=active",
cursor: deepCursor,
filters: { status: ["active"] },
limit: 200,
},
{
name: "search no-match",
search: "no_such_customer_zzz",
limit: 50,
},
];
let pass = 0;
let fail = 0;
try {
for (const tc of cases) {
const args = {
ctx,
search: tc.search ?? "",
filters: tc.filters,
cursor: tc.cursor ?? null,
limit: tc.limit ?? 200,
};
const oldRes = await runOldPath(args);
const newRes = await CusBatchService.getDashboardCursorPage(args);
const ok = diffCustomers(
oldRes.fullCustomers,
newRes.fullCustomers,
tc.name,
);
const oldDecoded = StandardCursor.decode(oldRes.next_cursor ?? "");
const newDecoded = StandardCursor.decode(newRes.next_cursor ?? "");
const cursorMatches =
(oldDecoded?.t ?? null) === (newDecoded?.t ?? null) &&
(oldDecoded?.id ?? null) === (newDecoded?.id ?? null);
if (!cursorMatches) {
console.log(
chalk.yellow(
` cursor differs: old=${JSON.stringify(oldDecoded)} new=${JSON.stringify(newDecoded)}`,
),
);
}
if (ok && cursorMatches) pass++;
else fail++;
}
console.log();
console.log(
chalk.bold(
`Result: ${chalk.green(`${pass} pass`)} / ${chalk.red(`${fail} fail`)} of ${cases.length}`,
),
);
} finally {
await ctx.client.end();
process.exit(fail === 0 ? 0 : 1);
}
};
await main();

View File

@@ -1,180 +0,0 @@
import { AppEnv } from "@autumn/shared";
import type { FlattenedCustomerRow } from "../src/internal/customers/reassembleFlattenedCustomer/index.js";
import chalk from "chalk";
import { sql } from "drizzle-orm";
import { RELEVANT_STATUSES } from "../src/internal/customers/cusProducts/CusProductService";
import { initDrizzle } from "../src/db/initDrizzle";
import { loadLocalEnv } from "../src/utils/envUtils";
import { getCursorPaginatedFullCusQuery } from "../src/internal/customers/cursorPaginatedFullCusQuery";
import { reassembleFlattenedCustomer } from "../src/internal/customers/reassembleFlattenedCustomer";
import { getOptimizedFullCusQuery } from "./optimizedFullCusQuery";
loadLocalEnv();
const ORG_ID = "org_2sWv2S8LJ9iaTjLI6UtNsfL88Kt";
type Args = {
orgId: string;
env: AppEnv;
inStatuses: typeof RELEVANT_STATUSES;
withSubs: boolean;
limit: number;
cusProductLimit: number;
};
const sharedArgs: Args & {
cursor?: { v: 0; t: number; id: string };
} = {
orgId: ORG_ID,
env: AppEnv.Sandbox,
inStatuses: RELEVANT_STATUSES,
withSubs: true,
limit: parseInt(process.env.LIMIT ?? "50", 10),
cusProductLimit: 15,
};
type AnyRecord = Record<string, unknown>;
const fetchFlat = async (
db: ReturnType<typeof initDrizzle>["db"],
q: any,
): Promise<FlattenedCustomerRow> => {
const rows = await db.execute(q);
const flat = (rows as unknown as AnyRecord[])[0] as unknown as FlattenedCustomerRow;
return flat;
};
const sortById = (a: { id?: string }, b: { id?: string }) =>
(a.id ?? "").localeCompare(b.id ?? "");
const sortDeep = (obj: unknown): unknown => {
if (Array.isArray(obj)) {
const sorted = obj.map(sortDeep);
if (sorted.length > 0 && typeof sorted[0] === "object" && sorted[0] !== null) {
(sorted as AnyRecord[]).sort((a, b) => {
const ka = (a as AnyRecord).id ?? (a as AnyRecord).internal_id ?? "";
const kb = (b as AnyRecord).id ?? (b as AnyRecord).internal_id ?? "";
return String(ka).localeCompare(String(kb));
});
}
return sorted;
}
if (obj && typeof obj === "object") {
const entries = Object.entries(obj as AnyRecord)
.map(([k, v]) => [k, sortDeep(v)] as const)
.sort(([a], [b]) => a.localeCompare(b));
return Object.fromEntries(entries);
}
return obj;
};
const main = async () => {
const { db, client } = initDrizzle();
try {
const offsetPct = parseInt(process.env.OFFSET_PCT ?? "0", 10);
if (offsetPct > 0) {
const total = (await db.execute(
sql`SELECT COUNT(*)::int AS n FROM customers WHERE org_id = ${ORG_ID} AND env = 'sandbox'`,
)) as unknown as { n: number }[];
const offset = Math.floor((total[0].n * offsetPct) / 100);
const row = (await db.execute(
sql`SELECT created_at, id FROM customers WHERE org_id = ${ORG_ID} AND env = 'sandbox' ORDER BY created_at DESC, id DESC LIMIT 1 OFFSET ${offset}`,
)) as unknown as { created_at: number; id: string }[];
sharedArgs.cursor = { v: 0, t: row[0].created_at, id: row[0].id };
console.log(chalk.cyan(`Using deep cursor at ${offsetPct}%: ${row[0].id}`));
}
console.log(chalk.cyan(`Running CURRENT query (limit=${sharedArgs.limit}, cursor=${sharedArgs.cursor ? "yes" : "no"})...`));
const flatCurrent = await fetchFlat(
db,
getCursorPaginatedFullCusQuery(sharedArgs),
);
console.log(chalk.cyan(`Running OPTIMIZED query...`));
const flatOptim = await fetchFlat(
db,
getOptimizedFullCusQuery(sharedArgs),
);
// Compare top-level array lengths
const keys = [
"customers",
"customer_products",
"customer_entitlements",
"extra_customer_entitlements",
"customer_prices",
"entitlements",
"rollovers",
"replaceables",
"free_trials",
"subscriptions",
] as const;
console.log(chalk.bold("\nTop-level counts:"));
let lenMismatch = false;
for (const k of keys) {
const a = (flatCurrent[k] as unknown[] | undefined)?.length ?? 0;
const b = (flatOptim[k] as unknown[] | undefined)?.length ?? 0;
const match = a === b;
if (!match) lenMismatch = true;
console.log(
` ${k.padEnd(32)} current=${String(a).padStart(5)} optim=${String(b).padStart(5)} ${match ? chalk.green("✓") : chalk.red("✗")}`,
);
}
if (lenMismatch) {
console.log(chalk.red("\n❌ Length mismatch — aborting deep compare"));
process.exit(1);
}
// Reassemble both and deep compare the FullCustomer arrays
const customersA = reassembleFlattenedCustomer(flatCurrent);
const customersB = reassembleFlattenedCustomer(flatOptim);
console.log(chalk.cyan(`\nReassembled ${customersA.length} customers (both queries)`));
if (customersA.length !== customersB.length) {
console.log(chalk.red(`Mismatch in reassembled customer counts: ${customersA.length} vs ${customersB.length}`));
process.exit(1);
}
// Sort by id for stable diff (same cursor order should already be aligned)
customersA.sort((a: any, b: any) => (a.internal_id ?? "").localeCompare(b.internal_id ?? ""));
customersB.sort((a: any, b: any) => (a.internal_id ?? "").localeCompare(b.internal_id ?? ""));
let diffs = 0;
for (let i = 0; i < customersA.length; i++) {
const a = sortDeep(customersA[i]);
const b = sortDeep(customersB[i]);
const ja = JSON.stringify(a);
const jb = JSON.stringify(b);
if (ja !== jb) {
diffs++;
if (diffs <= 3) {
console.log(chalk.red(`\nDIFF for customer #${i} (${(customersA[i] as any).id}):`));
// find first differing key
for (const k of Object.keys(a as AnyRecord)) {
const va = JSON.stringify((a as AnyRecord)[k]);
const vb = JSON.stringify((b as AnyRecord)[k]);
if (va !== vb) {
console.log(` KEY ${k}:`);
console.log(chalk.gray(` current: ${va?.slice(0, 200)}`));
console.log(chalk.gray(` optim: ${vb?.slice(0, 200)}`));
}
}
}
}
}
if (diffs === 0) {
console.log(chalk.green(`\n✅ All ${customersA.length} customers match byte-for-byte`));
} else {
console.log(chalk.red(`\n❌ ${diffs}/${customersA.length} customers differ`));
}
} finally {
await client.end();
process.exit(0);
}
};
await main();

View File

@@ -1,426 +0,0 @@
import {
type AppEnv,
type CusProductStatus,
type FullCustomer,
type ListCustomersV2Params,
RELEVANT_STATUSES,
} from "@autumn/shared";
import chalk from "chalk";
import { sql } from "drizzle-orm";
import { initDrizzle } from "../src/db/initDrizzle";
import { getCursorPaginatedFullCusQuery } from "../src/internal/customers/cursorPaginatedFullCusQuery";
import { getPaginatedFullCusQuery } from "../src/internal/customers/getFullCusQuery";
import {
type FlattenedCustomerRow,
reassembleFlattenedCustomer,
} from "../src/internal/customers/reassembleFlattenedCustomer";
import { loadLocalEnv } from "../src/utils/envUtils";
loadLocalEnv();
const ORGS: { id: string; env: AppEnv; label: string }[] = [
{ id: "biu9vSF7vghBLSKW1UTDwxHBAivjnPaK", env: "live" as AppEnv, label: "firecrawl" },
{ id: "r7pwHiekGsqt32qGqcVku6thWFh5aHh8", env: "live" as AppEnv, label: "runable" },
];
const LIMIT = parseInt(process.env.DIFF_LIMIT ?? "50", 10);
const DEEP_OFFSET = parseInt(process.env.DIFF_DEEP_OFFSET ?? "500", 10);
const CUS_PRODUCT_LIMIT = 15;
const STATEMENT_TIMEOUT_MS = 30_000;
type ResolvedParams = Partial<ListCustomersV2Params> & {
offset?: number;
cursor?: { t: number; id: string };
};
type CaseContext = { db: DB; orgId: string; env: AppEnv };
type Case = {
name: string;
build: (ctx: CaseContext) => Promise<ResolvedParams | null>;
};
type DB = ReturnType<typeof initDrizzle>["db"];
const runReadOnly = async <T,>(db: DB, fn: (tx: any) => Promise<T>): Promise<T> => {
return await db.transaction(async (tx) => {
await tx.execute(
sql.raw(`SET LOCAL statement_timeout = ${STATEMENT_TIMEOUT_MS}`),
);
await tx.execute(sql.raw("SET LOCAL transaction_read_only = on"));
return fn(tx);
});
};
const v22NormalizeTimestamp = (value: any): number => {
if (typeof value === "string") {
const parsed = parseInt(value, 10);
return Number.isNaN(parsed) ? Date.now() : parsed;
}
return typeof value === "number" ? value : Date.now();
};
const v22Normalize = (raw: any): any => {
const out = {
...raw,
created_at: v22NormalizeTimestamp(raw.created_at),
};
if (raw.customer_products && Array.isArray(raw.customer_products)) {
out.customer_products = raw.customer_products.map((cp: any) => ({
...cp,
created_at: v22NormalizeTimestamp(cp.created_at),
starts_at: cp.starts_at
? v22NormalizeTimestamp(cp.starts_at)
: v22NormalizeTimestamp(cp.created_at),
canceled_at: cp.canceled_at ? v22NormalizeTimestamp(cp.canceled_at) : null,
ended_at: cp.ended_at ? v22NormalizeTimestamp(cp.ended_at) : null,
trial_ends_at: cp.trial_ends_at
? v22NormalizeTimestamp(cp.trial_ends_at)
: null,
quantity: cp.quantity ? parseInt(cp.quantity, 10) || 1 : 1,
options: cp.options || [],
collection_method: cp.collection_method || "charge_automatically",
subscription_ids: cp.subscription_ids || [],
scheduled_ids: cp.scheduled_ids || [],
customer_entitlements: (cp.customer_entitlements || []).map((ce: any) => ({
...ce,
created_at: v22NormalizeTimestamp(ce.created_at),
next_reset_at: ce.next_reset_at
? v22NormalizeTimestamp(ce.next_reset_at)
: null,
balance: ce.balance ? parseFloat(ce.balance) || 0 : 0,
adjustment: ce.adjustment ? parseFloat(ce.adjustment) || 0 : 0,
})),
}));
}
return out;
};
const fetchV22 = async (
db: DB,
orgId: string,
env: AppEnv,
params: ResolvedParams,
) => {
const { subscription_status, plans, search, processors, offset = 0 } = params;
const query = getPaginatedFullCusQuery({
orgId,
env,
inStatuses: subscription_status
? [subscription_status as unknown as CusProductStatus]
: RELEVANT_STATUSES,
includeInvoices: false,
withEntities: false,
withTrialsUsed: false,
withSubs: true,
limit: LIMIT,
offset,
search,
plans,
processors,
cusProductLimit: CUS_PRODUCT_LIMIT,
});
const rows = await runReadOnly(db, (tx) => tx.execute(query));
return (rows as any[]).map(v22Normalize) as FullCustomer[];
};
const fetchV23 = async (
db: DB,
orgId: string,
env: AppEnv,
params: ResolvedParams,
) => {
const { subscription_status, plans, search, processors, cursor } = params;
const query = getCursorPaginatedFullCusQuery({
orgId,
env,
inStatuses: subscription_status
? [subscription_status as unknown as CusProductStatus]
: RELEVANT_STATUSES,
withSubs: true,
limit: LIMIT,
search,
plans,
processors,
cursor: cursor ? { v: 0 as const, t: cursor.t, id: cursor.id } : undefined,
cusProductLimit: CUS_PRODUCT_LIMIT,
});
const rows = (await runReadOnly(db, (tx) => tx.execute(query))) as any[];
const flat = (rows[0] ?? {}) as unknown as FlattenedCustomerRow;
const all = reassembleFlattenedCustomer(flat);
return all.slice(0, LIMIT);
};
const resolveCursorAtOffset = async ({
db,
orgId,
env,
offset,
inStatuses,
plans,
processors,
search,
}: {
db: DB;
orgId: string;
env: AppEnv;
offset: number;
inStatuses?: CusProductStatus[];
plans?: ListCustomersV2Params["plans"];
processors?: ListCustomersV2Params["processors"];
search?: string;
}): Promise<{ t: number; id: string } | null> => {
const query = getPaginatedFullCusQuery({
orgId,
env,
inStatuses: inStatuses ?? RELEVANT_STATUSES,
includeInvoices: false,
withEntities: false,
withTrialsUsed: false,
withSubs: false,
limit: 1,
offset: offset - 1,
search,
plans,
processors,
cusProductLimit: 1,
});
const rows = (await runReadOnly(db, (tx) => tx.execute(query))) as any[];
if (rows.length === 0) return null;
const row = rows[0] as { id: string; created_at: number | string };
return { t: v22NormalizeTimestamp(row.created_at), id: row.id };
};
const resolveFirstPlanId = async ({
db,
orgId,
env,
}: {
db: DB;
orgId: string;
env: AppEnv;
}): Promise<string | null> => {
const rows = (await runReadOnly(
db,
(tx) => tx.execute(sql`
SELECT p.id
FROM products p
JOIN customer_products cp ON cp.internal_product_id = p.internal_id
WHERE p.org_id = ${orgId} AND p.env = ${env}
GROUP BY p.id
ORDER BY COUNT(*) DESC
LIMIT 1
`),
)) as any[];
return rows[0]?.id ?? null;
};
const resolveSearchSubstring = async ({
db,
orgId,
env,
}: {
db: DB;
orgId: string;
env: AppEnv;
}): Promise<string | null> => {
const rows = (await runReadOnly(
db,
(tx) => tx.execute(sql`
SELECT c.email
FROM customers c
WHERE c.org_id = ${orgId} AND c.env = ${env}
AND c.email IS NOT NULL
AND length(c.email) >= 5
LIMIT 1
`),
)) as any[];
const email = rows[0]?.email as string | undefined;
if (!email) return null;
const at = email.indexOf("@");
if (at < 3) return email.slice(0, 3);
return email.slice(0, Math.min(at, 4));
};
const CASES: Case[] = [
{
name: "page 1 / no filters",
build: async () => ({}),
},
{
name: "page 1 / subscription_status=active",
build: async () => ({ subscription_status: "active" }),
},
{
name: "page 1 / processors=revenuecat",
build: async () => ({ processors: ["revenuecat"] }),
},
{
name: "page 1 / search",
build: async (ctx) => {
const search = await resolveSearchSubstring(ctx);
if (!search) return null;
return { search };
},
},
{
name: "page 1 / plans",
build: async (ctx) => {
const planId = await resolveFirstPlanId(ctx);
if (!planId) return null;
return { plans: [{ id: planId }] };
},
},
{
name: `deep / offset=${DEEP_OFFSET} / no filters`,
build: async (ctx) => {
const cursor = await resolveCursorAtOffset({
db: ctx.db,
orgId: ctx.orgId,
env: ctx.env,
offset: DEEP_OFFSET,
});
if (!cursor) return null;
return { offset: DEEP_OFFSET, cursor };
},
},
];
const findDiff = (a: any, b: any, path = "$"): string | null => {
if (a === b) return null;
if (a === null || b === null || a === undefined || b === undefined) {
return `${path}: ${JSON.stringify(a)} vs ${JSON.stringify(b)}`;
}
if (typeof a !== typeof b) {
return `${path}: type ${typeof a} vs ${typeof b}`;
}
if (Array.isArray(a) || Array.isArray(b)) {
if (!Array.isArray(a) || !Array.isArray(b)) {
return `${path}: array vs non-array`;
}
if (a.length !== b.length) {
return `${path}.length: ${a.length} vs ${b.length}`;
}
for (let i = 0; i < a.length; i++) {
const d = findDiff(a[i], b[i], `${path}[${i}]`);
if (d) return d;
}
return null;
}
if (typeof a === "object") {
const keys = new Set([...Object.keys(a), ...Object.keys(b)]);
for (const k of keys) {
const d = findDiff(a[k], b[k], `${path}.${k}`);
if (d) return d;
}
return null;
}
return `${path}: ${JSON.stringify(a)} vs ${JSON.stringify(b)}`;
};
const summarize = (label: string, list: FullCustomer[]) => {
const cps = list.reduce((n, c) => n + (c.customer_products?.length ?? 0), 0);
const subs = list.reduce(
(n, c) => n + (c.subscriptions?.length ?? 0),
0,
);
const extras = list.reduce(
(n, c) => n + (c.extra_customer_entitlements?.length ?? 0),
0,
);
return `${label}: ${list.length} cus / ${cps} cps / ${subs} subs / ${extras} loose_ces`;
};
const runOrg = async ({
db,
orgId,
env,
label,
}: {
db: DB;
orgId: string;
env: AppEnv;
label: string;
}) => {
console.log(
chalk.magentaBright(
`\n========= ${label} (${orgId}) env=${env} limit=${LIMIT} =========\n`,
),
);
let total = 0;
let passes = 0;
for (const c of CASES) {
total++;
console.log(chalk.cyan(`\n--- ${c.name} ---`));
const params = await c.build({ db, orgId, env });
if (!params) {
console.log(chalk.yellow(" ⊘ skipped (no data to build params)"));
passes++;
continue;
}
console.log(
chalk.gray(
` params: ${JSON.stringify(params, (_k, v) => (typeof v === "bigint" ? String(v) : v))}`,
),
);
const [v22, v23] = await Promise.all([
fetchV22(db, orgId, env, params),
fetchV23(db, orgId, env, params),
]);
console.log(chalk.gray(` ${summarize("V2.2", v22)}`));
console.log(chalk.gray(` ${summarize("V2.3", v23)}`));
const diff = findDiff(v22, v23);
if (diff) {
console.log(chalk.red(` ❌ DIFF at ${diff}`));
const idx = diff.match(/\$\[(\d+)\]/);
if (idx) {
const i = parseInt(idx[1]!, 10);
console.log(chalk.gray(` --- V2.2 [${i}] ---`));
console.log(chalk.gray(JSON.stringify(v22[i], null, 2).slice(0, 4000)));
console.log(chalk.gray(` --- V2.3 [${i}] ---`));
console.log(chalk.gray(JSON.stringify(v23[i], null, 2).slice(0, 4000)));
}
} else {
console.log(chalk.green(` ✓ MATCH`));
passes++;
}
}
console.log(
chalk.magentaBright(`\n ${label}: ${passes}/${total} cases match`),
);
return { total, passes };
};
const main = async () => {
const { db, client } = initDrizzle();
try {
let grandTotal = 0;
let grandPasses = 0;
for (const org of ORGS) {
try {
const { total, passes } = await runOrg({
db,
orgId: org.id,
env: org.env,
label: org.label,
});
grandTotal += total;
grandPasses += passes;
} catch (err) {
console.error(chalk.red(`\n❌ Org ${org.label} failed:`), err);
}
}
console.log(
chalk.magentaBright(
`\n========= TOTAL: ${grandPasses}/${grandTotal} cases match =========\n`,
),
);
} catch (error) {
console.error(chalk.red("\n❌ Diff failed:"));
console.error(error);
process.exit(1);
} finally {
await client.end();
process.exit(0);
}
};
await main();

View File

@@ -1,52 +0,0 @@
import chalk from "chalk";
import { sql } from "drizzle-orm";
import { initDrizzle } from "../src/db/initDrizzle";
import { loadLocalEnv } from "../src/utils/envUtils";
loadLocalEnv();
const main = async () => {
const { db, client } = initDrizzle();
try {
const tables = [
"customers",
"customer_products",
"customer_entitlements",
"customer_prices",
"subscriptions",
];
for (const t of tables) {
console.log(chalk.bold(`\n=== ${t} indexes ===`));
const r = (await db.execute(sql.raw(`
SELECT indexname, indexdef
FROM pg_indexes
WHERE tablename = '${t}' AND schemaname = 'public'
ORDER BY indexname
`))) as unknown as { indexname: string; indexdef: string }[];
for (const idx of r) {
console.log(` ${idx.indexname}`);
console.log(` ${idx.indexdef}`);
}
}
// Get total rows in customer_products across all orgs
console.log(chalk.bold("\n=== Global customer_products stats ==="));
const stats = (await db.execute(sql.raw(`
SELECT
reltuples::bigint AS estimated_rows,
pg_size_pretty(pg_relation_size('customer_products')) AS table_size,
pg_size_pretty(pg_indexes_size('customer_products')) AS indexes_size
FROM pg_class WHERE relname = 'customer_products'
`))) as unknown as { estimated_rows: string; table_size: string; indexes_size: string }[];
console.log(` estimated_rows=${stats[0].estimated_rows} table=${stats[0].table_size} indexes=${stats[0].indexes_size}`);
// Actual count globally
const real = (await db.execute(sql.raw(`SELECT COUNT(*)::int AS n FROM customer_products`))) as unknown as { n: number }[];
console.log(` actual_total_rows=${real[0].n.toLocaleString()}`);
} finally {
await client.end();
process.exit(0);
}
};
await main();

View File

@@ -1,90 +0,0 @@
import chalk from "chalk";
import { sql } from "drizzle-orm";
import { initDrizzle } from "../src/db/initDrizzle";
import { loadLocalEnv } from "../src/utils/envUtils";
loadLocalEnv();
const ORG_ID = "org_2sWv2S8LJ9iaTjLI6UtNsfL88Kt";
const main = async () => {
const { db, client } = initDrizzle();
try {
const tables = [
"customers",
"customer_products",
"customer_entitlements",
"customer_prices",
"subscriptions",
"entitlements",
"products",
"rollovers",
"replaceables",
"free_trials",
];
console.log(chalk.bold(`\nRow counts for org=${ORG_ID}:\n`));
for (const t of tables) {
const hasOrg = ["customers", "subscriptions", "entitlements", "products", "features"];
const col = hasOrg.includes(t)
? `WHERE org_id = '${ORG_ID}'`
: t === "customer_products" ||
t === "customer_entitlements" ||
t === "customer_prices"
? `WHERE internal_customer_id IN (SELECT internal_id FROM customers WHERE org_id = '${ORG_ID}')`
: "";
const start = performance.now();
const r = (await db.execute(
sql.raw(`SELECT COUNT(*)::int AS n FROM ${t} ${col}`),
)) as unknown as { n: number }[];
const n = r[0]?.n ?? 0;
console.log(
` ${t.padEnd(28)} ${n.toLocaleString().padStart(10)} (${(performance.now() - start).toFixed(0)}ms)`,
);
}
// Sample a customer to see if it has any products
const sample = (await db.execute(sql.raw(`
SELECT c.internal_id, c.id,
(SELECT COUNT(*)::int FROM customer_products cp WHERE cp.internal_customer_id = c.internal_id) AS cp_count,
(SELECT COUNT(*)::int FROM customer_entitlements ce WHERE ce.internal_customer_id = c.internal_id) AS ce_count
FROM customers c
WHERE c.org_id = '${ORG_ID}'
ORDER BY c.created_at DESC
LIMIT 10
`))) as unknown as Record<string, unknown>[];
console.log(chalk.bold(`\nFirst 10 customers by created_at DESC:\n`));
for (const row of sample) {
console.log(
` ${(row.id as string).padEnd(30)} cp=${row.cp_count} ce=${row.ce_count}`,
);
}
// Histogram: how many customers have N products?
const hist = (await db.execute(sql.raw(`
SELECT cp_bucket, COUNT(*)::int AS customer_count FROM (
SELECT c.internal_id,
LEAST(
(SELECT COUNT(*)::int FROM customer_products cp WHERE cp.internal_customer_id = c.internal_id),
10
) AS cp_bucket
FROM customers c
WHERE c.org_id = '${ORG_ID}'
) t
GROUP BY cp_bucket
ORDER BY cp_bucket
`))) as unknown as { cp_bucket: number; customer_count: number }[];
console.log(chalk.bold(`\nCustomer × #products histogram (capped at 10):\n`));
for (const row of hist) {
const bar = "█".repeat(Math.min(60, Math.floor(row.customer_count / 5000)));
console.log(
` ${row.cp_bucket.toString().padStart(2)}: ${row.customer_count.toLocaleString().padStart(8)} ${bar}`,
);
}
} finally {
await client.end();
process.exit(0);
}
};
await main();

View File

@@ -1,173 +0,0 @@
import type {
AppEnv,
CusProductStatus,
ListCustomersV2Params,
StandardCursorFields,
} from "@autumn/shared";
import { sql } from "drizzle-orm";
import { getCustomerListFilterSql } from "../src/internal/customers/getFullCusQuery";
export type OptimizedQueryArgs = {
orgId: string;
env: AppEnv;
inStatuses?: CusProductStatus[];
withSubs?: boolean;
limit: number;
cursor?: StandardCursorFields;
internalCustomerIds?: string[];
plans?: ListCustomersV2Params["plans"];
processors?: ListCustomersV2Params["processors"];
search?: string;
cusProductLimit: number;
};
/**
* Set-based replacement for the per-customer LATERAL nested loops.
* Key change: each child fetch is a single hash/merge join over the cr CTE
* instead of 1001 sequential scans (original Seq Scan-per-loop pattern).
*/
export const getOptimizedFullCusQuery = ({
orgId,
env,
inStatuses,
withSubs = true,
limit,
cursor,
internalCustomerIds,
plans,
processors,
search,
cusProductLimit,
}: OptimizedQueryArgs) => {
const cpStatusFilter = inStatuses?.length
? sql`AND cp.status = ANY(ARRAY[${sql.join(
inStatuses.map((status) => sql`${status}`),
sql`, `,
)}])`
: sql``;
const customerListFilterSql = getCustomerListFilterSql({
internalCustomerIds,
inStatuses,
plans,
processors,
search,
});
const cursorPredicate = cursor
? sql`AND (c.created_at, c.id) < (${cursor.t}, ${cursor.id})`
: sql``;
const fetchLimit = limit + 1;
const subscriptionsSelect = withSubs
? sql`(
SELECT COALESCE(json_agg(row_to_json(s)), '[]'::json)
FROM (
SELECT DISTINCT s.*
FROM cps_ranked cps
CROSS JOIN LATERAL unnest(cps.subscription_ids) AS sub_id_t(sub_id)
JOIN subscriptions s ON s.stripe_id = sub_id_t.sub_id
WHERE cps.subscription_ids IS NOT NULL
) s
) AS subscriptions`
: sql`'[]'::json AS subscriptions`;
return sql`
WITH cr AS MATERIALIZED (
SELECT
c.internal_id,
c.id,
c.created_at,
row_to_json(c) AS row_json
FROM customers c
WHERE c.org_id = ${orgId}
AND c.env = ${env}
${customerListFilterSql}
${cursorPredicate}
ORDER BY c.created_at DESC, c.id DESC
LIMIT ${fetchLimit}
),
cp_ranked_ids AS MATERIALIZED (
SELECT
cp.id,
cp.internal_customer_id,
cp.internal_product_id,
ROW_NUMBER() OVER (
PARTITION BY cp.internal_customer_id
ORDER BY prod.is_add_on ASC, cp.created_at DESC
) AS rn
FROM cr
JOIN customer_products cp ON cp.internal_customer_id = cr.internal_id
JOIN products prod ON prod.internal_id = cp.internal_product_id
WHERE TRUE ${cpStatusFilter}
),
cps_ranked AS MATERIALIZED (
SELECT
cp.id,
cp.internal_customer_id,
cp.internal_product_id,
cp.free_trial_id,
cp.subscription_ids,
(row_to_json(cp)::jsonb || jsonb_build_object('product', row_to_json(prod)))::json AS row_json
FROM cp_ranked_ids r
JOIN customer_products cp ON cp.id = r.id
JOIN products prod ON prod.internal_id = r.internal_product_id
WHERE r.rn <= ${cusProductLimit}
),
ces_bound AS MATERIALIZED (
-- Single hash join instead of 1001 LATERAL scans.
SELECT ce.id, ce.entitlement_id, row_to_json(ce) AS row_json
FROM cps_ranked
JOIN customer_entitlements ce ON ce.customer_product_id = cps_ranked.id
),
ces_loose AS MATERIALIZED (
-- LATERAL with LIMIT 30 stays; existing partial index is well-suited.
SELECT ce.id, ce.entitlement_id, row_to_json(ce) AS row_json
FROM cr
JOIN LATERAL (
SELECT ce.*
FROM customer_entitlements ce
WHERE ce.internal_customer_id = cr.internal_id
AND ce.customer_product_id IS NULL
AND (ce.expires_at IS NULL OR ce.expires_at > EXTRACT(EPOCH FROM now()) * 1000)
ORDER BY ce.id DESC
LIMIT 30
) ce ON true
),
ces_all AS MATERIALIZED (
SELECT id, entitlement_id FROM ces_bound
UNION ALL
SELECT id, entitlement_id FROM ces_loose
)
SELECT
(SELECT COALESCE(json_agg(row_json), '[]'::json) FROM cr) AS customers,
(SELECT COALESCE(json_agg(row_json), '[]'::json) FROM cps_ranked) AS customer_products,
(SELECT COALESCE(json_agg(row_json), '[]'::json) FROM ces_bound) AS customer_entitlements,
(SELECT COALESCE(json_agg(row_json ORDER BY id DESC), '[]'::json) FROM ces_loose) AS extra_customer_entitlements,
(SELECT COALESCE(json_agg(row_to_json(cpr)::jsonb || jsonb_build_object('price', row_to_json(p))), '[]'::json)
FROM cps_ranked
JOIN customer_prices cpr ON cpr.customer_product_id = cps_ranked.id
LEFT JOIN prices p ON p.id = cpr.price_id
) AS customer_prices,
(SELECT COALESCE(json_agg(row_to_json(e)::jsonb || jsonb_build_object('feature', row_to_json(f))), '[]'::json)
FROM (SELECT DISTINCT entitlement_id FROM ces_all) ce
JOIN entitlements e ON e.id = ce.entitlement_id
JOIN features f ON f.internal_id = e.internal_feature_id
) AS entitlements,
(SELECT COALESCE(json_agg(row_to_json(ro)), '[]'::json)
FROM ces_all
JOIN rollovers ro ON ro.cus_ent_id = ces_all.id
WHERE ro.expires_at IS NULL OR ro.expires_at > EXTRACT(EPOCH FROM now()) * 1000
) AS rollovers,
(SELECT COALESCE(json_agg(row_to_json(r)), '[]'::json)
FROM ces_all
JOIN replaceables r ON r.cus_ent_id = ces_all.id
) AS replaceables,
(SELECT COALESCE(json_agg(row_to_json(ft)), '[]'::json)
FROM (SELECT DISTINCT free_trial_id FROM cps_ranked WHERE free_trial_id IS NOT NULL) cps
JOIN free_trials ft ON ft.id = cps.free_trial_id
) AS free_trials,
${subscriptionsSelect}
`;
};

View File

@@ -1,368 +0,0 @@
import { AppEnv } from "@autumn/shared";
import chalk from "chalk";
import { sql, type SQL } from "drizzle-orm";
import { writeFileSync } from "node:fs";
import { join } from "node:path";
import { RELEVANT_STATUSES } from "../src/internal/customers/cusProducts/CusProductService";
import { initDrizzle } from "../src/db/initDrizzle";
import { loadLocalEnv } from "../src/utils/envUtils";
import { getCursorPaginatedFullCusQuery } from "../src/internal/customers/cursorPaginatedFullCusQuery";
loadLocalEnv();
const ORG_ID = "r7pwHiekGsqt32qGqcVku6thWFh5aHh8";
const ENV: AppEnv = AppEnv.Live;
const LABEL = "runable";
const REPEATS = 5;
const STATEMENT_TIMEOUT_MS = 30_000;
const DEEP_OFFSET_PCT = 45;
const BASE_LIMIT = 1000;
const READ_ONLY = true;
const CUS_PRODUCT_LIMIT = 15;
const RESULTS_DIR = join(import.meta.dir, "results");
type DB = ReturnType<typeof initDrizzle>["db"];
const sharedFullCusOpts = {
inStatuses: RELEVANT_STATUSES,
includeInvoices: false,
withEntities: false,
withTrialsUsed: false,
withSubs: true,
cusProductLimit: CUS_PRODUCT_LIMIT,
};
type Cell = {
name: string;
build: () => SQL;
includeExplain?: boolean;
};
type CellResult = {
name: string;
medianMs: number;
p95Ms: number;
minMs: number;
maxMs: number;
rowCount: number;
samples: number[];
explainPlan?: string;
error?: string;
};
const normalizeRows = (r: unknown): Record<string, unknown>[] => {
if (Array.isArray(r)) return r as Record<string, unknown>[];
if (r && typeof r === "object" && "rows" in r) {
return (r as { rows: Record<string, unknown>[] }).rows;
}
return [];
};
const runQueryInTxn = async ({
db,
query,
}: {
db: DB;
query: SQL;
}): Promise<Record<string, unknown>[]> => {
return await db.transaction(async (tx) => {
await tx.execute(sql.raw(`SET LOCAL statement_timeout = ${STATEMENT_TIMEOUT_MS}`));
if (READ_ONLY) {
await tx.execute(sql.raw("SET LOCAL transaction_read_only = on"));
}
return normalizeRows(await tx.execute(query));
});
};
const measureCell = async ({
db,
cell,
}: {
db: DB;
cell: Cell;
}): Promise<CellResult> => {
const samples: number[] = [];
let rowCount = 0;
let error: string | undefined;
for (let i = 0; i < REPEATS; i++) {
const query = cell.build();
const startedAt = performance.now();
try {
const result = await runQueryInTxn({ db, query });
const elapsed = performance.now() - startedAt;
samples.push(elapsed);
rowCount = result.length;
} catch (err) {
const elapsed = performance.now() - startedAt;
samples.push(elapsed);
error = err instanceof Error ? err.message : String(err);
break;
}
}
let explainPlan: string | undefined;
if (cell.includeExplain && !error) {
try {
const query = cell.build();
const explainRows = await runQueryInTxn({
db,
query: sql`EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT) ${query}`,
});
explainPlan = explainRows.map((row) => row["QUERY PLAN"]).join("\n");
} catch (err) {
explainPlan = `EXPLAIN failed: ${err instanceof Error ? err.message : String(err)}`;
}
}
const sorted = [...samples].sort((a, b) => a - b);
const median = sorted[Math.floor(sorted.length / 2)] ?? 0;
const p95 = sorted[Math.min(sorted.length - 1, Math.floor(sorted.length * 0.95))] ?? 0;
const min = sorted[0] ?? 0;
const max = sorted[sorted.length - 1] ?? 0;
return {
name: cell.name,
medianMs: median,
p95Ms: p95,
minMs: min,
maxMs: max,
rowCount,
samples,
explainPlan,
error,
};
};
const revenuecatCountQuery = (): SQL => sql`
SELECT COUNT(*)::int AS total_count
FROM customers c
WHERE c.org_id = ${ORG_ID}
AND c.env = ${ENV}
AND EXISTS (
SELECT 1 FROM customer_products cp
WHERE cp.internal_customer_id = c.internal_id
AND cp.processor->>'type' = 'revenuecat'
)
`;
const resolveRevenuecatCount = async ({ db }: { db: DB }) => {
const result = await runQueryInTxn({ db, query: revenuecatCountQuery() });
return (result[0] as { total_count: number }).total_count;
};
const resolveRevenuecatDeepCursor = async ({
db,
deepOffset,
}: {
db: DB;
deepOffset: number;
}): Promise<{ v: 0; t: number; id: string }> => {
const result = await runQueryInTxn({
db,
query: sql`
SELECT c.created_at, c.id
FROM customers c
WHERE c.org_id = ${ORG_ID}
AND c.env = ${ENV}
AND EXISTS (
SELECT 1 FROM customer_products cp
WHERE cp.internal_customer_id = c.internal_id
AND cp.processor->>'type' = 'revenuecat'
)
ORDER BY c.created_at DESC, c.id DESC
LIMIT 1 OFFSET ${deepOffset}
`,
});
const row = result[0] as { created_at: number; id: string } | undefined;
if (!row) {
throw new Error(
`Could not resolve revenuecat deep cursor at offset ${deepOffset}. Not enough revenuecat customers.`,
);
}
return { v: 0, t: row.created_at, id: row.id };
};
const buildCells = ({
deepCursor,
}: {
deepCursor: { v: 0; t: number; id: string };
}): Cell[] => {
return [
{
name: `10 cursor / revcat=true / first page / limit ${BASE_LIMIT}`,
build: () =>
getCursorPaginatedFullCusQuery({
orgId: ORG_ID,
env: ENV,
limit: BASE_LIMIT,
processors: ["revenuecat"],
...sharedFullCusOpts,
}),
includeExplain: true,
},
{
name: `11 cursor / revcat=true / deep / limit ${BASE_LIMIT}`,
build: () =>
getCursorPaginatedFullCusQuery({
orgId: ORG_ID,
env: ENV,
limit: BASE_LIMIT,
cursor: deepCursor,
processors: ["revenuecat"],
...sharedFullCusOpts,
}),
includeExplain: true,
},
];
};
const renderResults = ({
totalCount,
deepOffset,
deepCursor,
results,
}: {
totalCount: number;
deepOffset: number;
deepCursor: { v: 0; t: number; id: string };
results: CellResult[];
}): string => {
const date = new Date().toISOString().slice(0, 10);
const lines: string[] = [];
lines.push(`# Pagination Benchmark — ${date} — prod / ${LABEL}`);
lines.push("");
lines.push("## Config");
lines.push("");
lines.push(`- org_id: \`${ORG_ID}\``);
lines.push(`- env: \`${ENV}\``);
lines.push(`- revenuecat_customers: \`${totalCount.toLocaleString()}\``);
lines.push(
`- deep_offset (${DEEP_OFFSET_PCT}% within revcat subset): \`${deepOffset.toLocaleString()}\``,
);
lines.push(
`- deep_cursor (revcat-aware): \`{ t: ${deepCursor.t}, id: ${deepCursor.id} }\``,
);
lines.push(`- limit: \`${BASE_LIMIT}\``);
lines.push(`- repeats per cell: ${REPEATS}`);
lines.push(`- statement_timeout_ms: ${STATEMENT_TIMEOUT_MS}`);
lines.push(`- read_only: ${READ_ONLY}`);
lines.push(`- focus: revenuecat filter (single SQL call, cursor + EXISTS combined)`);
lines.push(`- partial index in place: idx_customer_products_revenuecat_processor`);
lines.push("");
lines.push("## Results");
lines.push("");
lines.push("| # | Cell | Rows | median ms | p95 ms | min ms | max ms | Error |");
lines.push("|---|------|------|-----------|--------|--------|--------|-------|");
for (const r of results) {
const idx = r.name.split(" ")[0];
const desc = r.name.split(" ").slice(1).join(" ");
const errCol = r.error ? `\`${r.error.slice(0, 80)}\`` : "";
lines.push(
`| ${idx} | ${desc} | ${r.rowCount} | ${r.medianMs.toFixed(2)} | ${r.p95Ms.toFixed(2)} | ${r.minMs.toFixed(2)} | ${r.maxMs.toFixed(2)} | ${errCol} |`,
);
}
lines.push("");
lines.push("## EXPLAIN ANALYZE");
lines.push("");
for (const r of results) {
if (!r.explainPlan) continue;
lines.push(`### ${r.name}`);
lines.push("");
lines.push("```");
lines.push(r.explainPlan);
lines.push("```");
lines.push("");
}
return lines.join("\n");
};
const main = async () => {
console.log(
chalk.magentaBright(
`\n================ Pagination Benchmark — prod / ${LABEL} ================\n`,
),
);
const { db, client } = initDrizzle();
try {
console.log(chalk.cyan(`Org: ${ORG_ID} (${ENV})`));
console.log(chalk.cyan("Resolving revenuecat customer count..."));
const totalCount = await resolveRevenuecatCount({ db });
const deepOffset = Math.floor((totalCount * DEEP_OFFSET_PCT) / 100);
console.log(
chalk.gray(
` revenuecat_customers = ${totalCount.toLocaleString()}, deep_offset (${DEEP_OFFSET_PCT}% within revcat) = ${deepOffset.toLocaleString()}`,
),
);
console.log(
chalk.cyan(`Resolving revcat-aware deep cursor at offset ${deepOffset}...`),
);
const deepCursor = await resolveRevenuecatDeepCursor({ db, deepOffset });
console.log(
chalk.gray(` cursor = { t: ${deepCursor.t}, id: ${deepCursor.id} }`),
);
console.log();
const cells = buildCells({ deepCursor });
const results: CellResult[] = [];
for (let i = 0; i < cells.length; i++) {
const cell = cells[i];
process.stdout.write(
chalk.gray(`[${i + 1}/${cells.length}] ${cell.name} ... `),
);
const result = await measureCell({ db, cell });
results.push(result);
if (result.error) {
console.log(chalk.red(`error: ${result.error.slice(0, 80)}`));
} else {
console.log(
chalk.green(
`median=${result.medianMs.toFixed(2)}ms p95=${result.p95Ms.toFixed(2)}ms rows=${result.rowCount}`,
),
);
}
}
const report = renderResults({
totalCount,
deepOffset,
deepCursor,
results,
});
const date = new Date().toISOString().slice(0, 10);
const outPath = join(RESULTS_DIR, `${date}-prod-${LABEL}.md`);
writeFileSync(outPath, report);
console.log();
console.log(chalk.green(`✅ Report written to ${outPath}`));
console.log(
chalk.magentaBright(
`\n================ Benchmark Complete ================\n`,
),
);
} catch (error) {
console.error(chalk.red("\n❌ Benchmark failed:"));
if (error instanceof Error) {
console.error(chalk.red(` ${error.message}`));
console.error(chalk.gray(error.stack));
} else {
console.error(chalk.red(` ${String(error)}`));
}
process.exit(1);
} finally {
await client.end();
process.exit(0);
}
};
await main();

View File

@@ -1,678 +0,0 @@
import { AppEnv, CusProductStatus, type ListCustomersV2Params } from "@autumn/shared";
import chalk from "chalk";
import { sql, type SQL } from "drizzle-orm";
import { writeFileSync } from "node:fs";
import { join } from "node:path";
import { initDrizzle } from "../src/db/initDrizzle";
import { getCursorPaginatedFullCusQuery } from "../src/internal/customers/cursorPaginatedFullCusQuery";
import { getPaginatedFullCusQuery } from "../src/internal/customers/getFullCusQuery";
import { RELEVANT_STATUSES } from "../src/internal/customers/cusProducts/CusProductService";
import { loadLocalEnv } from "../src/utils/envUtils";
loadLocalEnv();
// Runs against whatever DATABASE_URL points at. Intentionally bypasses
// the prod-safety guard — laptop → prod is the entire point.
const FIRECRAWL_ORG_ID = "biu9vSF7vghBLSKW1UTDwxHBAivjnPaK";
const RUNABLE_ORG_ID = "r7pwHiekGsqt32qGqcVku6thWFh5aHh8";
const ENV: AppEnv = AppEnv.Live;
const BASE_LIMIT = 1000;
const REPEATS = 5;
const STATEMENT_TIMEOUT_MS = 60_000;
const READ_ONLY = true;
const CUS_PRODUCT_LIMIT = 15;
const DEEP_OFFSET_PCT = 45;
const FIRECRAWL_BASELINE_DEEP_OFFSET = 950_000;
const PLAN_MASSIVE = "free";
const PLAN_MID = "hobby";
const PLAN_RARE = "scale_monthly";
const SEARCH_GMAIL = "@gmail";
const RESULTS_DIR = join(import.meta.dir, "results");
type DB = ReturnType<typeof initDrizzle>["db"];
type Cursor = { v: 0; t: number; id: string };
type FilterOverrides = {
inStatuses?: CusProductStatus[];
search?: string;
plans?: ListCustomersV2Params["plans"];
processors?: ListCustomersV2Params["processors"];
internalCustomerIds?: string[];
};
type Scenario = {
key: string;
label: string;
org: "firecrawl" | "runable";
orgId: string;
filter: FilterOverrides;
withDeep: boolean;
deepOffset?: number;
deepCursor?: Cursor;
};
type Cell = {
scenarioKey: string;
scenarioLabel: string;
org: "firecrawl" | "runable";
queryShape: "offset" | "cursor";
depth: "page1" | "deep";
build: () => SQL;
};
type CellResult = Cell & {
medianMs: number;
p95Ms: number;
minMs: number;
maxMs: number;
rowCount: number;
samples: number[];
error?: string;
};
const sharedFullCusOpts = {
includeInvoices: false,
withEntities: false,
withTrialsUsed: false,
withSubs: true,
cusProductLimit: CUS_PRODUCT_LIMIT,
};
const normalizeRows = (r: unknown): Record<string, unknown>[] => {
if (Array.isArray(r)) return r as Record<string, unknown>[];
if (r && typeof r === "object" && "rows" in r) {
return (r as { rows: Record<string, unknown>[] }).rows;
}
return [];
};
const runQueryInTxn = async ({
db,
query,
}: { db: DB; query: SQL }): Promise<Record<string, unknown>[]> => {
return await db.transaction(async (tx) => {
await tx.execute(
sql.raw(`SET LOCAL statement_timeout = ${STATEMENT_TIMEOUT_MS}`),
);
if (READ_ONLY) {
await tx.execute(sql.raw("SET LOCAL transaction_read_only = on"));
}
return normalizeRows(await tx.execute(query));
});
};
const measureCell = async ({
db,
cell,
}: { db: DB; cell: Cell }): Promise<CellResult> => {
const samples: number[] = [];
let rowCount = 0;
let error: string | undefined;
for (let i = 0; i < REPEATS; i++) {
const query = cell.build();
const startedAt = performance.now();
try {
const result = await runQueryInTxn({ db, query });
const elapsed = performance.now() - startedAt;
samples.push(elapsed);
rowCount = result.length;
} catch (err) {
const elapsed = performance.now() - startedAt;
samples.push(elapsed);
error = err instanceof Error ? err.message : String(err);
break;
}
}
const sorted = [...samples].sort((a, b) => a - b);
const median = sorted[Math.floor(sorted.length / 2)] ?? 0;
const p95 =
sorted[Math.min(sorted.length - 1, Math.floor(sorted.length * 0.95))] ?? 0;
const min = sorted[0] ?? 0;
const max = sorted[sorted.length - 1] ?? 0;
return {
...cell,
medianMs: median,
p95Ms: p95,
minMs: min,
maxMs: max,
rowCount,
samples,
error,
};
};
// Per-filter predicate matching getCustomerListFilterSql, used by the
// resolver helpers (count + deep cursor) so deep cells are filter-aware.
const filterPredicate = (f: FilterOverrides): SQL => {
const parts: SQL[] = [];
if (f.internalCustomerIds?.length) {
parts.push(
sql`AND c.internal_id IN (${sql.join(
f.internalCustomerIds.map((id) => sql`${id}`),
sql`, `,
)})`,
);
}
if (f.plans?.length) {
const planConditions = f.plans.map((plan) => {
if (plan.versions?.length) {
return sql`(p_filter.id = ${plan.id} AND p_filter.version IN (${sql.join(
plan.versions.map((v) => sql`${v}`),
sql`, `,
)}))`;
}
return sql`p_filter.id = ${plan.id}`;
});
parts.push(sql`AND EXISTS (
SELECT 1
FROM customer_products cp_filter
JOIN products p_filter ON cp_filter.internal_product_id = p_filter.internal_id
WHERE cp_filter.internal_customer_id = c.internal_id
${
f.inStatuses?.length
? sql`AND cp_filter.status = ANY(ARRAY[${sql.join(
f.inStatuses.map((s) => sql`${s}`),
sql`, `,
)}])`
: sql``
}
AND (${sql.join(planConditions, sql` OR `)})
)`);
}
const trimmedSearch = f.search?.trim();
if (trimmedSearch) {
const pattern = `%${trimmedSearch}%`;
parts.push(sql`AND (
c.id ILIKE ${pattern}
OR c.name ILIKE ${pattern}
OR c.email ILIKE ${pattern}
)`);
}
if (f.processors?.length) {
const procConditions = f.processors
.map((proc) => {
if (proc === "stripe") return sql`(c.processor->>'id' IS NOT NULL)`;
if (proc === "revenuecat")
return sql`EXISTS (
SELECT 1
FROM customer_products cp_processor
WHERE cp_processor.internal_customer_id = c.internal_id
AND cp_processor.processor->>'type' = 'revenuecat'
)`;
if (proc === "vercel") return sql`(c.processors->>'vercel' IS NOT NULL)`;
return null;
})
.filter((c): c is SQL => c !== null);
if (procConditions.length) {
parts.push(sql`AND (${sql.join(procConditions, sql` OR `)})`);
}
}
return parts.length ? sql.join(parts, sql` `) : sql``;
};
const resolveCount = async ({
db,
orgId,
filter,
}: { db: DB; orgId: string; filter: FilterOverrides }): Promise<number> => {
const predicate = filterPredicate(filter);
const rows = await runQueryInTxn({
db,
query: sql`
SELECT COUNT(*)::int AS total_count
FROM customers c
WHERE c.org_id = ${orgId}
AND c.env = ${ENV}
${predicate}
`,
});
return (rows[0] as { total_count: number }).total_count;
};
const resolveDeepCursor = async ({
db,
orgId,
filter,
deepOffset,
}: {
db: DB;
orgId: string;
filter: FilterOverrides;
deepOffset: number;
}): Promise<Cursor> => {
const predicate = filterPredicate(filter);
const rows = await runQueryInTxn({
db,
query: sql`
SELECT c.created_at, c.id
FROM customers c
WHERE c.org_id = ${orgId}
AND c.env = ${ENV}
${predicate}
ORDER BY c.created_at DESC, c.id DESC
LIMIT 1 OFFSET ${deepOffset}
`,
});
const row = rows[0] as { created_at: number; id: string } | undefined;
if (!row) {
throw new Error(
`No row at deep offset ${deepOffset} for filter ${JSON.stringify(filter)}`,
);
}
return { v: 0, t: row.created_at, id: row.id };
};
const resolveFirecrawlInternalIds = async ({
db,
}: { db: DB }): Promise<string[]> => {
const rows = await runQueryInTxn({
db,
query: sql`
SELECT internal_id
FROM customers
WHERE org_id = ${FIRECRAWL_ORG_ID}
AND env = ${ENV}
ORDER BY created_at DESC, id DESC
LIMIT 10
`,
});
return rows.map((r) => (r as { internal_id: string }).internal_id);
};
const buildScenarios = ({
firecrawlInternalIds,
}: { firecrawlInternalIds: string[] }): Scenario[] => {
const fc = (
key: string,
label: string,
filter: FilterOverrides,
withDeep: boolean,
): Scenario => ({
key,
label,
org: "firecrawl",
orgId: FIRECRAWL_ORG_ID,
filter,
withDeep,
});
return [
fc("01-baseline", "none (baseline)", {}, true),
fc("02-search-gmail", `search '${SEARCH_GMAIL}'`, { search: SEARCH_GMAIL }, true),
fc(
"03-status-active",
"inStatuses=['active']",
{ inStatuses: [CusProductStatus.Active] },
true,
),
fc("04-plan-massive", `plans=['${PLAN_MASSIVE}']`, { plans: [{ id: PLAN_MASSIVE }] }, true),
fc("05-plan-mid", `plans=['${PLAN_MID}']`, { plans: [{ id: PLAN_MID }] }, true),
fc("06-plan-rare", `plans=['${PLAN_RARE}']`, { plans: [{ id: PLAN_RARE }] }, false),
fc("07-processor-stripe", "processors=['stripe']", { processors: ["stripe"] }, true),
fc(
"08-internal-ids",
"internalCustomerIds=[10]",
{ internalCustomerIds: firecrawlInternalIds },
false,
),
{
key: "09-processor-revenuecat",
label: "processors=['revenuecat']",
org: "runable",
orgId: RUNABLE_ORG_ID,
filter: { processors: ["revenuecat"] },
withDeep: false,
},
];
};
const buildCellsForScenario = (s: Scenario): Cell[] => {
const inStatuses = s.filter.inStatuses ?? RELEVANT_STATUSES;
const filterArgs = {
inStatuses,
search: s.filter.search,
plans: s.filter.plans,
processors: s.filter.processors,
internalCustomerIds: s.filter.internalCustomerIds,
};
const cells: Cell[] = [
{
scenarioKey: s.key,
scenarioLabel: s.label,
org: s.org,
queryShape: "offset",
depth: "page1",
build: () =>
getPaginatedFullCusQuery({
orgId: s.orgId,
env: ENV,
limit: BASE_LIMIT,
offset: 0,
...sharedFullCusOpts,
...filterArgs,
}),
},
{
scenarioKey: s.key,
scenarioLabel: s.label,
org: s.org,
queryShape: "cursor",
depth: "page1",
build: () =>
getCursorPaginatedFullCusQuery({
orgId: s.orgId,
env: ENV,
limit: BASE_LIMIT,
...sharedFullCusOpts,
...filterArgs,
}),
},
];
if (s.withDeep && s.deepOffset !== undefined && s.deepCursor) {
const deepOffset = s.deepOffset;
const deepCursor = s.deepCursor;
cells.push(
{
scenarioKey: s.key,
scenarioLabel: s.label,
org: s.org,
queryShape: "offset",
depth: "deep",
build: () =>
getPaginatedFullCusQuery({
orgId: s.orgId,
env: ENV,
limit: BASE_LIMIT,
offset: deepOffset,
...sharedFullCusOpts,
...filterArgs,
}),
},
{
scenarioKey: s.key,
scenarioLabel: s.label,
org: s.org,
queryShape: "cursor",
depth: "deep",
build: () =>
getCursorPaginatedFullCusQuery({
orgId: s.orgId,
env: ENV,
limit: BASE_LIMIT,
cursor: deepCursor,
...sharedFullCusOpts,
...filterArgs,
}),
},
);
}
return cells;
};
const pairResults = (
results: CellResult[],
): {
scenarioKey: string;
scenarioLabel: string;
org: string;
depth: "page1" | "deep";
offset?: CellResult;
cursor?: CellResult;
}[] => {
const groups = new Map<
string,
{
scenarioKey: string;
scenarioLabel: string;
org: string;
depth: "page1" | "deep";
offset?: CellResult;
cursor?: CellResult;
}
>();
for (const r of results) {
const key = `${r.scenarioKey}|${r.depth}`;
const group = groups.get(key) ?? {
scenarioKey: r.scenarioKey,
scenarioLabel: r.scenarioLabel,
org: r.org,
depth: r.depth,
};
if (r.queryShape === "offset") group.offset = r;
else group.cursor = r;
groups.set(key, group);
}
return Array.from(groups.values());
};
const fmt = (n: number | undefined): string =>
n === undefined ? "—" : n.toFixed(0);
const renderReport = ({
scenarios,
pairs,
totalWallMs,
dbHost,
}: {
scenarios: Scenario[];
pairs: ReturnType<typeof pairResults>;
totalWallMs: number;
dbHost: string;
}): string => {
const date = new Date().toISOString().slice(0, 10);
const lines: string[] = [];
lines.push(`# Pagination Benchmark — offset vs cursor — ${date}`);
lines.push("");
lines.push("## Config");
lines.push("");
lines.push(`- db host: \`${dbHost}\``);
lines.push(`- env: \`${ENV}\``);
lines.push(`- limit: ${BASE_LIMIT}`);
lines.push(`- repeats per cell: ${REPEATS}`);
lines.push(`- statement_timeout_ms: ${STATEMENT_TIMEOUT_MS}`);
lines.push(`- read_only: ${READ_ONLY}`);
lines.push(`- shared opts: withSubs=true, includeInvoices=false, withEntities=false, withTrialsUsed=false, cusProductLimit=${CUS_PRODUCT_LIMIT}`);
lines.push(`- timings are wall-clock from this laptop around drizzle execute (includes network round-trip + result transfer + deserialize)`);
lines.push(`- total benchmark wall time: ${(totalWallMs / 1000).toFixed(1)}s`);
lines.push("");
lines.push("## Scenarios resolved");
lines.push("");
lines.push("| # | Org | Filter | Filtered count | Deep offset | Deep cursor |");
lines.push("|---|-----|--------|----------------|-------------|-------------|");
for (const s of scenarios) {
const count = (s as Scenario & { resolvedCount?: number }).resolvedCount;
lines.push(
`| ${s.key} | ${s.org} | \`${s.label}\` | ${count?.toLocaleString() ?? "—"} | ${s.deepOffset?.toLocaleString() ?? "—"} | ${s.deepCursor ? `\`{ t: ${s.deepCursor.t}, id: ${s.deepCursor.id.slice(0, 8)}… }\`` : "—"} |`,
);
}
lines.push("");
lines.push("## Results");
lines.push("");
lines.push(
"| # | Org | Filter | Depth | offset median ms | cursor median ms | Δ ms | offset p95 | cursor p95 | offset rows | cursor rows | offset error | cursor error |",
);
lines.push(
"|---|-----|--------|-------|------------------|------------------|------|------------|------------|-------------|-------------|--------------|--------------|",
);
for (const p of pairs) {
const off = p.offset;
const cur = p.cursor;
const delta =
off && cur && !off.error && !cur.error
? cur.medianMs - off.medianMs
: undefined;
const deltaStr =
delta === undefined
? "—"
: `${delta >= 0 ? "+" : ""}${delta.toFixed(0)}`;
lines.push(
`| ${p.scenarioKey} | ${p.org} | \`${p.scenarioLabel}\` | ${p.depth} | ${fmt(off?.medianMs)} | ${fmt(cur?.medianMs)} | ${deltaStr} | ${fmt(off?.p95Ms)} | ${fmt(cur?.p95Ms)} | ${off?.rowCount ?? "—"} | ${cur?.rowCount ?? "—"} | ${off?.error ? `\`${off.error.slice(0, 50)}\`` : ""} | ${cur?.error ? `\`${cur.error.slice(0, 50)}\`` : ""} |`,
);
}
lines.push("");
lines.push("## Raw samples (per cell)");
lines.push("");
for (const p of pairs) {
lines.push(`### ${p.scenarioKey} / ${p.depth}`);
if (p.offset) {
lines.push(
`- offset: [${p.offset.samples.map((s) => s.toFixed(0)).join(", ")}]ms${p.offset.error ? ` (error: ${p.offset.error})` : ""}`,
);
}
if (p.cursor) {
lines.push(
`- cursor: [${p.cursor.samples.map((s) => s.toFixed(0)).join(", ")}]ms${p.cursor.error ? ` (error: ${p.cursor.error})` : ""}`,
);
}
lines.push("");
}
return lines.join("\n");
};
const redactHost = (url: string | undefined): string => {
if (!url) return "<unset>";
try {
const u = new URL(url);
return `${u.hostname}:${u.port || "5432"}`;
} catch {
return "<unparseable>";
}
};
const main = async () => {
const startedAt = performance.now();
console.log(
chalk.magentaBright(
"\n================ Pagination Benchmark — offset vs cursor (prod DB) ================\n",
),
);
const dbHost = redactHost(process.env.DATABASE_URL);
console.log(chalk.cyan(`db host: ${dbHost}`));
const { db, client } = initDrizzle();
try {
console.log(chalk.cyan("Resolving Firecrawl internal_ids for IN-list cell..."));
const firecrawlInternalIds = await resolveFirecrawlInternalIds({ db });
console.log(chalk.gray(` got ${firecrawlInternalIds.length} ids`));
const scenarios = buildScenarios({ firecrawlInternalIds });
// Resolve counts and deep cursors for each scenario before running cells.
for (const s of scenarios) {
process.stdout.write(chalk.gray(`Resolving count for ${s.key} (${s.label})... `));
const count = await resolveCount({ db, orgId: s.orgId, filter: s.filter });
(s as Scenario & { resolvedCount?: number }).resolvedCount = count;
console.log(chalk.gray(`${count.toLocaleString()} customers`));
if (s.withDeep) {
const deepOffset =
s.key === "01-baseline"
? FIRECRAWL_BASELINE_DEEP_OFFSET
: Math.floor((count * DEEP_OFFSET_PCT) / 100);
s.deepOffset = deepOffset;
process.stdout.write(
chalk.gray(` resolving deep cursor at offset ${deepOffset}... `),
);
try {
s.deepCursor = await resolveDeepCursor({
db,
orgId: s.orgId,
filter: s.filter,
deepOffset,
});
console.log(
chalk.gray(
`{ t: ${s.deepCursor.t}, id: ${s.deepCursor.id.slice(0, 8)}… }`,
),
);
} catch (err) {
console.log(
chalk.yellow(
`failed: ${err instanceof Error ? err.message : String(err)}`,
),
);
s.withDeep = false;
}
}
}
const cells = scenarios.flatMap(buildCellsForScenario);
console.log();
console.log(chalk.cyan(`Running ${cells.length} cells × ${REPEATS} repeats...`));
console.log();
const results: CellResult[] = [];
for (let i = 0; i < cells.length; i++) {
const cell = cells[i];
process.stdout.write(
chalk.gray(
`[${(i + 1).toString().padStart(2)}/${cells.length}] ${cell.scenarioKey} ${cell.queryShape} ${cell.depth} ... `,
),
);
const result = await measureCell({ db, cell });
results.push(result);
if (result.error) {
console.log(chalk.red(`error: ${result.error.slice(0, 80)}`));
} else {
console.log(
chalk.green(
`median=${result.medianMs.toFixed(0)}ms p95=${result.p95Ms.toFixed(0)}ms rows=${result.rowCount}`,
),
);
}
}
const pairs = pairResults(results);
const totalWallMs = performance.now() - startedAt;
const report = renderReport({ scenarios, pairs, totalWallMs, dbHost });
const date = new Date().toISOString().slice(0, 10);
const outPath = join(RESULTS_DIR, `${date}-offset-vs-cursor.md`);
writeFileSync(outPath, report);
console.log();
console.log(chalk.green(`✅ Report written to ${outPath}`));
console.log(
chalk.magentaBright(
`\n================ Benchmark Complete (${(totalWallMs / 1000).toFixed(1)}s) ================\n`,
),
);
} catch (error) {
console.error(chalk.red("\n❌ Benchmark failed:"));
if (error instanceof Error) {
console.error(chalk.red(` ${error.message}`));
console.error(chalk.gray(error.stack));
} else {
console.error(chalk.red(` ${String(error)}`));
}
process.exit(1);
} finally {
await client.end();
process.exit(0);
}
};
await main();

View File

@@ -1,304 +0,0 @@
import { AppEnv } from "@autumn/shared";
import chalk from "chalk";
import { sql, type SQL } from "drizzle-orm";
import { RELEVANT_STATUSES } from "../src/internal/customers/cusProducts/CusProductService";
import { initDrizzle } from "../src/db/initDrizzle";
import { loadLocalEnv } from "../src/utils/envUtils";
import { getCursorPaginatedFullCusQuery } from "../src/internal/customers/cursorPaginatedFullCusQuery";
import { getOptimizedFullCusQuery } from "./optimizedFullCusQuery";
loadLocalEnv();
const ORG_ID = "org_2sWv2S8LJ9iaTjLI6UtNsfL88Kt";
const ENV: AppEnv = AppEnv.Sandbox;
const REPEATS = 5;
const STATEMENT_TIMEOUT_MS = 60_000;
const DEEP_OFFSET_PCT = parseInt(process.env.OFFSET_PCT ?? "60", 10);
const LIMIT = parseInt(process.env.LIMIT ?? "1000", 10);
const CUS_PRODUCT_LIMIT = 15;
const SHOW_EXPLAIN = process.env.EXPLAIN !== "false";
const SKIP_CURRENT = process.env.SKIP_CURRENT === "true";
const SKIP_OPTIMIZED = process.env.SKIP_OPTIMIZED === "true";
const DASHBOARD_MODE = process.env.DASHBOARD === "true";
type DB = ReturnType<typeof initDrizzle>["db"];
const normalizeRows = (r: unknown): Record<string, unknown>[] => {
if (Array.isArray(r)) return r as Record<string, unknown>[];
if (r && typeof r === "object" && "rows" in r) {
return (r as { rows: Record<string, unknown>[] }).rows;
}
return [];
};
const runInTxn = async ({ db, query }: { db: DB; query: SQL }) => {
return db.transaction(async (tx) => {
await tx.execute(
sql.raw(`SET LOCAL statement_timeout = ${STATEMENT_TIMEOUT_MS}`),
);
await tx.execute(sql.raw("SET LOCAL transaction_read_only = on"));
return normalizeRows(await tx.execute(query));
});
};
const resolveTotalCount = async ({ db }: { db: DB }) => {
const result = await runInTxn({
db,
query: sql`
SELECT COUNT(*)::int AS total_count
FROM customers c
WHERE c.org_id = ${ORG_ID} AND c.env = ${ENV}
`,
});
return (result[0] as { total_count: number }).total_count;
};
const resolveDeepCursor = async ({
db,
offset,
}: {
db: DB;
offset: number;
}) => {
const result = await runInTxn({
db,
query: sql`
SELECT c.created_at, c.id
FROM customers c
WHERE c.org_id = ${ORG_ID} AND c.env = ${ENV}
ORDER BY c.created_at DESC, c.id DESC
LIMIT 1 OFFSET ${offset}
`,
});
const row = result[0] as { created_at: number; id: string } | undefined;
if (!row) throw new Error(`No customer at offset ${offset}`);
return { v: 0 as const, t: row.created_at, id: row.id };
};
const buildQuery = (
cursor?: { v: 0; t: number; id: string },
variant: "current" | "optimized" = "current",
internalCustomerIds?: string[],
): SQL => {
const builder =
variant === "optimized"
? getOptimizedFullCusQuery
: getCursorPaginatedFullCusQuery;
return builder({
orgId: ORG_ID,
env: ENV,
inStatuses: RELEVANT_STATUSES,
withSubs: true,
limit: internalCustomerIds?.length ?? LIMIT,
cursor,
internalCustomerIds,
cusProductLimit: CUS_PRODUCT_LIMIT,
});
};
const resolveInternalIds = async ({
db,
offset,
limit,
}: {
db: DB;
offset: number;
limit: number;
}): Promise<string[]> => {
const result = await runInTxn({
db,
query: sql`
SELECT c.internal_id
FROM customers c
WHERE c.org_id = ${ORG_ID} AND c.env = ${ENV}
ORDER BY c.created_at DESC, c.id DESC
LIMIT ${limit} OFFSET ${offset}
`,
});
return (result as unknown as { internal_id: string }[]).map(
(r) => r.internal_id,
);
};
const measureRun = async ({
db,
cursor,
label,
variant = "current",
internalCustomerIds,
}: {
db: DB;
cursor?: { v: 0; t: number; id: string };
label: string;
variant?: "current" | "optimized";
internalCustomerIds?: string[];
}) => {
const samples: number[] = [];
for (let i = 0; i < REPEATS; i++) {
const t0 = performance.now();
await runInTxn({ db, query: buildQuery(cursor, variant, internalCustomerIds) });
const ms = performance.now() - t0;
samples.push(ms);
process.stdout.write(chalk.gray(` run ${i + 1}/${REPEATS}: ${ms.toFixed(0)}ms\n`));
}
const sorted = [...samples].sort((a, b) => a - b);
const median = sorted[Math.floor(sorted.length / 2)] ?? 0;
const p95 = sorted[Math.min(sorted.length - 1, Math.floor(sorted.length * 0.95))] ?? 0;
const min = sorted[0] ?? 0;
const max = sorted[sorted.length - 1] ?? 0;
console.log(
chalk.bold(
` ${label}: median=${median.toFixed(0)}ms p95=${p95.toFixed(0)}ms min=${min.toFixed(0)}ms max=${max.toFixed(0)}ms`,
),
);
return { median, p95, min, max, samples };
};
const runExplain = async ({
db,
cursor,
variant = "current",
internalCustomerIds,
}: {
db: DB;
cursor?: { v: 0; t: number; id: string };
variant?: "current" | "optimized";
internalCustomerIds?: string[];
}) => {
const explain = await runInTxn({
db,
query: sql`EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT) ${buildQuery(cursor, variant, internalCustomerIds)}`,
});
return explain.map((r) => r["QUERY PLAN"]).join("\n");
};
const main = async () => {
console.log(
chalk.magentaBright(
`\n================ SQL Bench — unit-test-org ================\n`,
),
);
const { db, client } = initDrizzle();
try {
console.log(chalk.cyan(`Org: ${ORG_ID} Env: ${ENV} Limit: ${LIMIT}`));
console.log(chalk.cyan("Resolving total customer count..."));
const total = await resolveTotalCount({ db });
const deepOffset = Math.floor((total * DEEP_OFFSET_PCT) / 100);
console.log(
chalk.gray(
` total=${total.toLocaleString()} deep_offset(${DEEP_OFFSET_PCT}%)=${deepOffset.toLocaleString()}`,
),
);
console.log(chalk.cyan(`Resolving deep cursor at offset ${deepOffset}...`));
const deepCursor = await resolveDeepCursor({ db, offset: deepOffset });
console.log(
chalk.gray(` cursor = { t: ${deepCursor.t}, id: ${deepCursor.id} }\n`),
);
let curFirst: { median: number } | null = null;
let curDeep: { median: number } | null = null;
let optFirst: { median: number } | null = null;
let optDeep: { median: number } | null = null;
let dashIds: string[] | undefined;
if (DASHBOARD_MODE) {
const offset = Math.floor((total * DEEP_OFFSET_PCT) / 100);
console.log(
chalk.cyan(`Dashboard mode: resolving ${LIMIT} internal_ids at offset ${offset}...`),
);
dashIds = await resolveInternalIds({ db, offset, limit: LIMIT });
console.log(chalk.gray(` got ${dashIds.length} ids\n`));
}
if (!SKIP_CURRENT) {
console.log(chalk.bold("→ CURRENT first page:"));
curFirst = await measureRun({ db, label: "current first" });
console.log(chalk.bold(`→ CURRENT deep page${DASHBOARD_MODE ? " (internalCustomerIds)" : ""}:`));
curDeep = await measureRun({
db,
cursor: DASHBOARD_MODE ? undefined : deepCursor,
internalCustomerIds: DASHBOARD_MODE ? dashIds : undefined,
label: "current deep",
});
} else {
console.log(chalk.gray("(SKIP_CURRENT=true — skipping current variant)"));
}
if (!SKIP_OPTIMIZED) {
console.log();
console.log(chalk.bold("→ OPTIMIZED first page:"));
optFirst = await measureRun({
db,
label: "optim first",
variant: "optimized",
});
console.log(chalk.bold(`→ OPTIMIZED deep page${DASHBOARD_MODE ? " (internalCustomerIds)" : ""}:`));
optDeep = await measureRun({
db,
cursor: DASHBOARD_MODE ? undefined : deepCursor,
internalCustomerIds: DASHBOARD_MODE ? dashIds : undefined,
label: "optim deep",
variant: "optimized",
});
} else {
console.log(chalk.gray("(SKIP_OPTIMIZED=true — skipping optimized variant)"));
}
if (SHOW_EXPLAIN) {
if (!SKIP_CURRENT) {
console.log();
console.log(
chalk.magenta("================ EXPLAIN: CURRENT deep ================"),
);
console.log(await runExplain({ db, cursor: deepCursor }));
}
if (!SKIP_OPTIMIZED) {
console.log();
console.log(
chalk.magenta(
"================ EXPLAIN: OPTIMIZED deep ================",
),
);
console.log(
await runExplain({ db, cursor: deepCursor, variant: "optimized" }),
);
}
}
console.log();
console.log(chalk.magentaBright("================ Summary ================"));
const fmtDelta = (oldMs: number, newMs: number) => {
const delta = ((newMs - oldMs) / oldMs) * 100;
const arrow = delta < 0 ? "↓" : "↑";
return chalk[delta < 0 ? "green" : "red"](
`${arrow}${Math.abs(delta).toFixed(0)}%`,
);
};
if (curFirst && optFirst) {
console.log(
` first page current=${curFirst.median.toFixed(0)}ms optimized=${optFirst.median.toFixed(0)}ms ${fmtDelta(curFirst.median, optFirst.median)}`,
);
console.log(
` deep page current=${curDeep!.median.toFixed(0)}ms optimized=${optDeep!.median.toFixed(0)}ms ${fmtDelta(curDeep!.median, optDeep!.median)}`,
);
} else if (curFirst) {
console.log(` first page current=${curFirst.median.toFixed(0)}ms`);
console.log(` deep page current=${curDeep!.median.toFixed(0)}ms`);
} else if (optFirst) {
console.log(` first page optimized=${optFirst.median.toFixed(0)}ms`);
console.log(` deep page optimized=${optDeep!.median.toFixed(0)}ms`);
}
} catch (err) {
console.error(chalk.red(`\n❌ ${err instanceof Error ? err.message : err}`));
if (err instanceof Error && err.stack) console.error(chalk.gray(err.stack));
process.exit(1);
} finally {
await client.end();
process.exit(0);
}
};
await main();

View File

@@ -1,130 +0,0 @@
import { AppEnv } from "@autumn/shared";
import chalk from "chalk";
import { sql } from "drizzle-orm";
import { CusBatchService } from "../src/internal/customers/CusBatchService";
import { initDrizzle } from "../src/db/initDrizzle";
import { loadLocalEnv } from "../src/utils/envUtils";
loadLocalEnv();
const ORG_ID = "org_2sWv2S8LJ9iaTjLI6UtNsfL88Kt";
const ENV = AppEnv.Sandbox;
const PAGE_SIZE = parseInt(process.env.PAGE_SIZE ?? "100", 10);
const MAX_PAGES = parseInt(process.env.MAX_PAGES ?? "50", 10);
const minimalCtx = () => {
const { db, client } = initDrizzle();
return {
db,
client,
org: { id: ORG_ID, slug: "unit-test-org" },
env: ENV,
logger: {
info: () => {},
error: () => {},
warn: () => {},
debug: () => {},
trace: () => {},
},
} as any;
};
const main = async () => {
console.log(
chalk.magentaBright(
"\n================ Dashboard Cursor No-Skip Sweep ================\n",
),
);
const ctx = minimalCtx();
try {
const seen = new Set<string>();
const duplicates: string[] = [];
const order: string[] = [];
let cursor: { t: number; id: string } | null = null;
let pageNum = 0;
while (pageNum < MAX_PAGES) {
const res: { fullCustomers: any[]; next_cursor: string | null } =
await CusBatchService.getDashboardCursorPage({
ctx,
search: "",
filters: undefined,
cursor,
limit: PAGE_SIZE,
});
pageNum++;
for (const c of res.fullCustomers) {
if (seen.has(c.internal_id)) duplicates.push(c.internal_id);
seen.add(c.internal_id);
order.push(c.internal_id);
}
console.log(
chalk.gray(
` page ${pageNum.toString().padStart(3)} rows=${res.fullCustomers.length.toString().padStart(4)} total=${seen.size.toString().padStart(6)} next=${res.next_cursor ? "yes" : "no"}`,
),
);
if (!res.next_cursor) break;
const decoded = JSON.parse(
Buffer.from(res.next_cursor, "base64").toString("utf8"),
);
cursor = { t: decoded.t, id: decoded.id };
}
const expected = (
(await ctx.db.execute(
sql`
SELECT c.internal_id
FROM customers c
WHERE c.org_id = ${ORG_ID} AND c.env = ${ENV}
ORDER BY c.created_at DESC, c.id DESC
LIMIT ${pageNum * PAGE_SIZE}
`,
)) as unknown as { internal_id: string }[]
).map((r) => r.internal_id);
console.log();
console.log(
chalk.bold(
` Walked ${pageNum} pages, saw ${seen.size} unique customers (expected first ${expected.length}).`,
),
);
if (duplicates.length > 0) {
console.log(
chalk.red(`${duplicates.length} duplicates returned across pages`),
);
} else {
console.log(chalk.green(` ✓ no duplicates`));
}
const missing: string[] = [];
for (const id of expected) if (!seen.has(id)) missing.push(id);
if (missing.length > 0) {
console.log(
chalk.red(
`${missing.length} customers skipped! First 5: ${missing.slice(0, 5).join(", ")}`,
),
);
} else {
console.log(chalk.green(` ✓ no customers skipped`));
}
const sameOrder = order.every((id, i) => id === expected[i]);
console.log(
sameOrder
? chalk.green(` ✓ pagination order matches direct query`)
: chalk.yellow(` ⚠ pagination order differs from direct query`),
);
process.exit(missing.length === 0 && duplicates.length === 0 ? 0 : 1);
} finally {
await ctx.client.end();
}
};
await main();

View File

@@ -1,463 +0,0 @@
import chalk from "chalk";
import { sql, type SQL } from "drizzle-orm";
import { writeFileSync } from "node:fs";
import { join } from "node:path";
import { initDrizzle } from "../src/db/initDrizzle";
import { loadLocalEnv } from "../src/utils/envUtils";
loadLocalEnv();
const ORG_ID = "biu9vSF7vghBLSKW1UTDwxHBAivjnPaK";
const ENV = "live";
const LABEL = "firecrawl-deep";
const LIMIT = 1000;
const FETCH_LIMIT = LIMIT + 1;
const SQL_REPEATS = 1;
const REASSEMBLY_REPEATS = 20;
const STATEMENT_TIMEOUT_MS = 30_000;
const DEEP_CURSOR = {
t: 1774237983361,
id: "772c9569-fc97-4c30-9fd8-c8a585b66755",
};
const RESULTS_DIR = join(import.meta.dir, "results");
type DB = ReturnType<typeof initDrizzle>["db"];
const buildVariant07Sql = (): SQL => sql`
WITH cr AS MATERIALIZED (
SELECT
c.internal_id,
c.id,
c.created_at,
row_to_json(c) AS row_json
FROM customers c
WHERE c.org_id = ${ORG_ID}
AND c.env = ${ENV}
AND (c.created_at, c.id) < (${DEEP_CURSOR.t}, ${DEEP_CURSOR.id})
ORDER BY c.created_at DESC, c.id DESC
LIMIT ${FETCH_LIMIT}
),
cps_flat AS MATERIALIZED (
SELECT
cp.id,
cp.internal_customer_id,
cp.internal_product_id,
cp.free_trial_id,
cp.subscription_ids,
(row_to_json(cp)::jsonb || jsonb_build_object('product', row_to_json(prod)))::json AS row_json
FROM cr
JOIN LATERAL (
SELECT cp.*
FROM customer_products cp
WHERE cp.internal_customer_id = cr.internal_id
AND cp.status = ANY(ARRAY['active', 'past_due', 'scheduled'])
ORDER BY cp.created_at DESC
LIMIT 15
) cp ON true
JOIN products prod ON cp.internal_product_id = prod.internal_id
),
ces_combined AS MATERIALIZED (
SELECT 'bound'::text AS kind, ce.id, ce.entitlement_id, row_to_json(ce) AS row_json
FROM cps_flat
JOIN LATERAL (
SELECT ce.*
FROM customer_entitlements ce
WHERE ce.customer_product_id = cps_flat.id
) ce ON true
UNION ALL
SELECT 'loose'::text AS kind, ce.id, ce.entitlement_id, row_to_json(ce) AS row_json
FROM cr
JOIN LATERAL (
SELECT ce.*
FROM customer_entitlements ce
WHERE ce.internal_customer_id = cr.internal_id
AND ce.customer_product_id IS NULL
AND (ce.expires_at IS NULL OR ce.expires_at > EXTRACT(EPOCH FROM now()) * 1000)
ORDER BY ce.id DESC
LIMIT 30
) ce ON true
),
arrays AS MATERIALIZED (
SELECT
(SELECT array_agg(id) FROM ces_combined) AS all_ce_ids,
(SELECT array_agg(DISTINCT entitlement_id) FROM ces_combined) AS distinct_entitlement_ids,
(SELECT array_agg(DISTINCT free_trial_id) FILTER (WHERE free_trial_id IS NOT NULL) FROM cps_flat) AS free_trial_ids
)
SELECT
(SELECT COALESCE(json_agg(row_json), '[]'::json) FROM cr) AS customers,
(SELECT COALESCE(json_agg(row_json), '[]'::json) FROM cps_flat) AS customer_products,
(SELECT COALESCE(json_agg(row_json), '[]'::json) FROM ces_combined WHERE kind = 'bound') AS customer_entitlements,
(SELECT COALESCE(json_agg(row_json), '[]'::json) FROM ces_combined WHERE kind = 'loose') AS extra_customer_entitlements,
(SELECT COALESCE(json_agg(row_to_json(cpr)::jsonb || jsonb_build_object('price', row_to_json(p))), '[]'::json)
FROM cps_flat cps
JOIN LATERAL (SELECT cpr.* FROM customer_prices cpr WHERE cpr.customer_product_id = cps.id) cpr ON true
LEFT JOIN LATERAL (SELECT p.* FROM prices p WHERE p.id = cpr.price_id) p ON true) AS customer_prices,
(SELECT COALESCE(json_agg(row_to_json(e)::jsonb || jsonb_build_object('feature', row_to_json(f))), '[]'::json)
FROM unnest((SELECT distinct_entitlement_ids FROM arrays)) AS u(entitlement_id)
JOIN LATERAL (SELECT e.* FROM entitlements e WHERE e.id = u.entitlement_id) e ON true
JOIN LATERAL (SELECT f.* FROM features f WHERE f.internal_id = e.internal_feature_id) f ON true) AS entitlements,
(SELECT COALESCE(json_agg(row_to_json(ro)), '[]'::json)
FROM unnest((SELECT all_ce_ids FROM arrays)) AS u(ce_id)
JOIN LATERAL (SELECT ro.* FROM rollovers ro WHERE ro.cus_ent_id = u.ce_id AND (ro.expires_at IS NULL OR ro.expires_at > EXTRACT(EPOCH FROM now()) * 1000)) ro ON true) AS rollovers,
(SELECT COALESCE(json_agg(row_to_json(r)), '[]'::json)
FROM unnest((SELECT all_ce_ids FROM arrays)) AS u(ce_id)
JOIN LATERAL (SELECT r.* FROM replaceables r WHERE r.cus_ent_id = u.ce_id) r ON true) AS replaceables,
(SELECT COALESCE(json_agg(row_to_json(ft)), '[]'::json)
FROM unnest((SELECT free_trial_ids FROM arrays)) AS u(ft_id)
JOIN LATERAL (SELECT ft.* FROM free_trials ft WHERE ft.id = u.ft_id) ft ON true) AS free_trials,
(SELECT COALESCE(json_agg(row_to_json(s)), '[]'::json)
FROM (
SELECT DISTINCT s.*
FROM cps_flat cps
CROSS JOIN LATERAL unnest(cps.subscription_ids) AS sub_id_t(sub_id)
JOIN LATERAL (SELECT s.* FROM subscriptions s WHERE s.stripe_id = sub_id_t.sub_id) s ON true
WHERE cps.subscription_ids IS NOT NULL
) s) AS subscriptions
`;
type V07Row = {
customers: any[];
customer_products: any[];
customer_entitlements: any[];
extra_customer_entitlements: any[];
customer_prices: any[];
entitlements: any[];
rollovers: any[];
replaceables: any[];
free_trials: any[];
subscriptions: any[];
};
const reassemble = (flat: V07Row) => {
const {
customers,
customer_products,
customer_entitlements,
extra_customer_entitlements,
customer_prices,
entitlements,
rollovers,
replaceables,
free_trials,
subscriptions,
} = flat;
const entById = new Map<string, any>();
for (const e of entitlements) entById.set(e.id, e);
const ftById = new Map<string, any>();
for (const ft of free_trials) ftById.set(ft.id, ft);
const subByStripeId = new Map<string, any>();
for (const s of subscriptions) subByStripeId.set(s.stripe_id, s);
const rolloversByCeId = new Map<string, any[]>();
for (const ro of rollovers) {
const list = rolloversByCeId.get(ro.cus_ent_id);
if (list) list.push(ro);
else rolloversByCeId.set(ro.cus_ent_id, [ro]);
}
const replaceablesByCeId = new Map<string, any[]>();
for (const r of replaceables) {
const list = replaceablesByCeId.get(r.cus_ent_id);
if (list) list.push(r);
else replaceablesByCeId.set(r.cus_ent_id, [r]);
}
const cpricesByCpId = new Map<string, any[]>();
for (const cpr of customer_prices) {
const list = cpricesByCpId.get(cpr.customer_product_id);
if (list) list.push(cpr);
else cpricesByCpId.set(cpr.customer_product_id, [cpr]);
}
const hydrateCe = (ce: any) => ({
...ce,
entitlement: entById.get(ce.entitlement_id) ?? null,
rollovers: rolloversByCeId.get(ce.id) ?? [],
replaceables: replaceablesByCeId.get(ce.id) ?? [],
});
const cesByCpId = new Map<string, any[]>();
for (const ce of customer_entitlements) {
const hydrated = hydrateCe(ce);
const list = cesByCpId.get(ce.customer_product_id);
if (list) list.push(hydrated);
else cesByCpId.set(ce.customer_product_id, [hydrated]);
}
const looseCesByCusId = new Map<string, any[]>();
for (const ce of extra_customer_entitlements) {
const hydrated = hydrateCe(ce);
const list = looseCesByCusId.get(ce.internal_customer_id);
if (list) list.push(hydrated);
else looseCesByCusId.set(ce.internal_customer_id, [hydrated]);
}
const cpsByCusId = new Map<string, any[]>();
for (const cp of customer_products) {
const hydrated = {
...cp,
customer_prices: cpricesByCpId.get(cp.id) ?? [],
customer_entitlements: cesByCpId.get(cp.id) ?? [],
free_trial: cp.free_trial_id ? (ftById.get(cp.free_trial_id) ?? null) : null,
};
const list = cpsByCusId.get(cp.internal_customer_id);
if (list) list.push(hydrated);
else cpsByCusId.set(cp.internal_customer_id, [hydrated]);
}
const subsByCusId = new Map<string, any[]>();
for (const cp of customer_products) {
if (!cp.subscription_ids?.length) continue;
const existing = subsByCusId.get(cp.internal_customer_id) ?? [];
const seen = new Set(existing.map((s: any) => s.stripe_id));
for (const subId of cp.subscription_ids) {
if (seen.has(subId)) continue;
const sub = subByStripeId.get(subId);
if (sub) {
existing.push(sub);
seen.add(subId);
}
}
if (existing.length) subsByCusId.set(cp.internal_customer_id, existing);
}
const result: any[] = [];
for (const c of customers) {
result.push({
...c,
customer_products: cpsByCusId.get(c.internal_id) ?? [],
extra_customer_entitlements: looseCesByCusId.get(c.internal_id) ?? [],
subscriptions: subsByCusId.get(c.internal_id) ?? [],
});
}
return result;
};
const runQueryInTxn = async ({
db,
query,
}: {
db: DB;
query: SQL;
}): Promise<Record<string, unknown>[]> => {
return await db.transaction(async (tx) => {
await tx.execute(
sql.raw(`SET LOCAL statement_timeout = ${STATEMENT_TIMEOUT_MS}`),
);
await tx.execute(sql.raw("SET LOCAL transaction_read_only = on"));
const result = await tx.execute(query);
return result as unknown as Record<string, unknown>[];
});
};
const summarise = (samples: number[]) => {
const sorted = [...samples].sort((a, b) => a - b);
return {
min: sorted[0] ?? 0,
median: sorted[Math.floor(sorted.length / 2)] ?? 0,
p95: sorted[Math.min(sorted.length - 1, Math.floor(sorted.length * 0.95))] ?? 0,
max: sorted[sorted.length - 1] ?? 0,
samples: sorted,
};
};
const main = async () => {
console.log(
chalk.magentaBright(
`\n================ Variant 07 + Reassembly Benchmark — ${LABEL} ================\n`,
),
);
const { db, client } = initDrizzle();
try {
console.log(chalk.cyan(`Org: ${ORG_ID} (${ENV})`));
console.log(
chalk.cyan(
`Deep cursor: t=${DEEP_CURSOR.t} id=${DEEP_CURSOR.id} limit=${LIMIT}\n`,
),
);
// Step 1 — EXPLAIN ANALYZE pass for server-side SQL execution time
console.log(chalk.cyan("[1/3] EXPLAIN (ANALYZE, FORMAT JSON) — server-side ms"));
const explainSamples: number[] = [];
let lastExplainPlan: any = null;
for (let i = 0; i < SQL_REPEATS; i++) {
const explainRows = await runQueryInTxn({
db,
query: sql`EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) ${buildVariant07Sql()}`,
});
const plan = (explainRows[0] as { "QUERY PLAN": any })["QUERY PLAN"];
const planObj = Array.isArray(plan) ? plan[0] : plan;
const execTime = planObj["Execution Time"] as number;
explainSamples.push(execTime);
lastExplainPlan = planObj;
process.stdout.write(chalk.gray(` run ${i + 1}: ${execTime.toFixed(2)}ms\n`));
}
const sqlSummary = summarise(explainSamples);
// Step 2 — actual query to capture rows for reassembly
console.log(chalk.cyan("\n[2/3] Executing variant 07 to capture row payload"));
const queryStart = performance.now();
const rows = await runQueryInTxn({ db, query: buildVariant07Sql() });
const queryWallMs = performance.now() - queryStart;
const flatRow = rows[0] as unknown as V07Row;
const counts = {
customers: flatRow.customers?.length ?? 0,
customer_products: flatRow.customer_products?.length ?? 0,
customer_entitlements: flatRow.customer_entitlements?.length ?? 0,
extra_customer_entitlements: flatRow.extra_customer_entitlements?.length ?? 0,
customer_prices: flatRow.customer_prices?.length ?? 0,
entitlements: flatRow.entitlements?.length ?? 0,
rollovers: flatRow.rollovers?.length ?? 0,
replaceables: flatRow.replaceables?.length ?? 0,
free_trials: flatRow.free_trials?.length ?? 0,
subscriptions: flatRow.subscriptions?.length ?? 0,
};
console.log(
chalk.gray(` client-side wall (incl. UK→US network): ${queryWallMs.toFixed(2)}ms`),
);
console.log(chalk.gray(` row counts: ${JSON.stringify(counts)}`));
const payloadBytes = Buffer.byteLength(JSON.stringify(flatRow), "utf8");
console.log(
chalk.gray(` payload size: ${(payloadBytes / 1024 / 1024).toFixed(2)} MB`),
);
// Step 3 — reassembly benchmark (pure JS, in-memory)
console.log(
chalk.cyan(`\n[3/3] Reassembly benchmark — ${REASSEMBLY_REPEATS} runs`),
);
// Warm up the JIT
for (let i = 0; i < 3; i++) reassemble(flatRow);
const reassemblySamples: number[] = [];
let lastReassembledLen = 0;
for (let i = 0; i < REASSEMBLY_REPEATS; i++) {
const start = performance.now();
const reassembled = reassemble(flatRow);
const elapsed = performance.now() - start;
reassemblySamples.push(elapsed);
lastReassembledLen = reassembled.length;
}
const reassemblySummary = summarise(reassemblySamples);
console.log(
chalk.gray(
` reassembled ${lastReassembledLen} FullCustomers (${REASSEMBLY_REPEATS} runs)`,
),
);
// Report
console.log(chalk.magentaBright("\n================ RESULTS ================\n"));
console.log(chalk.bold("SQL (server-side, EXPLAIN ANALYZE Execution Time):"));
console.log(
` min=${sqlSummary.min.toFixed(2)}ms median=${sqlSummary.median.toFixed(2)}ms p95=${sqlSummary.p95.toFixed(2)}ms max=${sqlSummary.max.toFixed(2)}ms`,
);
console.log(chalk.gray(` samples: ${sqlSummary.samples.map((s) => s.toFixed(1)).join(", ")}`));
console.log();
console.log(chalk.bold("Reassembly (JS, in-memory, network-free):"));
console.log(
` min=${reassemblySummary.min.toFixed(2)}ms median=${reassemblySummary.median.toFixed(2)}ms p95=${reassemblySummary.p95.toFixed(2)}ms max=${reassemblySummary.max.toFixed(2)}ms`,
);
console.log(chalk.gray(` samples: ${reassemblySummary.samples.map((s) => s.toFixed(2)).join(", ")}`));
console.log();
console.log(chalk.bold.green("Total (network-free) median:"));
console.log(
chalk.bold.green(
` ${(sqlSummary.median + reassemblySummary.median).toFixed(2)}ms = ${sqlSummary.median.toFixed(2)}ms SQL + ${reassemblySummary.median.toFixed(2)}ms reassembly`,
),
);
console.log();
console.log(chalk.bold("Reference (UK→US client wall, includes ~100ms network):"));
console.log(` one-shot db.execute: ${queryWallMs.toFixed(2)}ms`);
console.log();
const date = new Date().toISOString().slice(0, 10);
const reportPath = join(RESULTS_DIR, `${date}-v07-reassembly-${LABEL}.md`);
const fixturePath = join(RESULTS_DIR, `${date}-v07-fixture-${LABEL}.json`);
const lines: string[] = [];
lines.push(`# Variant 07 + JS Reassembly — ${date}${LABEL}`);
lines.push("");
lines.push("## Config");
lines.push(`- org_id: \`${ORG_ID}\``);
lines.push(`- env: \`${ENV}\``);
lines.push(`- limit: ${LIMIT} (fetch ${FETCH_LIMIT})`);
lines.push(`- deep cursor: \`{ t: ${DEEP_CURSOR.t}, id: ${DEEP_CURSOR.id} }\``);
lines.push(`- SQL repeats: ${SQL_REPEATS}`);
lines.push(`- reassembly repeats: ${REASSEMBLY_REPEATS} (after 3 warmup runs)`);
lines.push("");
lines.push("## SQL (server-side, EXPLAIN ANALYZE Execution Time, network-free)");
lines.push("");
lines.push(`| min | median | p95 | max |`);
lines.push(`|---|---|---|---|`);
lines.push(
`| ${sqlSummary.min.toFixed(2)}ms | ${sqlSummary.median.toFixed(2)}ms | ${sqlSummary.p95.toFixed(2)}ms | ${sqlSummary.max.toFixed(2)}ms |`,
);
lines.push("");
lines.push(
`Samples: ${sqlSummary.samples.map((s) => `${s.toFixed(1)}ms`).join(", ")}`,
);
lines.push("");
lines.push("## Reassembly (JS, in-memory)");
lines.push("");
lines.push(`| min | median | p95 | max |`);
lines.push(`|---|---|---|---|`);
lines.push(
`| ${reassemblySummary.min.toFixed(2)}ms | ${reassemblySummary.median.toFixed(2)}ms | ${reassemblySummary.p95.toFixed(2)}ms | ${reassemblySummary.max.toFixed(2)}ms |`,
);
lines.push("");
lines.push(
`Samples: ${reassemblySummary.samples.map((s) => `${s.toFixed(2)}ms`).join(", ")}`,
);
lines.push("");
lines.push("## Total network-free");
lines.push("");
lines.push(
`**${(sqlSummary.median + reassemblySummary.median).toFixed(2)}ms** = ${sqlSummary.median.toFixed(2)}ms SQL + ${reassemblySummary.median.toFixed(2)}ms reassembly`,
);
lines.push("");
lines.push("## Row counts");
lines.push("");
lines.push("```json");
lines.push(JSON.stringify(counts, null, 2));
lines.push("```");
lines.push("");
lines.push(`Payload size: ${(payloadBytes / 1024 / 1024).toFixed(2)} MB`);
lines.push("");
lines.push("## Reference: UK→US client wall");
lines.push("");
lines.push(`One-shot \`db.execute\`: ${queryWallMs.toFixed(2)}ms`);
lines.push("");
lines.push("## Last EXPLAIN plan (JSON)");
lines.push("");
lines.push("```json");
lines.push(JSON.stringify(lastExplainPlan, null, 2));
lines.push("```");
writeFileSync(reportPath, lines.join("\n"));
writeFileSync(fixturePath, JSON.stringify(flatRow));
console.log(chalk.green(`✅ Report written to ${reportPath}`));
console.log(chalk.green(`✅ Fixture written to ${fixturePath}`));
console.log(
chalk.magentaBright(
"\n================ Benchmark Complete ================\n",
),
);
} catch (error) {
console.error(chalk.red("\n❌ Benchmark failed:"));
console.error(error);
console.error(chalk.gray(JSON.stringify(error, Object.getOwnPropertyNames(error || {}))));
process.exit(1);
} finally {
await client.end();
process.exit(0);
}
};
await main();

View File

@@ -1,547 +0,0 @@
import {
AffectedResource,
AllowanceType,
type ApiCustomerV5,
ApiVersion,
ApiVersionClass,
applyResponseVersionChanges,
AppEnv,
BillingInterval,
CollectionMethod,
type CustomerLegacyData,
CusProductStatus,
EntInterval,
FeatureType,
type FullCustomer,
type FullCustomerEntitlement,
type FullCusProduct
} from "@autumn/shared";
import chalk from "chalk";
import { getApiCustomerBase } from "../src/internal/customers/cusUtils/apiCusUtils/getApiCustomerBase";
const CUSTOMER_COUNT = 1000;
const ITERATIONS = 5;
const WARMUP_ITERATIONS = 2;
const ORG_ID = "org_bench";
const FEATURE_IDS = [
"messages",
"credits",
"users",
"projects",
"api_calls",
"storage_gb",
"connectors",
"webhooks",
"exports",
"dashboards",
];
const ADDON_FEATURE_IDS = [
"extra_messages",
"extra_credits",
"premium_support",
"sso",
"audit_log",
];
const LOOSE_FEATURE_IDS = [
"loose_a",
"loose_b",
"loose_c",
"loose_d",
"loose_e",
];
const featureFromId = (id: string) => ({
internal_id: `fe_${id}`,
org_id: ORG_ID,
created_at: 1000,
env: AppEnv.Sandbox,
id,
name: id,
type: FeatureType.Metered,
config: { usage_type: "single_use" },
display: { singular: id, plural: `${id}s` },
archived: false,
event_names: [id],
});
const allFeatures = [
...FEATURE_IDS.map(featureFromId),
...ADDON_FEATURE_IDS.map(featureFromId),
...LOOSE_FEATURE_IDS.map(featureFromId),
];
const makeEntitlement = ({
cusEntId,
productInternalId,
productCusId,
featureId,
internalCustomerId,
customerId,
}: {
cusEntId: string;
productInternalId: string;
productCusId: string | null;
featureId: string;
internalCustomerId: string;
customerId: string;
}): FullCustomerEntitlement => ({
id: cusEntId,
internal_customer_id: internalCustomerId,
internal_entity_id: null,
internal_feature_id: `fe_${featureId}`,
customer_id: customerId,
feature_id: featureId,
customer_product_id: productCusId,
entitlement_id: `ent_${featureId}_${productInternalId}`,
created_at: 1000,
unlimited: false,
balance: 100,
additional_balance: 0,
usage_allowed: null,
next_reset_at: 2000,
adjustment: 0,
expires_at: null,
cache_version: 0,
entities: null,
external_id: null,
entitlement: {
id: `ent_${featureId}_${productInternalId}`,
created_at: 1000,
internal_feature_id: `fe_${featureId}`,
internal_product_id: productInternalId,
is_custom: false,
allowance_type: AllowanceType.Fixed,
allowance: 100,
interval: EntInterval.Month,
interval_count: 1,
entity_feature_id: null,
feature_id: featureId,
usage_limit: null,
feature: featureFromId(featureId),
},
replaceables: [],
rollovers: [],
});
const makeCusProduct = ({
productCusId,
productInternalId,
productId,
productName,
isAddOn,
internalCustomerId,
customerId,
featureIds,
cusEntPrefix,
internalEntityId,
entityId,
}: {
productCusId: string;
productInternalId: string;
productId: string;
productName: string;
isAddOn: boolean;
internalCustomerId: string;
customerId: string;
featureIds: string[];
cusEntPrefix: string;
internalEntityId?: string | null;
entityId?: string | null;
}): FullCusProduct => ({
id: productCusId,
internal_product_id: productInternalId,
product_id: productId,
internal_customer_id: internalCustomerId,
customer_id: customerId,
internal_entity_id: internalEntityId ?? null,
entity_id: entityId ?? null,
created_at: 1500,
updated_at: null,
status: CusProductStatus.Active,
canceled: false,
starts_at: 1500,
access_starts_at: null,
trial_ends_at: null,
billing_cycle_anchor_resets_at: null,
canceled_at: null,
ended_at: null,
options: [],
free_trial_id: null,
collection_method: CollectionMethod.ChargeAutomatically,
subscription_ids: [`sub_${productCusId}`],
scheduled_ids: [],
processor: { type: "stripe" as any },
quantity: 1,
api_semver: null,
is_custom: false,
billing_version: "v2" as any,
external_id: null,
stripe_checkout_session_id: null,
customer_prices: [
{
id: `cus_price_${productCusId}`,
internal_customer_id: internalCustomerId,
customer_product_id: productCusId,
created_at: 1500,
price_id: `price_${productInternalId}`,
price: {
id: `price_${productInternalId}`,
internal_product_id: productInternalId,
org_id: ORG_ID,
created_at: 1500,
billing_type: null,
tier_behavior: null,
is_custom: false,
config: {
type: "fixed",
amount: 99,
interval: BillingInterval.Month,
} as any,
entitlement_id: null,
proration_config: null,
},
},
],
customer_entitlements: featureIds.map((fid, i) =>
makeEntitlement({
cusEntId: `${cusEntPrefix}_${i}`,
productInternalId,
productCusId,
featureId: fid,
internalCustomerId,
customerId,
}),
),
product: {
id: productId,
name: productName,
description: null,
is_add_on: isAddOn,
is_default: false,
version: 1,
group: "",
env: AppEnv.Sandbox,
internal_id: productInternalId,
org_id: ORG_ID,
created_at: 1000,
processor: { type: "stripe", id: `prod_${productId}` },
base_variant_id: null,
archived: false,
config: { ignore_past_due: false },
},
free_trial: null,
});
const makeFullCustomer = (idx: number): FullCustomer => {
const internalId = `cus_bench_${idx.toString().padStart(8, "0")}`;
const customerId = `bench_${idx}`;
const customerProducts: FullCusProduct[] = [
makeCusProduct({
productCusId: `cus_prod_main_${idx}`,
productInternalId: "prod_main",
productId: "pro",
productName: "Pro",
isAddOn: false,
internalCustomerId: internalId,
customerId,
featureIds: FEATURE_IDS,
cusEntPrefix: `cus_ent_main_${idx}`,
}),
makeCusProduct({
productCusId: `cus_prod_addon_${idx}`,
productInternalId: "prod_addon",
productId: "pro_addon",
productName: "Pro Add-on",
isAddOn: true,
internalCustomerId: internalId,
customerId,
featureIds: ADDON_FEATURE_IDS,
cusEntPrefix: `cus_ent_addon_${idx}`,
}),
];
const entities = Array.from({ length: 5 }, (_, i) => ({
id: `ent_${idx}_${i}`,
org_id: ORG_ID,
created_at: 1100,
internal_id: `ent_int_${idx}_${i}`,
internal_customer_id: internalId,
env: AppEnv.Sandbox,
name: `Entity ${i}`,
deleted: false,
feature_id: "seats",
internal_feature_id: "fe_seats",
}));
for (let i = 0; i < 3; i++) {
const ent = entities[i]!;
customerProducts.push(
makeCusProduct({
productCusId: `cus_prod_main_${idx}_e${i}`,
productInternalId: "prod_main",
productId: "pro",
productName: "Pro (Entity-scoped)",
isAddOn: false,
internalCustomerId: internalId,
customerId,
featureIds: FEATURE_IDS,
cusEntPrefix: `cus_ent_main_${idx}_e${i}`,
internalEntityId: ent.internal_id,
entityId: ent.id,
}),
);
}
const looseEnts: FullCustomerEntitlement[] = LOOSE_FEATURE_IDS.map((fid, i) =>
makeEntitlement({
cusEntId: `cus_ent_loose_${idx}_${i}`,
productInternalId: "prod_loose",
productCusId: null,
featureId: fid,
internalCustomerId: internalId,
customerId,
}),
);
return {
id: customerId,
name: `Bench Customer ${idx}`,
email: `bench+${idx}@autumn.dev`,
fingerprint: null,
internal_id: internalId,
org_id: ORG_ID,
created_at: 1000,
env: AppEnv.Sandbox,
processor: { id: `cus_stripe_${idx}`, type: "stripe" },
processors: null,
metadata: {},
send_email_receipts: false,
auto_topups: null,
spend_limits: null,
usage_alerts: null,
overage_allowed: null,
config: null,
customer_products: customerProducts,
entities,
extra_customer_entitlements: looseEnts,
subscriptions: customerProducts
.filter((cp) => cp.subscription_ids?.length)
.flatMap((cp) =>
(cp.subscription_ids ?? []).map((sid) => ({
id: sid,
stripe_id: sid,
stripe_schedule_id: null,
created_at: 1500,
usage_features: [],
metadata: {},
org_id: ORG_ID,
env: AppEnv.Sandbox,
current_period_start: 1500,
current_period_end: 4000,
})),
),
} as unknown as FullCustomer;
};
const makeCtx = () =>
({
org: {
id: ORG_ID,
slug: "bench",
created_at: 1000,
default_currency: "usd",
config: { in_statuses: [CusProductStatus.Active] },
stripe_connected: false,
},
env: AppEnv.Sandbox,
features: allFeatures,
logger: {
info: () => {},
error: () => {},
warn: () => {},
debug: () => {},
trace: () => {},
child: () => makeCtx().logger,
},
expand: [],
apiVersion: new ApiVersionClass(ApiVersion.V2_3),
}) as any;
const summarize = (samples: number[]) => {
const sorted = [...samples].sort((a, b) => a - b);
return {
min: sorted[0] ?? 0,
p50: sorted[Math.floor(sorted.length / 2)] ?? 0,
p95: sorted[Math.min(sorted.length - 1, Math.floor(sorted.length * 0.95))] ?? 0,
max: sorted[sorted.length - 1] ?? 0,
mean: samples.reduce((a, b) => a + b, 0) / samples.length,
};
};
const fmt = (n: number) => `${n.toFixed(2)}ms`.padStart(9, " ");
const runSerial = async (customers: FullCustomer[], ctx: any) => {
const finals: ApiCustomerV5[] = [];
for (const fullCus of customers) {
const { apiCustomer: baseCustomer, legacyData } = await getApiCustomerBase({
ctx,
fullCus,
withAutumnId: false,
});
const versioned = applyResponseVersionChanges<ApiCustomerV5, CustomerLegacyData>({
input: baseCustomer,
legacyData,
targetVersion: ctx.apiVersion,
resource: AffectedResource.Customer,
ctx,
});
finals.push(versioned);
}
return finals;
};
const runPromiseAll = async (customers: FullCustomer[], ctx: any) => {
const finals = await Promise.all(
customers.map(async (fullCus) => {
const { apiCustomer: baseCustomer, legacyData } = await getApiCustomerBase({
ctx,
fullCus,
withAutumnId: false,
});
return applyResponseVersionChanges<ApiCustomerV5, CustomerLegacyData>({
input: baseCustomer,
legacyData,
targetVersion: ctx.apiVersion,
resource: AffectedResource.Customer,
ctx,
});
}),
);
return finals;
};
// "sync-equivalent" path: keeps the async function calls but uses a tight
// promise-chained sequence with no extra microtask churn between customers.
// Since getApiCustomerBase is async, true sync isn't possible without rewriting it.
const runSyncEquivalent = (customers: FullCustomer[], ctx: any) => {
let p: Promise<ApiCustomerV5[]> = Promise.resolve([] as ApiCustomerV5[]);
for (const fullCus of customers) {
p = p.then(async (acc) => {
const { apiCustomer: baseCustomer, legacyData } = await getApiCustomerBase({
ctx,
fullCus,
withAutumnId: false,
});
const versioned = applyResponseVersionChanges<ApiCustomerV5, CustomerLegacyData>({
input: baseCustomer,
legacyData,
targetVersion: ctx.apiVersion,
resource: AffectedResource.Customer,
ctx,
});
acc.push(versioned);
return acc;
});
}
return p;
};
const benchVariant = async ({
name,
customers,
ctx,
run,
}: {
name: string;
customers: FullCustomer[];
ctx: any;
run: (customers: FullCustomer[], ctx: any) => Promise<ApiCustomerV5[]>;
}) => {
for (let i = 0; i < WARMUP_ITERATIONS; i++) await run(customers, ctx);
const samples: number[] = [];
for (let i = 0; i < ITERATIONS; i++) {
const t0 = performance.now();
const result = await run(customers, ctx);
const t1 = performance.now();
if (result.length !== customers.length) {
throw new Error(`${name}: result length mismatch ${result.length} vs ${customers.length}`);
}
samples.push(t1 - t0);
}
const s = summarize(samples);
const perCustomer = s.p50 / customers.length;
console.log(
` ${chalk.cyan(name.padEnd(20))} | total p50 ${fmt(s.p50)} (per cus ${perCustomer.toFixed(3)}ms) | mean ${fmt(s.mean)} | p95 ${fmt(s.p95)} | min ${fmt(s.min)} | max ${fmt(s.max)}`,
);
return s;
};
const main = async () => {
console.log(
chalk.magentaBright(
`\n================ Version Pipeline Bench ================`,
),
);
console.log(
chalk.gray(
` customers per iter: ${CUSTOMER_COUNT.toLocaleString()}, iterations: ${ITERATIONS} (+${WARMUP_ITERATIONS} warmup)\n`,
),
);
const ctx = makeCtx();
const customers = Array.from({ length: CUSTOMER_COUNT }, (_, i) =>
makeFullCustomer(i),
);
console.log(
chalk.gray(
` shape per customer: ${customers[0]!.customer_products.length} cps · ${customers[0]!.customer_products.reduce((n, cp) => n + cp.customer_entitlements.length, 0)} bound ces · ${customers[0]!.extra_customer_entitlements.length} loose ces · ${customers[0]!.entities.length} entities`,
),
);
console.log();
console.log(chalk.bold("Baseline (serial for-await):"));
const serial = await benchVariant({ name: "serial", customers, ctx, run: runSerial });
console.log();
console.log(chalk.bold("Variant A (Promise.all):"));
const promiseAll = await benchVariant({
name: "Promise.all",
customers,
ctx,
run: runPromiseAll,
});
console.log();
console.log(chalk.bold("Variant B (sync-equivalent promise chain):"));
const syncish = await benchVariant({
name: "sync-equivalent",
customers,
ctx,
run: runSyncEquivalent,
});
const fmtDelta = (other: number, baseline: number) => {
const delta = ((other - baseline) / baseline) * 100;
const arrow = delta < 0 ? "↓" : "↑";
return `${arrow}${Math.abs(delta).toFixed(1)}%`;
};
console.log();
console.log(chalk.magentaBright("================ Summary ================"));
console.log(
` serial: ${fmt(serial.p50)} ${chalk.gray("(baseline)")}`,
);
console.log(
` Promise.all: ${fmt(promiseAll.p50)} (${fmtDelta(promiseAll.p50, serial.p50)})`,
);
console.log(
` sync-equivalent: ${fmt(syncish.p50)} (${fmtDelta(syncish.p50, serial.p50)})`,
);
};
await main();
process.exit(0);