mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-22 10:06:42 +02:00
chore(articles): hygiene pass — shared-ai actor + lib/sync-db + metrics (#5,#7,#11)
#5 — SYSTEM_ARTICLES_IMPORT_WORKER hoisted into @mana/shared-ai The worker built its actor inline, bypassing the SystemSource union that's the blessed list for system-write principals. Now uses makeSystemActor(SYSTEM_ARTICLES_IMPORT_WORKER) like every other server-side system writer (mission-runner, projection, …). #7 — sync-db helper hoisted out of mcp/ into lib/ Implementation moved to apps/api/src/lib/sync-db.ts; mcp/sync-db.ts is a re-export shim so existing MCP imports keep working. Articles bulk-import + future modules import from lib/ directly — no more "articles depending on mcp" layering smell. #11 — Prometheus metrics for the worker New counters + histogram in lib/metrics.ts under mana_api_articles_import_*: - ticks_total{result=processed|skipped|error} - items_total{result=extracted|error|consent_wall|cancelled} - extract_duration_seconds (histogram, 0.25–30s buckets) - jobs_completed_total{result=done} - pickup_gc_rows_total Worker tick + extractor instrumented at the right transition points. Steady-state pickup_gc_rows_total > 0 over time signals a stuck consumer somewhere — useful operator alert. Plan: docs/plans/articles-bulk-import.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
93545f8516
commit
59373c0d57
8 changed files with 245 additions and 122 deletions
|
|
@ -22,7 +22,12 @@
|
|||
* Plan: docs/plans/articles-bulk-import.md.
|
||||
*/
|
||||
|
||||
import { getSyncConnection } from '../../mcp/sync-db';
|
||||
import { getSyncConnection } from '../../lib/sync-db';
|
||||
import {
|
||||
articlesImportJobsCompletedTotal,
|
||||
articlesImportPickupGcRows,
|
||||
articlesImportTicksTotal,
|
||||
} from '../../lib/metrics';
|
||||
import {
|
||||
listClaimableJobs,
|
||||
listItemsForJob,
|
||||
|
|
@ -94,8 +99,13 @@ async function runTickGuarded(): Promise<void> {
|
|||
if (running) return;
|
||||
running = true;
|
||||
try {
|
||||
await runTickOnce();
|
||||
const result = await runTickOnce();
|
||||
articlesImportTicksTotal.inc({ result: result.skipped ? 'skipped' : 'processed' });
|
||||
if (typeof result.pickupGcRows === 'number' && result.pickupGcRows > 0) {
|
||||
articlesImportPickupGcRows.inc(result.pickupGcRows);
|
||||
}
|
||||
} catch (err) {
|
||||
articlesImportTicksTotal.inc({ result: 'error' });
|
||||
console.error('[articles-import] tick error:', err);
|
||||
} finally {
|
||||
running = false;
|
||||
|
|
@ -229,6 +239,7 @@ async function processOneJob(job: ImportJobRow): Promise<number> {
|
|||
counterPatch.status = 'done';
|
||||
counterPatch.finishedAt = new Date().toISOString();
|
||||
dirty = true;
|
||||
articlesImportJobsCompletedTotal.inc({ result: 'done' });
|
||||
}
|
||||
if (dirty) {
|
||||
await writeJobUpdate(job.userId, job.id, counterPatch);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue