Repository navigation
Conversation
This was referenced Sep 14, 2026
[session storage 2/2] Remove open-or-create from both stores, and close from the segment store
#1625
Draft
Closed
Draft
[qdrant options] Let a deployment tune a Qdrant collection's HNSW, optimizers and quantization
#1618
Draft
edwinyyyu
force-pushed
the
feat/vector-store-request-timeout-speedkick
branch
5 times, most recently
from
September 14, 2026 23:16
d87b9ba to
2bccb36
Compare
edwinyyyu
force-pushed
the
feat/vector-store-request-timeout-speedkick
branch
2 times, most recently
from
September 15, 2026 17:26
d87b9ba to
6d51658
Compare
edwinyyyu
force-pushed
the
feat/vector-store-request-timeout-speedkick
branch
5 times, most recently
from
September 15, 2026 19:16
8f47ff5 to
22f2639
Compare
edwinyyyu
force-pushed
the
feat/vector-store-request-timeout-speedkick
branch
from
September 15, 2026 19:47
22f2639 to
8d1d54f
Compare
edwinyyyu
force-pushed
the
feat/vector-store-request-timeout-speedkick
branch
from
September 18, 2026 19:39
0461e28 to
ee80e36
Compare
The Qdrant and Milvus clients were built without a timeout, so a remote write could hang a request indefinitely. `request_timeout` on QdrantConf and MilvusConf, in seconds, is passed to the client; it is required, with no default, so a deployment states how long it is willing to wait, and the configuration wizard supplies 30 seconds as the starting point. The sample configurations and the configuration docs show the option. A breaking configuration change on `speedkick`. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 5c669ee)
A required field bounds only the deployments that added it and fails the rest at load; a default bounds every deployment, including one whose cfg.yml predates the option, and matches every other field on QdrantConf and MilvusConf. The wizard no longer carries the value: it constructs the confs and the field supplies it. Zero and negative values are rejected at load rather than handed to httpx as the request timeout and to pymilvus as the gRPC deadline, where zero expires every request on arrival. Without the option, qdrant-client already bounded a request at 5 seconds (httpx's default for REST, DEFAULT_GRPC_TIMEOUT for gRPC); pymilvus passed no deadline, so a Milvus request could wait forever. The default applies 30 seconds to both. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 98f09b2)
Neither client's keyword carries the unit, and the field mirrors neither (both take `timeout`), so it follows max_retry_interval_seconds on the embedder and language model configurations instead. The sample configurations lose their "seconds" comments, which the name now carries. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 0fe31cd)
MilvusClient's constructor timeout is the time it waits for the channel to become ready, at construction and on reconnect; a request is bounded only by the timeout passed to that request, and pymilvus keeps no default for it, so every request the store made had no deadline. The store now takes request_timeout_seconds and passes it on every request; the client keeps it as its connection bound. A test wraps every request method and checks the timeout reaches each call. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 92f536e)
qdrant-client takes its timeout as an int and rounds a fraction up, so a fractional value was honored by pymilvus and silently changed for Qdrant. An int is honored exactly by both, and matches max_retry_interval_seconds on the embedder and language model configurations. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 5e9f363)
…e the stores are configured MilvusVectorStoreCollection.get() was the one client request without `timeout=`; the spy test now exercises it, so a request without the timeout fails the test. The configuration parameter table gains `request_timeout_seconds`, the databases page's Milvus example carries it, and the configuration page gains a Qdrant example beside the Milvus one. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn
edwinyyyu
force-pushed
the
feat/vector-store-request-timeout-speedkick
branch
from
September 21, 2026 18:11
ee80e36 to
ce97ac0
Compare
Contributor
Author
|
@malatewang These changes (or similar) will get folded into #1631 since a timeout is required for #1631. This was mistakenly taken out of the chain. |
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 22, 2026
The Qdrant and Milvus clients were built without a timeout, so a remote write could hang a request indefinitely. `request_timeout` on QdrantConf and MilvusConf, in seconds, is passed to the client; it is required, with no default, so a deployment states how long it is willing to wait, and the configuration wizard supplies 30 seconds as the starting point. The sample configurations and the configuration docs show the option. A breaking configuration change on `speedkick`. Folded from MemMachine#1630 into MemMachine#1631, whose purge relies on a bounded request: request_timeout sits beside collection_registry in the configuration, the tests and the samples, and MemMachine#1630's is_distributed and registry_replication_factor lines are dropped (both fields are gone below). Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 5c669ee) (cherry picked from commit f4b5aea)
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 22, 2026
A required field bounds only the deployments that added it and fails the rest at load; a default bounds every deployment, including one whose cfg.yml predates the option, and matches every other field on QdrantConf and MilvusConf. The wizard no longer carries the value: it constructs the confs and the field supplies it. Zero and negative values are rejected at load rather than handed to httpx as the request timeout and to pymilvus as the gRPC deadline, where zero expires every request on arrival. Without the option, qdrant-client already bounded a request at 5 seconds (httpx's default for REST, DEFAULT_GRPC_TIMEOUT for gRPC); pymilvus passed no deadline, so a Milvus request could wait forever. The default applies 30 seconds to both. Folded from MemMachine#1630 into MemMachine#1631: the timeout argument leaves the configurations that also name a collection_registry, which stays; the new positivity checks name a collection_registry, which MemMachine#1631 requires. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 98f09b2) (cherry picked from commit 95dab30)
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 22, 2026
Neither client's keyword carries the unit, and the field mirrors neither (both take `timeout`), so it follows max_retry_interval_seconds on the embedder and language model configurations instead. The sample configurations lose their "seconds" comments, which the name now carries. Folded from MemMachine#1630 into MemMachine#1631: the rename reaches the configurations and tests that also name a collection_registry. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 0fe31cd) (cherry picked from commit b9f19fe)
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 22, 2026
MilvusClient's constructor timeout is the time it waits for the channel to become ready, at construction and on reconnect; a request is bounded only by the timeout passed to that request, and pymilvus keeps no default for it, so every request the store made had no deadline. The store now takes request_timeout_seconds and passes it on every request; the client keeps it as its connection bound. A test wraps every request method and checks the timeout reaches each call. Folded from MemMachine#1630 into MemMachine#1631, whose Milvus store no longer keeps its registry in Milvus: the timeout reaches every request this store makes, the existence check under the native-creation lock and the purge's existence check, query and delete included, and the per-namespace registry calls this commit bounded are gone. The test follows the store's requests, the purge's among them, and no longer expects the registry's insert. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 92f536e) (cherry picked from commit 6a7be31)
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 22, 2026
qdrant-client takes its timeout as an int and rounds a fraction up, so a fractional value was honored by pymilvus and silently changed for Qdrant. An int is honored exactly by both, and matches max_retry_interval_seconds on the embedder and language model configurations. Folded from MemMachine#1630 into MemMachine#1631: the whole seconds reach the configurations and tests that also name a collection_registry. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 5e9f363) (cherry picked from commit 874ec47)
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 22, 2026
…e the stores are configured MilvusVectorStoreCollection.get() was the one client request without `timeout=`; the spy test now exercises it, so a request without the timeout fails the test. The configuration parameter table gains `request_timeout_seconds`, the databases page's Milvus example carries it, and the configuration page gains a Qdrant example beside the Milvus one. Folded from MemMachine#1630 into MemMachine#1631: the parameter table and the Milvus example show the timeout beside collection_registry, and the every-request test spies on get again, now that get carries the timeout. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit ce97ac0)
Contributor
Author
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 25, 2026
The Qdrant and Milvus clients were built without a timeout, so a remote write could hang a request indefinitely. `request_timeout` on QdrantConf and MilvusConf, in seconds, is passed to the client; it is required, with no default, so a deployment states how long it is willing to wait, and the configuration wizard supplies 30 seconds as the starting point. The sample configurations and the configuration docs show the option. A breaking configuration change on `speedkick`. Folded from MemMachine#1630 into MemMachine#1631, whose purge relies on a bounded request: request_timeout sits beside collection_registry in the configuration, the tests and the samples, and MemMachine#1630's is_distributed and registry_replication_factor lines are dropped (both fields are gone below). Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 5c669ee) (cherry picked from commit f4b5aea)
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 25, 2026
A required field bounds only the deployments that added it and fails the rest at load; a default bounds every deployment, including one whose cfg.yml predates the option, and matches every other field on QdrantConf and MilvusConf. The wizard no longer carries the value: it constructs the confs and the field supplies it. Zero and negative values are rejected at load rather than handed to httpx as the request timeout and to pymilvus as the gRPC deadline, where zero expires every request on arrival. Without the option, qdrant-client already bounded a request at 5 seconds (httpx's default for REST, DEFAULT_GRPC_TIMEOUT for gRPC); pymilvus passed no deadline, so a Milvus request could wait forever. The default applies 30 seconds to both. Folded from MemMachine#1630 into MemMachine#1631: the timeout argument leaves the configurations that also name a collection_registry, which stays; the new positivity checks name a collection_registry, which MemMachine#1631 requires. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 98f09b2) (cherry picked from commit 95dab30)
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 25, 2026
Neither client's keyword carries the unit, and the field mirrors neither (both take `timeout`), so it follows max_retry_interval_seconds on the embedder and language model configurations instead. The sample configurations lose their "seconds" comments, which the name now carries. Folded from MemMachine#1630 into MemMachine#1631: the rename reaches the configurations and tests that also name a collection_registry. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 0fe31cd) (cherry picked from commit b9f19fe)
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 25, 2026
MilvusClient's constructor timeout is the time it waits for the channel to become ready, at construction and on reconnect; a request is bounded only by the timeout passed to that request, and pymilvus keeps no default for it, so every request the store made had no deadline. The store now takes request_timeout_seconds and passes it on every request; the client keeps it as its connection bound. A test wraps every request method and checks the timeout reaches each call. Folded from MemMachine#1630 into MemMachine#1631, whose Milvus store no longer keeps its registry in Milvus: the timeout reaches every request this store makes, the existence check under the native-creation lock and the purge's existence check, query and delete included, and the per-namespace registry calls this commit bounded are gone. The test follows the store's requests, the purge's among them, and no longer expects the registry's insert. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 92f536e) (cherry picked from commit 6a7be31)
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 25, 2026
qdrant-client takes its timeout as an int and rounds a fraction up, so a fractional value was honored by pymilvus and silently changed for Qdrant. An int is honored exactly by both, and matches max_retry_interval_seconds on the embedder and language model configurations. Folded from MemMachine#1630 into MemMachine#1631: the whole seconds reach the configurations and tests that also name a collection_registry. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 5e9f363) (cherry picked from commit 874ec47)
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 25, 2026
…e the stores are configured MilvusVectorStoreCollection.get() was the one client request without `timeout=`; the spy test now exercises it, so a request without the timeout fails the test. The configuration parameter table gains `request_timeout_seconds`, the databases page's Milvus example carries it, and the configuration page gains a Qdrant example beside the Milvus one. Folded from MemMachine#1630 into MemMachine#1631: the parameter table and the Milvus example show the timeout beside collection_registry, and the every-request test spies on get again, now that get carries the timeout. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit ce97ac0)
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 25, 2026
The Qdrant and Milvus clients were built without a timeout, so a remote write could hang a request indefinitely. `request_timeout` on QdrantConf and MilvusConf, in seconds, is passed to the client; it is required, with no default, so a deployment states how long it is willing to wait, and the configuration wizard supplies 30 seconds as the starting point. The sample configurations and the configuration docs show the option. A breaking configuration change on `speedkick`. Folded from MemMachine#1630 into MemMachine#1631, whose purge relies on a bounded request: request_timeout sits beside collection_registry in the configuration, the tests and the samples, and MemMachine#1630's is_distributed and registry_replication_factor lines are dropped (both fields are gone below). Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 5c669ee) (cherry picked from commit f4b5aea)
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 25, 2026
A required field bounds only the deployments that added it and fails the rest at load; a default bounds every deployment, including one whose cfg.yml predates the option, and matches every other field on QdrantConf and MilvusConf. The wizard no longer carries the value: it constructs the confs and the field supplies it. Zero and negative values are rejected at load rather than handed to httpx as the request timeout and to pymilvus as the gRPC deadline, where zero expires every request on arrival. Without the option, qdrant-client already bounded a request at 5 seconds (httpx's default for REST, DEFAULT_GRPC_TIMEOUT for gRPC); pymilvus passed no deadline, so a Milvus request could wait forever. The default applies 30 seconds to both. Folded from MemMachine#1630 into MemMachine#1631: the timeout argument leaves the configurations that also name a collection_registry, which stays; the new positivity checks name a collection_registry, which MemMachine#1631 requires. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 98f09b2) (cherry picked from commit 95dab30)
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 25, 2026
Neither client's keyword carries the unit, and the field mirrors neither (both take `timeout`), so it follows max_retry_interval_seconds on the embedder and language model configurations instead. The sample configurations lose their "seconds" comments, which the name now carries. Folded from MemMachine#1630 into MemMachine#1631: the rename reaches the configurations and tests that also name a collection_registry. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 0fe31cd) (cherry picked from commit b9f19fe)
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 25, 2026
MilvusClient's constructor timeout is the time it waits for the channel to become ready, at construction and on reconnect; a request is bounded only by the timeout passed to that request, and pymilvus keeps no default for it, so every request the store made had no deadline. The store now takes request_timeout_seconds and passes it on every request; the client keeps it as its connection bound. A test wraps every request method and checks the timeout reaches each call. Folded from MemMachine#1630 into MemMachine#1631, whose Milvus store no longer keeps its registry in Milvus: the timeout reaches every request this store makes, the existence check under the native-creation lock and the purge's existence check, query and delete included, and the per-namespace registry calls this commit bounded are gone. The test follows the store's requests, the purge's among them, and no longer expects the registry's insert. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 92f536e) (cherry picked from commit 6a7be31)
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 25, 2026
qdrant-client takes its timeout as an int and rounds a fraction up, so a fractional value was honored by pymilvus and silently changed for Qdrant. An int is honored exactly by both, and matches max_retry_interval_seconds on the embedder and language model configurations. Folded from MemMachine#1630 into MemMachine#1631: the whole seconds reach the configurations and tests that also name a collection_registry. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit 5e9f363) (cherry picked from commit 874ec47)
edwinyyyu
added a commit
to edwinyyyu/MemMachine
that referenced
this pull request
Sep 25, 2026
…e the stores are configured MilvusVectorStoreCollection.get() was the one client request without `timeout=`; the spy test now exercises it, so a request without the timeout fails the test. The configuration parameter table gains `request_timeout_seconds`, the databases page's Milvus example carries it, and the configuration page gains a Qdrant example beside the Milvus one. Folded from MemMachine#1630 into MemMachine#1631: the parameter table and the Milvus example show the timeout beside collection_registry, and the every-request test spies on get again, now that get carries the timeout. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn (cherry picked from commit ce97ac0)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose of the change
A remote vector store request had no bound on this side: qdrant-client bounds its own at 5 s by default, pymilvus not at all, so a Milvus write could hang a request indefinitely, and a Qdrant deployment could not choose its bound.
request_timeout_secondsonQdrantConfandMilvusConf: an integer number of seconds, default 30, required positive (zero would expire every request on arrival), named for its unit likemax_retry_interval_secondson the embedder and language-model configurations. Why the two stores differ in the diff:AsyncQdrantClient(timeout=)is a client-wide default, the httpx request timeout on REST and the deadline of every gRPC call, so the one kwarg where the client is built bounds every requestQdrantVectorStoremakes and the store itself does not change (qdrant-client takes an integer and appliesmath.ceilto it).MilvusClient(timeout=)bounds connecting and reconnecting only; each data call takes its owntimeout=, so the Milvus store carries the value and passes it on every request it makes. Acfg.ymlthat predates the option loads unchanged. The sample configurations, the configuration docs' parameter table and their Qdrant and Milvus examples show the option.Stack
23 PRs on
main: 5 independent ones, and three consecutive stages numbered on their own: the vector store scale-out, the SQLite store fixes and the vector store contract changes. A stacked PR's diff on GitHub is cumulative until the PRs under it merge.Independent PRs, each directly on
main; review and merge in any order:The vector store stages, consecutive: each stacked on the one below. [vector store scale-out 1/5] is directly on
mainand 2/5 on it alone; they do not depend on the independent PRs. From 3/5 up, the chain's history also carries the independent PRs' commits beneath it, since the later stages were written on top of them ([vector store contract 2/6] on #1624's session policy, for one); so a merge of an independent PR rebases the chain without conflict, and until they merge those PRs' changes show in a stacked PR's diff.speedkick, #1588)speedkick, #1589)This PR is its 6 commits,
f4b5aea9c,95dab3075,b9f19fe3d,6a7be31de,874ec4707,ce97ac053, directly onmain, independent of the others: review and merge it in any order among the independent PRs (a later one touching the same file rebases). The stages' history carries the same change from [vector store scale-out 3/5] up, so their diffs include it until it merges.Verification
At every one of its 6 commits, on 2026-09-21:
ruff checkandruff format --checkclean;ty checkclean as CI runs it (uv run --frozen --all-extras ty check --project packages/server); the full server suite without integration tests passes (pytest packages/server/server_tests -m "not integration"), 1916 tests at its headce97ac053.🤖 Generated with Claude Code
https://claude.ai/code/session_01ESpWYTmCR7X3bJEpoA8SAn