Skip to content

Commit 9a362cc

Browse files
committed
fix(profile): fix alias pattern and schema repair robustness
- Remove trailing \d* from ALIAS_PATTERN since disambiguateSegments uses 'x' prefix, not numeric suffix. This prevents misclassifying inputs like 'process2' as aliases. - Separate index creation from table DDL in repairMissingTables so a failed index doesn't prevent subsequent repair passes from creating it (table exists check was skipping the index).
1 parent 043a7af commit 9a362cc

File tree

2 files changed

+34
-20
lines changed

2 files changed

+34
-20
lines changed

src/lib/db/schema.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -398,23 +398,43 @@ export type RepairResult = {
398398
failed: string[];
399399
};
400400

401+
/** Index for efficient alias lookups by alias string + fingerprint */
402+
const TRANSACTION_ALIASES_INDEX = `
403+
CREATE INDEX IF NOT EXISTS idx_txn_alias_lookup
404+
ON transaction_aliases(alias, fingerprint)
405+
`;
406+
401407
function repairMissingTables(db: Database, result: RepairResult): void {
402408
for (const [tableName, ddl] of Object.entries(EXPECTED_TABLES)) {
403409
if (tableExists(db, tableName)) {
404410
continue;
405411
}
406412
try {
407413
db.exec(ddl);
408-
// Create associated indexes for tables that need them
409-
if (tableName === "transaction_aliases") {
410-
db.exec(TRANSACTION_ALIASES_INDEX);
411-
}
412414
result.fixed.push(`Created table ${tableName}`);
413415
} catch (e) {
414416
const msg = e instanceof Error ? e.message : String(e);
415417
result.failed.push(`Failed to create table ${tableName}: ${msg}`);
416418
}
417419
}
420+
// Create indexes for newly created tables (separate pass to avoid
421+
// leaving the index uncreated if the table DDL succeeds but the
422+
// index fails in the same try/catch)
423+
ensureTableIndexes(db, result);
424+
}
425+
426+
/** Ensure indexes exist for tables that need them */
427+
function ensureTableIndexes(db: Database, result: RepairResult): void {
428+
if (tableExists(db, "transaction_aliases")) {
429+
try {
430+
db.exec(TRANSACTION_ALIASES_INDEX);
431+
} catch (e) {
432+
const msg = e instanceof Error ? e.message : String(e);
433+
result.failed.push(
434+
`Failed to create index for transaction_aliases: ${msg}`
435+
);
436+
}
437+
}
418438
}
419439

420440
function repairMissingColumns(db: Database, result: RepairResult): void {
@@ -569,12 +589,6 @@ export function tryRepairAndRetry<T>(
569589
return { attempted: false };
570590
}
571591

572-
/** Index for efficient alias lookups by alias string + fingerprint */
573-
const TRANSACTION_ALIASES_INDEX = `
574-
CREATE INDEX IF NOT EXISTS idx_txn_alias_lookup
575-
ON transaction_aliases(alias, fingerprint)
576-
`;
577-
578592
export function initSchema(db: Database): void {
579593
const ddlStatements = Object.values(EXPECTED_TABLES).join(";\n\n");
580594
db.exec(ddlStatements);

src/lib/resolve-transaction.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,25 +48,25 @@ const MAX_ALIAS_LENGTH = 20;
4848

4949
/**
5050
* Pattern matching alias-shaped input: purely ASCII letters in a single case
51-
* (all lowercase or all uppercase for caps-lock tolerance), optionally
52-
* followed by a numeric disambiguator (e.g. "issues2", "ISSUES2").
51+
* (all lowercase or all uppercase for caps-lock tolerance).
5352
*
5453
* This mirrors how `buildTransactionAliases` generates aliases:
5554
* segments are lowercased, stripped of hyphens/underscores, then
56-
* `findShortestUniquePrefixes` produces a lowercase-letter prefix,
57-
* and `disambiguateSegments` may append a numeric suffix.
55+
* `findShortestUniquePrefixes` produces a lowercase-letter prefix.
56+
* `disambiguateSegments` prepends "x" characters for duplicates
57+
* (e.g. "xissues", "xxissues"), so aliases are always purely alphabetic.
5858
*
5959
* Mixed-case inputs like "ProcessEvent" are treated as full transaction
6060
* names since aliases are always lowercase (or all-caps with caps lock).
6161
*/
62-
const ALIAS_PATTERN = /^(?:[a-z]+|[A-Z]+)\d*$/;
62+
const ALIAS_PATTERN = /^(?:[a-z]+|[A-Z]+)$/;
6363

6464
/**
6565
* Check if input looks like a cached alias rather than a full transaction name.
6666
*
67-
* Aliases are short, single-case letter strings (with optional numeric suffix).
68-
* Anything containing special characters like `/`, `.`, `-`, `_`, spaces,
69-
* colons, or mixed-case letters is treated as a full transaction name.
67+
* Aliases are short, purely alphabetic, single-case strings.
68+
* Anything containing digits, special characters like `/`, `.`, `-`, `_`,
69+
* spaces, colons, or mixed-case letters is treated as a full transaction name.
7070
*/
7171
function isAliasLike(input: string): boolean {
7272
return input.length <= MAX_ALIAS_LENGTH && ALIAS_PATTERN.test(input);
@@ -147,8 +147,8 @@ function buildUnknownRefError(
147147
*
148148
* Resolution order:
149149
* 1. Numeric index: "1", "2", "10" → looks up by cached index
150-
* 2. Alias-shaped input (single-case letters + optional digits, ≤20 chars):
151-
* "i", "e", "iu", "issues2", "I" (caps lock) → looks up by cached alias
150+
* 2. Alias-shaped input (single-case letters only, ≤20 chars):
151+
* "i", "e", "iu", "xissues", "I" (caps lock) → looks up by cached alias
152152
* 3. Everything else is treated as a full transaction name and passed through:
153153
* "/api/0/...", "tasks.process", "process_request", "handle-webhook",
154154
* "ProcessEvent", "GET /users"

0 commit comments

Comments
 (0)