Commit graph

3 commits

Author SHA1 Message Date
8f17c42c65
test(core): cover the review fixes; scope history gaps; guard record --server
Adds regression tests for the fixed-width timestamp format and sub-second
boundaries, in-memory store dedup and cursor pagination, stream-ID selector
escaping, live-vs-synthetic event IDs, gap healing and baseline state reset,
path-scoped diff ignores, nested Added/Removed flags, snapshot watermarks and
the TypeSnapshot record, NodePort/headless service sanitization, the
dry-run-gated apply, skipped-object reporting, and the expanded gvrFor table.
The object-history endpoint now scopes gap markers to the requested window,
and record --server fails loudly instead of silently recording locally.
2026-08-06 07:01:21 +05:30
44fbd878a1
fix(core): storage time ordering, watch state machine, replay safety, API pagination
Storage: fixed-width millisecond timestamp format with a one-time migration
so lexicographic comparisons stay chronological; snapshot auto-IDs get
nanosecond precision; Close is synchronized; commit failures roll back; DSN
paths are URI-escaped; the dedup index is no longer rebuilt every startup;
the in-memory store now dedups by event_id and honors Limit/Offset/SinceSeq.

Event/discovery: stream IDs URL-escape the selector so slash-containing label
selectors round-trip and cannot collide; alias resolution fills empty fields
only and no longer clobbers explicit group/version/kind; rc maps to
replicationcontrollers and rs to replicasets.

Watch: the label selector is now actually applied to List and Watch; the 410
relist path is backoff-throttled, backoff resets after a healthy watch, an
empty list resourceVersion backs off instead of looping forever, non-410
watch errors reconnect without writing a spurious permanent gap, an idle
watch timer forces reconnects, and Run cancels sibling streams and recovers
from panics. Synthetic relist events carry a distinct event_id so unchanged
objects re-listed after a gap survive dedup.

Materialize: a baseline now resets object state (objects deleted during a gap
disappear) and heals open gaps; diff ignores server metadata by path, not by
key name, so user fields named status/uid are kept; nested add/remove carry
Added/Removed flags; dotted paths are escaped; Diff validates the window and
treats a zero before as empty; Snapshot records per-stream watermarks and
writes a TypeSnapshot journal record.

Replay: apply requires a successful dry run; gvrFor covers every policy kind
so Include* toggles work; unsupported kinds are reported as skipped instead
of silently dropped; NodePort services lose clusterIP and nodePort while
headless keeps clusterIP: None; targetNS is always honored; namespace mapping
collisions are detected; plan IDs and field managers are collision-safe and
plans are mutex-guarded against concurrent dry-runs/applies.

API: cursor pagination pushes ingest_seq into the SQL filter (export --server
no longer truncates); gap records expose their payload; /v1/diff requires a
cluster_id; dry-run/apply no longer accept a client-supplied kubeconfig;
plans carry target_context; HTTP server gets timeouts.

Metrics: the watch collector and replay planner now bump the registered
counters, and the server refreshes store-derived gauges on a ticker.

CLI: replay apply works locally and refuses to apply after a failed dry run;
coverage --server follows cursors and shows gap details; timeline
auto-detects namespaces and resolves cluster-scoped objects; diff validates
the window; export writes 0600 files; PVCs are no longer treated as
cluster-scoped; krply-server reports the build version.
2026-08-06 06:50:30 +05:30
7cc863d40b
feat(core): add journal, collector, storage, and materializer
- durable event schema with stream identity and dedup hashing
- SQLite WAL and in-memory journal stores with atomic append+checkpoint
- list-and-watch collector with bookmarks, reconnects, and 410 relists
- state reduction, snapshots, and semantic field diffs
2026-08-06 05:30:51 +05:30