mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-07 08:43:35 +08:00
fix(graph-buffer): log why an atomic publish failed instead of a successful dump
cbm_gbuf_dump_to_sqlite() emitted gbuf.dump regardless of the writer's result, so a run that published nothing still logged node and edge counts as if it had worked, and the failure reached the user only as the generic "Pipeline failed. Check repo_path exists and contains source files." The writer's temp -> final rename in publish_writer_output() returned a bare ERR_WRITE_FAILED. #1628 taught cbm_rename_replace() to translate the platform error into errno so callers could report why, and wired up the stage -> final rename in pipeline.c. This is the other rename on that path, and it is the one that runs first. Preserve errno across the cleanup in every publish error branch. That includes cbm_writer_open(), where the cleanup unlinks a file that was never created: without the save it leaves ENOENT behind, so a directory that denied the create is reported as a missing path — the #1620 case, stated wrongly. Read the value in graph_buffer.c before the profiling macro can clobber it, and report gbuf.dump_failed with the return code and that errno. A sticky append failure clears errno rather than attach a reason it does not have, and the field is omitted when there is none. No logging is added inside internal/cbm/, which has none today. Tests cover both halves: the dump reports a failure instead of a summary, the writer names its truncation reason, and the publish rename's errno survives a cleanup that itself fails. Refs #1620, #2001. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012FxkVF773gDGNmBmsLnzN7 Signed-off-by: juan Carlos Estrada Montoya <junk151516@users.noreply.github.com>
This commit is contained in:
committed by
Martin Vogel
co-authored by
Claude Opus 5
parent
92abefa3f5
commit
460ebefc87
@@ -39,6 +39,7 @@ enum {
|
||||
#include "foundation/mem_core.h"
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h> // int64_t
|
||||
#include <stdio.h>
|
||||
@@ -1841,6 +1842,32 @@ static void log_dump_summary(int node_count, int edge_count) {
|
||||
cbm_log_info("gbuf.dump", "nodes", b1, "edges", b2);
|
||||
}
|
||||
|
||||
/* A dump that published nothing gets exactly one signature in the log.
|
||||
* Without it the writer's return code is the only evidence, and it reaches
|
||||
* the user as a generic pipeline failure that blames their repository
|
||||
* (#1620, #2001).
|
||||
*
|
||||
* failure_errno is read by the caller at the point of failure: the value is
|
||||
* only meaningful before the next library call. Zero means the failure did
|
||||
* not originate at the publish boundary — an append that failed many calls
|
||||
* earlier — and the field is omitted rather than claim a reason this record
|
||||
* does not have. */
|
||||
static void log_dump_failed(int rc, int failure_errno, int node_count, int edge_count) {
|
||||
char b1[CBM_SZ_16];
|
||||
char b3[CBM_SZ_16];
|
||||
char b4[CBM_SZ_16];
|
||||
snprintf(b1, sizeof(b1), "%d", rc);
|
||||
snprintf(b3, sizeof(b3), "%d", node_count);
|
||||
snprintf(b4, sizeof(b4), "%d", edge_count);
|
||||
if (failure_errno == 0) {
|
||||
cbm_log_error("gbuf.dump_failed", "rc", b1, "nodes", b3, "edges", b4);
|
||||
return;
|
||||
}
|
||||
char b2[CBM_SZ_16];
|
||||
snprintf(b2, sizeof(b2), "%d", failure_errno);
|
||||
cbm_log_error("gbuf.dump_failed", "rc", b1, "errno", b2, "nodes", b3, "edges", b4);
|
||||
}
|
||||
|
||||
static void free_dump_resources(char **url_paths, char **local_names, int edge_count,
|
||||
CBMDumpEdge *dump_edges, CBMDumpNode *dump_nodes,
|
||||
int64_t *temp_to_final) {
|
||||
@@ -1896,6 +1923,7 @@ int cbm_gbuf_dump_to_sqlite(cbm_gbuf_t *gb, const char *path) {
|
||||
int64_t max_temp_id = gb->next_id;
|
||||
int64_t *temp_to_final = cbm_calloc(CBM_MEM_CLASS_DUMP, (size_t)max_temp_id * sizeof(int64_t));
|
||||
if (!temp_to_final) {
|
||||
log_dump_failed(CBM_NOT_FOUND, errno, 0, 0);
|
||||
return CBM_NOT_FOUND;
|
||||
}
|
||||
|
||||
@@ -1926,6 +1954,7 @@ int cbm_gbuf_dump_to_sqlite(cbm_gbuf_t *gb, const char *path) {
|
||||
* uninitialized budget from ever triggering the free). */
|
||||
cbm_db_writer_t *w = cbm_writer_open(path);
|
||||
if (!w) {
|
||||
log_dump_failed(CBM_NOT_FOUND, errno, node_idx, 0);
|
||||
cbm_free(CBM_MEM_CLASS_DUMP, src_nodes);
|
||||
cbm_free(CBM_MEM_CLASS_DUMP, dump_nodes);
|
||||
cbm_free(CBM_MEM_CLASS_DUMP, temp_to_final);
|
||||
@@ -1980,12 +2009,19 @@ int cbm_gbuf_dump_to_sqlite(cbm_gbuf_t *gb, const char *path) {
|
||||
int frc = cbm_writer_finalize(w, gb->project, gb->root_path, indexed_at, dump_nodes, node_idx,
|
||||
dump_edges, edge_idx, gb->dump_vectors, gb->dump_vector_count,
|
||||
gb->dump_token_vecs, gb->dump_token_vec_count);
|
||||
/* Read errno before anything else can touch it: the profiling macro
|
||||
* below is already one library call away from losing the reason. */
|
||||
int finalize_errno = errno;
|
||||
CBM_PROF_END_N("dump", "6_write_db_finalize", t_finalize, node_idx + edge_idx);
|
||||
if (rc == 0) {
|
||||
rc = frc;
|
||||
}
|
||||
|
||||
log_dump_summary(node_idx, edge_idx);
|
||||
if (rc != 0) {
|
||||
log_dump_failed(rc, finalize_errno, node_idx, edge_idx);
|
||||
} else {
|
||||
log_dump_summary(node_idx, edge_idx);
|
||||
}
|
||||
free_dump_resources(url_paths, local_names, edge_idx, dump_edges, dump_nodes, temp_to_final);
|
||||
cbm_free(CBM_MEM_CLASS_DUMP, src_nodes);
|
||||
return rc;
|
||||
|
||||
Reference in New Issue
Block a user