exporter

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 2, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package exporter builds the /api/export zip. It ships JSONL bytes straight from disk into a streaming zip with no transformation; SQLite only selects which JSONL lines to include.

The zip layout follows docs/specs/phase-i-export-contract.md and docs/specs/phase-k-media-contract.md:

data/<YYYY-MM-DD>/<keyhash8>.jsonl          (all rows on disk matched)
data/<YYYY-MM-DD>/<keyhash8>.partial.jsonl  (subset matched)
media/<trace_id>/<idx>.<ext>                 (extracted attachments, if any)
agent/CLAUDE.md
agent/jq-cheatsheet.md
README.md

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func WriteZip

func WriteZip(ctx context.Context, w io.Writer, store *sqlite.Store, dataDir string, filters sqlite.ListFilters, coord *storage.Coordinator) error

WriteZip streams a zip archive of every row matched by filters into w.

Two-phase pipeline (v0.1.1):

  1. Cursor (one SQLite conn borrowed via StreamMatching) walks rows, builds the per-file groups (jsonl_offset → trace ID) and the slim mediaRef slice. Incremental minTs / maxTs / matched count. No zip bytes are written here — if the SQLite query errors, the caller can still return a clean HTTP status.
  2. After the cursor closes (conn released back to the pool), the zip is built. zip.NewWriter is registered with a level-1 Deflate compressor — adopters trade ~5% size for ~3× wall-clock on 100k+ row exports (the workload that motivated streaming in the first place). Each (date, keyhash) group acquires a storage lease in an inner-func scope, writes its entry, and releases on iteration exit; the naive top-of-loop defer would pin every bucket.

dataDir is the storage root that JSONL paths in the SQLite rows are relative to (or absolute; we accept either — the row's JSONLPath is the authoritative reader-side path).

coord (v0.1.1) is the storage coordinator. nil disables lease arbitration: the exporter reads JSONL files without notifying retention — fine for tests / no-retention deployments. Non-nil: groups whose bucket is mid-eviction (ErrFileBeingDeleted) are skipped with a WARN log; the rest of the zip still streams cleanly.

ctx is propagated into StreamMatching (cursor abort on cancel) and honored at every group + media iteration. Cancel mid-export leaves the zip well-formed up to the cancel point — adopters see a truncated body, never a corrupted central directory.

No internal hardCap: callers gate oversize exports via CountMatching BEFORE calling WriteZip. The cursor walks every matching row; pre-flight is the contract.

The returned error means either the SQLite read failed (zip not yet started) or a disk / zip write failed mid-stream (zip may be partial — zw.Close() is still called via defer to write the central directory of whatever was emitted, but downstream callers should treat the archive as suspect).

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL