fix(tests): Integration tests are failing in the CI system: "RuntimeE…#1010
Merged
Conversation
…rror: Event loop is closed" Issue - #1009 Summary: Fix RuntimeError: Event loop is closed in OpenAI client initialization by separating the HTTP/2 probe from production client creation. The probe thread previously returned the AsyncOpenAI client itself, leaving its SSL connections bound to a closed event loop. The production client is now created after the thread exits, in the caller's event loop. Details: The HTTP/2 probe ran in a background thread with its own event loop, created an AsyncOpenAI client, and returned it directly. Closing the thread's event loop while the client still held open keep-alive SSL connections caused `RuntimeError: Event loop is closed` whenever the client was later used in the caller's (different) event loop. Bug Fix: Decouple probe from production client lifetime - Rename probe_and_initialize() → probe_http2(), which now returns a bool instead of an AsyncOpenAI client - Explicitly close the probe client in a finally block so all connections are drained before the thread's event loop is closed - Create the production AsyncOpenAI client after the thread exits, in the caller's event loop context, so its connections bind to the correct running loop HTTP/2 Fallback Logic - Preserve HTTP/2 vs HTTP/1.1 selection: use_http2=True creates a default AsyncOpenAI(); use_http2=False creates one with an explicit httpx.AsyncClient(http2=False) transport - No change to probe timeout (5s) or overall initialization timeout (15s)
…rror: Event loop is closed" Issue - #1009 Summary: Fix two CI-only failures caused by environment variable bleed-through in the CI test pipeline: Docker containers receiving localhost as the OpenSearch hostname (instead of the opensearch service name), and the backend crashing with invalid literal for int() with base 10: '' due to empty Langflow retry env vars being injected into the container. Detials: The GitHub Actions workflow sets OPENSEARCH_HOST=localhost as a step-level env var so the in-process pytest backend can reach OpenSearch via Docker port mapping. This bled into docker-compose, overriding the opensearch service-name default and breaking all OpenSearch calls from inside the backend and Langflow containers. Separately, LANGFLOW_KEY_RETRIES and LANGFLOW_KEY_RETRY_DELAY had no :-default fallbacks in docker-compose.yml, so when unset in CI they were injected as empty strings, causing int("") to raise ValueError inside get_langflow_api_key(). CI Configuration: Docker container startup - Pin OPENSEARCH_HOST=opensearch when invoking docker-compose up in the test-ci and test-ci-local Makefile targets, isolating it from the OPENSEARCH_HOST=localhost value the surrounding CI shell sets for pytest docker-compose.yml: Environment variable defaults - Add :-15 default for LANGFLOW_KEY_RETRIES so unset env produces "15" rather than an empty string that crashes int() in settings.py - Add :-2.0 default for LANGFLOW_KEY_RETRY_DELAY for the same reason; defaults match the hardcoded fallbacks already in settings.py:227-228
Closed
2 tasks
Collaborator
|
Thanks @mpawlow Good one! Lets merge this so that Other PRs could be unblocked in tests. |
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes CI integration test failures by addressing an async OpenAI client lifecycle bug and hardening CI/container environment variable behavior.
Changes:
- Refactors the OpenAI HTTP/2 probe to return only a boolean and creates the production
AsyncOpenAIclient in the caller’s event loop (avoids cross-loop “Event loop is closed” errors). - Adds safe defaults for
LANGFLOW_KEY_RETRIES/LANGFLOW_KEY_RETRY_DELAYindocker-compose.ymlto prevent empty-string parsing failures in CI. - Pins
OPENSEARCH_HOST=opensearchfordocker-compose upin CI Makefile targets to avoid CI env-var bleed-through (localhostinside containers).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/config/settings.py |
Decouples HTTP/2 probe from production client creation to avoid cross-event-loop transport usage. |
docker-compose.yml |
Provides defaults for Langflow retry env vars to prevent int("") / float("") failures. |
Makefile |
Forces container-side OpenSearch hostname to opensearch during CI compose startup. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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.
…rror: Event loop is closed"
Issue
Commit 1
Summary:
Fix RuntimeError: Event loop is closed in OpenAI client initialization by separating the HTTP/2 probe from production client creation. The probe thread previously returned the AsyncOpenAI client itself, leaving its SSL connections bound to a closed event loop. The production client is now created after the thread exits, in the caller's event loop.
Details
The HTTP/2 probe ran in a background thread with its own event loop, created an AsyncOpenAI client, and returned it directly. Closing the thread's event loop while the client still held open keep-alive SSL connections caused
RuntimeError: Event loop is closedwhenever the client was later used in the caller's (different) event loop.Bug Fix: Decouple probe from production client lifetime
HTTP/2 Fallback Logic
Commit 2
Summary
Fix two CI-only failures caused by environment variable bleed-through in the CI test pipeline: Docker containers receiving localhost as the OpenSearch hostname (instead of the opensearch service name), and the backend crashing with invalid literal for int() with base 10: '' due
to empty Langflow retry env vars being injected into the container.
Details
The GitHub Actions workflow sets OPENSEARCH_HOST=localhost as a step-level env var so the in-process pytest backend can reach OpenSearch via Docker port mapping. This bled into docker-compose, overriding the opensearch service-name default and breaking all OpenSearch calls from inside the backend and Langflow containers. Separately, LANGFLOW_KEY_RETRIES and LANGFLOW_KEY_RETRY_DELAY had no :-default fallbacks in docker-compose.yml, so when unset in CI they were injected as empty strings, causing int("") to raise ValueError inside get_langflow_api_key().
CI Configuration: Docker container startup
test-ci and test-ci-local Makefile targets, isolating it from the
OPENSEARCH_HOST=localhost value the surrounding CI shell sets for pytest
docker-compose.yml: Environment variable defaults
rather than an empty string that crashes int() in settings.py
defaults match the hardcoded fallbacks already in settings.py:227-228