Skip to content

Commit 761beda

Browse files
authored
Show per-fund updater progress (#5)
Co-authored-by: daggerok <daggerok@users.noreply.github.com>
1 parent 610db22 commit 761beda

2 files changed

Lines changed: 19 additions & 7 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ Each fund carries a `metrics` object and detailed `meta.json` that power the sha
9595

9696
### Full passes and resuming bounded runs
9797

98-
Running the updater without filters refreshes all catalog rows in alphabetical ticker order and resets the saved cursor after a full pass. A positive `MAX_FETCHES` is a resumable batch, not a permanent first-page limit: repeated runs continue after the committed cursor and wrap around the catalog. A filter run publishes only the eligible result set; an unfiltered run preserves prior rows for a fund that fails transiently.
98+
Running the updater without filters refreshes all catalog rows in alphabetical ticker order and resets the saved cursor after a full pass. A positive `MAX_FETCHES` is a resumable batch, not a permanent first-page limit: repeated runs continue after the committed cursor and wrap around the catalog. A filter run publishes only the eligible result set; an unfiltered run preserves prior rows for a fund that fails transiently. During every run, the updater prints one `[progress] n/total TICKER updated` or `[progress] n/total TICKER not updated` line as each fund finishes.
9999

100100
All range variables use `min:max`; both bounds are inclusive and optional, but the colon is required (`15:`, `:0.5`, `0.1:0.5`, `:`). AUM presets use the same sibling convention: nano (< $10M), micro ($10M–$300M), small ($300M–$2B), mid ($2B–$10B), large (>$10B).
101101

‎scripts/update-data.ts‎

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,8 +1109,7 @@ function matchesReturnFilters(metrics: JsonRecord, config: UpdaterConfig): strin
11091109
async function processFund(fund: CatalogFund, config: UpdaterConfig, previous: JsonRecord = {}): Promise<JsonRecord> {
11101110
const reasons = catalogFilterReasons(fund, config);
11111111
if (reasons.length) {
1112-
console.log(`[${fund.ticker.padEnd(5)}] skipped (${reasons.join(', ')})`);
1113-
return { __skipped: true, ticker: fund.ticker };
1112+
return { __skipped: true, ticker: fund.ticker, __skipReasons: reasons };
11141113
}
11151114
const fundDir = new URL(`funds/${fund.ticker}/`, API_ROOT);
11161115
await mkdir(fundDir, { recursive: true });
@@ -1213,8 +1212,7 @@ async function processFund(fund: CatalogFund, config: UpdaterConfig, previous: J
12131212
}
12141213
const returnFilterReasons = matchesReturnFilters(metrics, config);
12151214
if (returnFilterReasons.length) {
1216-
console.log(`[${fund.ticker.padEnd(5)}] skipped (${returnFilterReasons.join(', ')})`);
1217-
return { __skipped: true, ticker: fund.ticker };
1215+
return { __skipped: true, ticker: fund.ticker, __skipReasons: returnFilterReasons };
12181216
}
12191217

12201218
const history = historyRows(days);
@@ -1401,10 +1399,17 @@ async function main(): Promise<void> {
14011399
const index = cursor ? universe.findIndex((fund) => fund.ticker === cursor) : -1;
14021400
const ordered = index >= 0 ? universe.slice(index + 1).concat(universe.slice(0, index + 1)) : universe;
14031401
const queue = ordered.slice();
1402+
const totalAttempts = config.maxFetches > 0 ? Math.min(config.maxFetches, ordered.length) : ordered.length;
14041403
const results: JsonRecord[] = [];
14051404
let processed = 0;
1405+
let completed = 0;
14061406
let failures = 0;
14071407
let lastTicker: string | null = cursor || null;
1408+
const logProgress = (fund: CatalogFund, status: 'updated' | 'not updated', detail: string): void => {
1409+
completed += 1;
1410+
const ordinal = String(completed).padStart(String(Math.max(1, totalAttempts)).length, ' ');
1411+
console.log(`[progress] ${ordinal}/${totalAttempts} ${fund.ticker.padEnd(5)} ${status}${detail ? ` — ${detail}` : ''}`);
1412+
};
14081413
const worker = async (): Promise<void> => {
14091414
for (;;) {
14101415
if (config.maxFetches > 0 && processed >= config.maxFetches) return;
@@ -1413,12 +1418,19 @@ async function main(): Promise<void> {
14131418
processed += 1;
14141419
try {
14151420
const row = await processFund(fund, config, previous.get(fund.ticker) || {});
1416-
if (!row.__skipped) { results.push(row); lastTicker = fund.ticker; }
1421+
if (row.__skipped) {
1422+
logProgress(fund, 'not updated', `filtered: ${(row.__skipReasons || ['not eligible']).join(', ')}`);
1423+
} else {
1424+
results.push(row);
1425+
lastTicker = fund.ticker;
1426+
logProgress(fund, 'updated', `${row.holdings ?? 0} holdings, ${row.history ?? 0} history rows`);
1427+
}
14171428
} catch (error) {
14181429
failures += 1;
1419-
console.warn(`[error ] ${fund.ticker}: ${error instanceof Error ? error.message : String(error)}`);
1430+
const message = error instanceof Error ? error.message : String(error);
14201431
const old = previous.get(fund.ticker);
14211432
if (old && !hasConfiguredFilters(config)) results.push(old);
1433+
logProgress(fund, 'not updated', `error: ${message}`);
14221434
}
14231435
}
14241436
};

0 commit comments

Comments
 (0)