MCPcopy Create free account
hub / github.com/DeusData/codebase-memory-mcp / index_run_supervised

Function index_run_supervised

src/mcp/mcp.c:3645–3815  ·  view source on GitHub ↗

Run index_repository in a supervised worker subprocess with skip-and-continue * (Stage 3c). Returns the response string (caller frees): * - the worker's own response on a clean first run (the common path); * - after a crash/hang, the response from a clean single-threaded RECOVERY run * that quarantines the culprit file(s) — status="indexed" with them listed in * skipped[] as phase

Source from the content-addressed store, hash-verified

3643 * Returns NULL only when the worker could not be spawned at all, so the caller
3644 * degrades to the in-process path. */
3645static char *index_run_supervised(cbm_mcp_server_t *srv, const char *args) {
3646 supervisor_invalidate_store(srv);
3647
3648 /* First attempt: normal parallel run. */
3649 cbm_index_worker_result_t wr;
3650 int rc = cbm_index_spawn_worker(args, false, NULL, NULL, &wr);
3651
3652 if (rc != 0 || wr.outcome == CBM_PROC_SPAWN_FAILED) {
3653 cbm_index_worker_result_free(&wr);
3654 supervisor_invalidate_store(srv);
3655 return NULL; /* degrade to in-process */
3656 }
3657 if (wr.outcome == CBM_PROC_CLEAN) {
3658 /* Clean exit → transfer the worker's response (the common path). If the
3659 * worker exited clean but wrote no response (a degenerate case, e.g. a
3660 * self binary that does not act as an index worker), resp is NULL and the
3661 * caller degrades to the in-process path — a clean run never needs the
3662 * crash-recovery loop. */
3663 char *resp = wr.response; /* transfer ownership to caller (may be NULL) */
3664 wr.response = NULL;
3665 cbm_index_worker_result_free(&wr);
3666 supervisor_invalidate_store(srv);
3667 return resp;
3668 }
3669
3670 /* Crash / hang / nonzero exit → skip-and-continue recovery. Re-run the
3671 * worker PARALLEL (there are no sequential production runs) with the
3672 * per-file marker JOURNAL armed; after each failed run the journal's
3673 * open-S set is the in-flight SUSPECT set. A file is quarantined only
3674 * when it appears in the suspect sets of TWO CONSECUTIVE failed runs
3675 * (intersection — a stale or merely unlucky in-flight file rotates out),
3676 * and only ONE file per round: the OLDEST open S in the intersection
3677 * (for a hang the oldest still-open file IS the stuck one; for a crash
3678 * it is the longest-running suspect — the best single deterministic
3679 * pick). A clean run then indexes the good files and reports the
3680 * quarantined ones as phase="crash"/"hang" skips via the ordinary
3681 * Stage-2 skip plumbing. The old design re-ran SINGLE-THREADED to keep
3682 * one exact marker; at scale that fell into the sequential crawl, went
3683 * quiet, was killed as a hang mid-pass, and the stale marker got FOUR
3684 * innocent ms-typescript fixtures quarantined one 15-minute retry at a
3685 * time. */
3686 cbm_proc_outcome_t last_outcome = wr.outcome;
3687 cbm_index_worker_result_free(&wr);
3688
3689 char marker_path[CBM_SZ_1K];
3690 char quarantine_path[CBM_SZ_1K];
3691 supervisor_tmp_path(marker_path, sizeof(marker_path), ".marker");
3692 supervisor_tmp_path(quarantine_path, sizeof(quarantine_path), ".quarantine");
3693 (void)remove(marker_path);
3694 /* Start the quarantine list empty (truncate any stale file). */
3695 FILE *qinit = cbm_fopen(quarantine_path, "wb");
3696 if (qinit) {
3697 (void)fclose(qinit);
3698 }
3699
3700 int cap = 100;
3701 const char *cap_env = getenv("CBM_INDEX_MAX_RESTARTS");
3702 if (cap_env && cap_env[0]) {

Callers 2

handle_index_repositoryFunction · 0.85

Calls 11

cbm_index_spawn_workerFunction · 0.85
supervisor_tmp_pathFunction · 0.85
cbm_fopenFunction · 0.85
supervisor_read_suspectsFunction · 0.85
supervisor_free_suspectsFunction · 0.85
cbm_proc_outcome_strFunction · 0.85

Tested by

no test coverage detected