Skip to content

feat(ingestion): submit all sources then poll the last episode (v0.3.0) - #607

Merged
jackaldenryan merged 5 commits into
mainfrom
jack/zep-ingest-0.3.0
Aug 28, 2026
Merged

jackaldenryan merged 5 commits into
mainfrom
jack/zep-ingest-0.3.0

Conversation

@jackaldenryan

@jackaldenryan jackaldenryan commented Aug 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • zep-ingest 0.3.0: Submit all sources into a graph before any optional wait. Sequential vs batch only chooses graph.add vs the Batch API — not “finish extracting this file before sending the next.”
  • wait() is opt-in and aligned with Check data ingestion status:
    • Batch path: poll last batch_id via batch.get
    • Sequential graph.add: poll last-submitted episode
    • Sequential thread.add_messages: poll last message UUID per thread (message_uuids only — regular add_messages does not return task_id)
    • Nodes/triples: poll every task_id
  • Default timeout: max(120s, 60s × items_submitted). Pass timeout=None for unbounded wait.
  • SourcePaths sequences, ConcatLoader, and IngestResult.combine() for mixed/multi-call submits. combine() merges poll handles only (not node_uuids/edge_uuids). Prefer separate wait() for seeding vs episodes.
  • Multi-thread sequential fix: each thread saga polled independently (no false-complete when one thread finishes first).

Test plan

  • cd ingestion && uv sync --extra dev && uv run pytest tests/ -m "not integration" (678 passed)
  • uv run ruff check . && uv run ruff format --check . && uv run mypy src/
  • Production smoke: keybank run zep-prod -- env ZEP_API_URL=https://api.getzep.com uv run python scripts/release_smoke_prod.py (7/7)
  • Pytest integration against prod (2/2)
  • After merge: dispatch Release Ingestion Package on main → publishes zep-ingest 0.3.0 (zep-ingest-v0.3.0)

Stop treating sequential ingest as wait-for-each-file. Queue every file into
a graph first; wait() is opt-in, polls the tail of the per-graph queue, and
scales its timeout with how many episodes were submitted. Bump zep-ingest to
0.3.0 for the release.

Co-authored-by: Cursor <cursoragent@cursor.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical — ingestion/src/zep_ingest/result.py:217: combine() does not verify that results target the same graph/user, yet tail polling marks every combined episode processed when only the final UUID completes. Combining sequential results from different graphs can therefore make wait() return while earlier episodes are still processing. Store destination identity in each result and reject mismatched combinations, or poll one tail per destination. Add a cross-destination test.

Give episodes and manual graph updates more headroom before wait() raises IngestTimeoutError.

Co-authored-by: Cursor <cursoragent@cursor.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Critical — ingestion/src/zep_ingest/result.py, combine() / _refresh_episodes(only_last=True) hunks: combine() neither verifies a shared graph destination nor preserves/verifies actual submission order. Combining results from different graphs—or calling later.combine(earlier)—can poll an unrelated/earlier episode and then mark every episode processed, causing wait() to return while work remains. Track destination and submission ordering in IngestResult and reject incompatible combinations, or poll every combined episode instead of applying the tail optimization.

Poll thread backfills via the last message UUID per request, document batch vs episode vs task handles, and warn against mixing batch and sequential graph.add on one graph.

Co-authored-by: Cursor <cursoragent@cursor.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical

  • ingestion/src/zep_ingest/result.py, _refresh_episodes() / combine() hunks: combine() does not verify that results target the same graph/user, yet tail polling marks every combined episode processed when only episode_uuids[-1] completes. Combining sequential submissions from different destinations can therefore make wait() return succeeded while earlier ingestion is still processing. Store and validate the destination when combining, or retain separate completion tails per submission/destination and poll each one.

No other actionable findings.

Regular thread.add_messages returns message_uuids only (verified against production). Remove dead task_id fallback, poll one tail per thread, and stop falsely marking all threads done when one saga finishes.

Co-authored-by: Cursor <cursoragent@cursor.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical

  • ingestion/src/zep_ingest/result.py, IngestResult.combine() hunk (_single_queue_episode_poll aggregation): Combining multiple results incorrectly preserves tail-only polling whenever each input individually represents one queue. For example, combining two sequential single-thread ingests for different threads leaves the flag True; wait() polls only the second thread’s UUID and marks every UUID processed when it completes, even if the first thread is still processing. The same false-success can occur when combining sequential graph ingests for different graph destinations because destination identity is not retained or validated. Track each result’s queue/destination identity and enable tail-only polling only when all episode handles demonstrably share that queue; otherwise set _single_queue_episode_poll=False and poll every tail independently. Add tests combining separate single-thread results and results from different graph destinations.

Document pre-release prod checks and finalize 0.3.0 changelog notes for thread polling and combine().

Co-authored-by: Cursor <cursoragent@cursor.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical

  • ingestion/src/zep_ingest/result.py, IngestResult.combine() hunk: combining independently queued episode results preserves _single_queue_episode_poll=True. This is unsafe for results from different threads or graphs: wait() polls only the final UUID, then marks every combined UUID processed, potentially returning succeeded while earlier queues are still running. Set the flag to false when combining separate episode-bearing results, or retain queue boundaries and poll one tail per queue. Add a test combining two single-thread results where only the second tail is processed.

@jackaldenryan
jackaldenryan merged commit 54f63ee into main Aug 28, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant