Problem/Motivation

Vector indexing in ai_vdb_provider_milvus runs inside Drupal's entity lifecycle. Whenever a node is created, updated, translated, or deleted, the provider calls MilvusV2::makeRequest() to insert or remove vectors.

When the Milvus server is unreachable:

  1. makeRequest() had no exception handling, so Guzzle's ConnectException propagated uncaught and unlogged.
  2. The timeouts were set to 120 seconds across the board (connect_timeout, read_timeout, timeout), so every request to a dead host blocked for up to two minutes before failing.
  3. MilvusProvider::insertIntoCollection() threw \Exception("Failed to record vector.") on failure, and the search/query/delete paths let exceptions propagate as well.

Because these calls happen during entity save/delete, the uncaught exception aborted the surrounding operation. The result:

  • Creating or deleting node translations (and other content operations) failed entirely whenever Milvus was down, even though the content operation itself had nothing to do with the vector database.
  • Milvus being unavailable effectively blocked normal content editing, with users hanging for ~2 minutes before hitting an error.

Steps to reproduce

  1. Configure the module against a Milvus server.
  2. Stop Milvus / point it at an unreachable host.
  3. Try to create or delete a node translation (or save any indexed node).
  4. Observe the request hangs for ~120s and then fails with an uncaught exception, aborting the entity operation.

Proposed resolution

  1. Fail fast on connect, but don't cut off legitimate work. Lower connect_timeout to 30 so an unreachable/misconfigured host is detected quickly, while lowering read_timeout and timeout from 120 to 60 so large inserts, index builds, and searches aren't killed mid-flight and mistaken for connection failures. read_timeout is retained to guard against a server that accepts the connection but stalls while sending the response.
  2. Catch and log connection/request errors in MilvusV2::makeRequest() (ConnectException, RequestException, generic \Exception), including host and operation (path) context, then re-throw so callers can decide how to react. MilvusV2 now uses LoggerChannelTrait.
  3. Make callers resilient. Each caller wraps its client call in a try/catch and degrades gracefully instead of aborting the surrounding entity/content operation:
    • insertIntoCollection(): on exception, log and return; also return gracefully (instead of throwing "Failed to record vector.") when the response has no code, since that indicates a caught connection error.
    • deleteFromCollection(): on exception, log and return.
    • query() and search(): on exception, log and return an empty array.
    • Config form (validateConfigurationForm() / buildConfigurationForm()): on exception from describeCollection(), build a sentinel ['code' => -1] result locally and handle it (see UI changes below).
  4. Fix incorrect provider labels. Correct the validation message that referenced "Pinecone" to reference "Milvus".

Remaining tasks

  • Review + commit.

User interface changes

On the provider config form, an unreachable server now produces a clear validation error on the server field ("Could not connect to the Milvus server. Please check the server address and port.") instead of a hang followed by a WSOD. The previous validation message that incorrectly mentioned "Pinecone" now correctly refers to "Milvus".

API changes

MilvusV2::makeRequest() now logs connection/request failures (ConnectException, RequestException, generic \Exception) with host and operation context before re-throwing; its return type and success behaviour are unchanged. It does not return a sentinel payload. Instead, exception handling now lives in the callers: the config-form validation converts a caught exception into a local ['code' => -1] sentinel to trigger a form error, while insertIntoCollection(), deleteFromCollection(), query(), and search() catch, log, and degrade gracefully (returning early or returning an empty array) so a Milvus outage no longer aborts entity operations.

Data model changes

None.

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

remco hoeneveld created an issue. See original summary.

remco hoeneveld’s picture

Issue summary: View changes
remco hoeneveld’s picture

Issue summary: View changes
remco hoeneveld’s picture

Issue summary: View changes
remco hoeneveld’s picture

Version: 1.1.0-beta3 » 1.1.x-dev

remco hoeneveld’s picture

Issue summary: View changes
remco hoeneveld’s picture

Issue summary: View changes