Skip to content

feat: persist _marker cursor for gapless resume across restarts#23

Merged
carlosmmatos merged 3 commits intomainfrom
atlas/task-10
Apr 13, 2026
Merged

feat: persist _marker cursor for gapless resume across restarts#23
carlosmmatos merged 3 commits intomainfrom
atlas/task-10

Conversation

@carlosmmatos
Copy link
Copy Markdown
Contributor

Adds state persistence so the bridge resumes from its exact position in the Falcon indicator feed after a container restart, eliminating gaps and redundant re-fetches.

What changed:

  • New ccib/state.py module with atomic file writes (tempfile + os.replace) to prevent corruption on mid-write kills
  • FalconReaderThread saves the last _marker cursor to data/state.json after each fetch cycle and resumes from it on startup
  • get_indicators() now yields (batch, last_marker) tuples so the marker propagates to the caller
  • Chronicle._indicator_ts() uses the indicator's own published_date/last_updated instead of wall-clock time for more accurate Chronicle timestamps
  • FigConfig gains STATE_FILE env var support (optional, defaults to data/state.json)
  • Dockerfile creates /ccib/data with proper ownership and declares a VOLUME; .dockerignore prevents local state from leaking into the image
  • README documents the volume mount and fallback behavior

Without the volume mount the bridge still works — it falls back to initial_sync_lookback and the ICache deduplicates any overlap.

Switch state persistence from wall-clock timestamps to the Falcon Intel
API's opaque _marker cursor. This eliminates gaps from clock skew and
indicators arriving between time.time() and the actual API response.

- Add state.py module for JSON-based state load/save with atomic writes
- Expose _marker from falcon.py generator as (batch, marker) tuples
- Track last_marker_seen in FalconReaderThread, fall back to wall-clock
  only when no indicators are returned in a cycle
- Wire up state loading in __main__.py with safe fallback for old state
  files (missing last_marker key triggers initial_sync_lookback)
- Add per-indicator timestamps in chronicle.py using published_date
- Add STATE_FILE env var support and Dockerfile volume for /ccib/data
- Update README with state persistence docs and volume mount examples
The local data/state.json was leaking into the Docker image via
COPY, and the non-recursive chown left it root-owned — causing
permission denied errors when ccibuser tried to read it.
@carlosmmatos carlosmmatos added the fix Bug fixes label Apr 11, 2026
@carlosmmatos carlosmmatos changed the title Persist _marker cursor for gapless resume across restarts feat: persist _marker cursor for gapless resume across restarts Apr 11, 2026
@carlosmmatos carlosmmatos merged commit 68f6259 into main Apr 13, 2026
7 checks passed
@carlosmmatos carlosmmatos deleted the atlas/task-10 branch April 13, 2026 19:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix Bug fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants