feat(viz): graph_sources lector operations.db + streaming (issue 0049g)
- graph_load_from_operations: SQLite read-only, schema-detect (type_ref/type, from_entity/source, to_entity/target, name/type, weight, updated_at). - 16-color indigo palette por hash FNV1a32 del nombre de tipo. user_data por nodo es FNV1a64(entity.id) — deterministico entre cargas. - Label pool interno: metadata.name (JSON simple) > entities.name > id. - graph_free libera nodes/edges/types/rel_types/labels/strdup'd names via arena_map (GraphData* -> arena). - Streaming pull-based con tiebreak (updated_at, id) y crecimiento x2 de capacidad. Tipos nuevos descubiertos en stream se anaden a types. - Tests: fixture in-memory (3 entity types, 2 rel types, 10 entities, 15 relations) + smoke contra apps/script_navegador/operations.db. - Issue movido a completed/. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include "graph_types.h"
|
||||
|
||||
// Lectores de grafos para `GraphData` (issue 0049g). Disenado como un set de
|
||||
// funciones con la misma firma `GraphLoadFn` para que anadir un backend nuevo
|
||||
// (JSON, JSONL, GraphML, etc.) sea declarar otra funcion compatible — el
|
||||
// resto del codigo (apps, viewport, force layout) no cambia.
|
||||
//
|
||||
// Esquema soportado de operations.db:
|
||||
// entities (id, type_ref|type, name?, metadata?, updated_at)
|
||||
// relations (id, from_entity|source, to_entity|target, name?, type?,
|
||||
// weight?, updated_at)
|
||||
// La funcion detecta los nombres reales via `PRAGMA table_info` y mapea:
|
||||
// - entity.type_ref / entity.type → EntityType (color por hash de nombre)
|
||||
// - relation.name (o type) → RelationType
|
||||
// - entity.id → user_data (FNV1a 64), label
|
||||
// - entity.metadata.name (json) → label si existe, else id
|
||||
|
||||
namespace graph {
|
||||
|
||||
struct GraphLoadStats {
|
||||
int nodes_loaded;
|
||||
int edges_loaded;
|
||||
int types_discovered;
|
||||
int rel_types_discovered;
|
||||
int errors;
|
||||
char error_msg[256];
|
||||
};
|
||||
|
||||
// Firma uniforme para todos los backends. `uri` es opaco — para
|
||||
// `graph_load_from_operations` es el path de un fichero SQLite.
|
||||
typedef bool (*GraphLoadFn)(const char* uri, GraphData* out, GraphLoadStats* stats);
|
||||
|
||||
// Carga sincrona de operations.db. Allocs propios en out (nodes/edges/types/
|
||||
// rel_types + string pool interno). El caller libera con graph_free.
|
||||
bool graph_load_from_operations(const char* db_path, GraphData* out, GraphLoadStats* stats);
|
||||
|
||||
// Libera toda la memoria alocada por graph_load_from_operations (incluyendo
|
||||
// los nombres de tipos y el label pool). Deja la struct a cero.
|
||||
void graph_free(GraphData* graph);
|
||||
|
||||
// Devuelve el label de un nodo. Si label_idx == 0 o no hay pool, retorna "".
|
||||
const char* graph_label(const GraphData* graph, uint32_t label_idx);
|
||||
|
||||
// --- Streaming --------------------------------------------------------------
|
||||
// Pull-based: el caller invoca pull cada N ms y la fuente devuelve cuantas
|
||||
// entidades/relaciones nuevas anadio in-place al GraphData. Si no hay sitio
|
||||
// (capacity), corta y devuelve cuanto pudo escribir; el caller decide si
|
||||
// reallocar.
|
||||
struct GraphStreamSource;
|
||||
|
||||
GraphStreamSource* graph_stream_operations_open(const char* db_path, int poll_ms);
|
||||
int graph_stream_pull(GraphStreamSource* src, GraphData* graph);
|
||||
void graph_stream_close(GraphStreamSource* src);
|
||||
|
||||
} // namespace graph
|
||||
Reference in New Issue
Block a user