You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
1. ingest.py is copied into 9 packages and only supports create-from-scratch
All of these have almost identical src/ingest.py files: _template, sqlite, mysql, mongodb, supabase, dynamodb, huggingface, s3, zeroentropy. Each one does:
docs=list(source) # materialise the whole source in memory
...
returnawaitclient.create_index(index_name, docs, model_id=model_id)
Memory:list(source) loads the whole table, collection, or dataset before anything is sent. For huggingface, dynamodb, or a large MongoDB collection, that can mean millions of rows in RAM. The connectors' streaming __iter__ does nothing to help.
Create-only:ingest() always calls create_index. There is no way to re-sync a source into an existing index (upsert changed rows, add new ones). Users have to delete the index and rebuild it, which leaves search unavailable in the meantime.
Drift: fixes land in some copies and not others (see Yatharth/samplev2 #2 below).
The S3 connector already shows the right pattern in moss-connector-s3/src/watch.py:
create_index when the index is missing
add_docs(..., options=MutationOptions(upsert=True)) for additions and modifications
delete_docs for removals
This logic is only used by the S3 watcher, and every other connector lacks it.
2. Bug: moss-connector-mysql does not support auto_id
packages/moss-data-connector/README.md documents for all connectors:
Use auto_id=True when your mapper does not have a stable primary key and you want Moss to generate UUID document IDs.
But moss-connector-mysql/src/ingest.py has no auto_id parameter and no _replace_doc_id helper. await ingest(source, ..., auto_id=True) raises TypeError: ingest() got an unexpected keyword argument 'auto_id'. Every other connector supports it (it was added in #172).
Proposed solution
Fix MySQL first (small, separate PR): add auto_id: bool = False to match moss-connector-sqlite/src/ingest.py, plus a test in moss-connector-mysql/tests.
Batched ingest: consume source in chunks (e.g. batch_size: int = 500):
create the index with the first batch
send the remaining batches with add_docs(index_name, batch, options=MutationOptions(upsert=True))
return an aggregated result (e.g. total docs, list of job IDs)
Add a mode parameter:
mode="create": current behavior (default, backwards compatible)
mode="upsert": if the index exists, upsert into it; otherwise create it
optionally mode="replace": upsert, then delete_docs for IDs no longer present in the source. Reuse the diff logic from s3/watch.py.
Deduplicate: either move the shared ingest into one small shared module that the connectors depend on, or (if the maintainers prefer each connector to stay standalone) at minimum update _template/src/ingest.py and add a parametrized test that checks every connector's ingest has the same signature, so they can't drift again.
Document batch_size / mode in packages/moss-data-connector/README.md and each connector README.
Acceptance criteria
moss_connector_mysql.ingest(..., auto_id=True) works and is tested.
Peak memory while ingesting N rows is bounded by batch_size: a test with a generator source of 10k fake docs and a mocked MossClient checks that no single call receives more than batch_size docs.
mode="upsert" on an existing index calls add_docs(upsert=True) and never create_index / delete_index.
Default behavior (mode="create", no batch_size) stays compatible for existing callers.
Area:
packages/moss-data-connector/*Problem
1.
ingest.pyis copied into 9 packages and only supports create-from-scratchAll of these have almost identical
src/ingest.pyfiles:_template,sqlite,mysql,mongodb,supabase,dynamodb,huggingface,s3,zeroentropy. Each one does:(e.g.
moss-connector-sqlite/src/ingest.py:32-36,moss-connector-mongodb/src/ingest.py:32-36)This causes three problems:
list(source)loads the whole table, collection, or dataset before anything is sent. Forhuggingface,dynamodb, or a large MongoDB collection, that can mean millions of rows in RAM. The connectors' streaming__iter__does nothing to help.ingest()always callscreate_index. There is no way to re-sync a source into an existing index (upsert changed rows, add new ones). Users have to delete the index and rebuild it, which leaves search unavailable in the meantime.The S3 connector already shows the right pattern in
moss-connector-s3/src/watch.py:create_indexwhen the index is missingadd_docs(..., options=MutationOptions(upsert=True))for additions and modificationsdelete_docsfor removalsThis logic is only used by the S3 watcher, and every other connector lacks it.
2. Bug:
moss-connector-mysqldoes not supportauto_idpackages/moss-data-connector/README.mddocuments for all connectors:But
moss-connector-mysql/src/ingest.pyhas noauto_idparameter and no_replace_doc_idhelper.await ingest(source, ..., auto_id=True)raisesTypeError: ingest() got an unexpected keyword argument 'auto_id'. Every other connector supports it (it was added in #172).Proposed solution
auto_id: bool = Falseto matchmoss-connector-sqlite/src/ingest.py, plus a test inmoss-connector-mysql/tests.sourcein chunks (e.g.batch_size: int = 500):add_docs(index_name, batch, options=MutationOptions(upsert=True))modeparameter:mode="create": current behavior (default, backwards compatible)mode="upsert": if the index exists, upsert into it; otherwise create itmode="replace": upsert, thendelete_docsfor IDs no longer present in the source. Reuse the diff logic froms3/watch.py._template/src/ingest.pyand add a parametrized test that checks every connector'singesthas the same signature, so they can't drift again.batch_size/modeinpackages/moss-data-connector/README.mdand each connector README.Acceptance criteria
moss_connector_mysql.ingest(..., auto_id=True)works and is tested.batch_size: a test with a generator source of 10k fake docs and a mockedMossClientchecks that no single call receives more thanbatch_sizedocs.mode="upsert"on an existing index callsadd_docs(upsert=True)and nevercreate_index/delete_index.mode="create", nobatch_size) stays compatible for existing callers.ingestsignature.Overlap check
_template.