Skip to content

[FEATURE] Add pluggable ChunkStore interface for chunk text storage - #436

Draft
noel-improv wants to merge 3 commits into
awslabs:mainfrom
noel-improv:feat/chunk-store-interface
Draft

[FEATURE] Add pluggable ChunkStore interface for chunk text storage#436
noel-improv wants to merge 3 commits into
awslabs:mainfrom
noel-improv:feat/chunk-store-interface

Conversation

@noel-improv

@noel-improv noel-improv commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Description

Chunk text is stored inline as a chunk.value property on every __Chunk__ graph node. Neptune keeps all node properties in memory regardless of whether a query reads them, so at scale this is a large, avoidable memory cost. This PR adds a ChunkStore interface for chunk text (get/put/get_batch) with a factory registration pattern, and an InGraphChunkStore implementation that preserves today's behavior as the default. This PR is interface-only: no existing write or read path is wired to the new interface yet, so there is no behavior change. Wiring ChunkGraphBuilder and the read paths to ChunkStore, and adding an external (e.g. S3) backend, are follow-up PRs that depend on this one and should merge after it.

Changes

  • Add ChunkStore, an abstract interface for chunk text storage. put/get_batch are abstract; get has a default implementation (get_batch([chunk_id]).get(chunk_id)) so backends only need to implement get_batch to get single-chunk lookups for free.
  • Add InGraphChunkStore, which reads and writes chunk.value on __Chunk__ nodes, matching the existence semantics of the current get_chunks_query read path (a chunk without a valid __EXTRACTED_FROM__ link to a __Source__ is excluded).
  • Add ChunkStoreFactory, a registration pattern mirroring GraphStoreFactory. InGraphChunkStoreFactory is registered as an explicit last-resort fallback, tried only after any other registered factory, regardless of registration order.
  • Extract a shared graph_utils.to_params() helper for the UNWIND $params-style Cypher parameter wrapping already used by GraphBuilder._to_params; InGraphChunkStore.put() reuses it instead of duplicating the shape inline.

Problem

Related issue (if any): #324

Testing

  • Unit tests added/updated
  • Integration tests added (as appropriate)
  • Existing tests pass (pytest)
  • Tested manually (describe below)

New unit tests cover the ChunkStore abstract contract, InGraphChunkStore's get/get_batch/put behavior against a mocked graph client, and ChunkStoreFactory's registration and fallback-ordering behavior. I also ran the new code against a real Neo4j instance (via a local container) to confirm the Cypher actually executes as written, since mocked unit tests can't catch a malformed query — this caught and fixed a real bug (a missing parameter-wrapping step) before it reached review.

Checklist

  • Code follows existing style and conventions
  • License headers present on new files
  • Documentation updated (if applicable) — not applicable yet: this is an internal storage interface with no user-facing config surface until a real external backend (S3ChunkStore) is wired in
  • No breaking changes (or clearly documented)

No new backend is wired into any existing write or read path, so there is nothing to migrate and no behavior change for current users.


By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Chunk text lives inline as a chunk.value graph property today, which
Neptune keeps in memory for every node whether or not a query reads it.
This adds a ChunkStore interface (get/put/get_batch) with a
ChunkStoreFactory registration pattern mirroring GraphStoreFactory, and
an InGraphChunkStore implementing today's behavior as the default. No
existing write or read path is wired to it yet — this is the interface
and default backend only, laying the groundwork for an external (e.g.
S3) backend in a follow-up.
Every backend implementing ChunkStore ends up writing the same
get_batch([chunk_id]).get(chunk_id) one-liner for get(). Make get() a
concrete method on the ABC instead of forcing each implementation to
repeat it; only put()/get_batch() stay abstract.
…reFactory

InGraphChunkStoreFactory checked isinstance(graph_store, GraphStore),
but GraphBatchClient - what real graph builders actually pass as
graph_client - duck-types GraphStore without subclassing it, matching
how the rest of the codebase already treats this parameter. The
isinstance check would have rejected it once ChunkGraphBuilder wires
up to ChunkStore. Check for None instead of type.
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