Skip to content

[rhoai-2.25] fix(tests): bound exposing_contextmanager's portforward retry loop - #2691

Open
jiridanek wants to merge 4 commits into
rhoai-2.25from
fix/rhoai-2.25-socket-proxy-bounded-remote-timeout
Open

[rhoai-2.25] fix(tests): bound exposing_contextmanager's portforward retry loop#2691
jiridanek wants to merge 4 commits into
rhoai-2.25from
fix/rhoai-2.25-socket-proxy-bounded-remote-timeout

Conversation

@jiridanek

@jiridanek jiridanek commented Aug 2, 2026

Copy link
Copy Markdown
Member

Summary

Implements "Fix #2" from the suggested (not-yet-implemented) hardening ideas in
#2684: bound
exposing_contextmanager()'s kubernetes.stream.portforward() retry loop in
tests/containers/kubernetes_utils.py.

Why

exposing_contextmanager() retried portforward() in a
while not pf or not pf.connected or not s: loop with no deadline and no give-up
condition
. Verified via the kubernetes client library source
(kubernetes/stream/ws_client.py) that the underlying websocket.connect(...) call
has no per-call timeout plumbed through portforward()'s public API -- a single
iteration can, in principle, hang forever (e.g. a wedged connection to the API
server), not just retry quickly.

Because SocketProxy.listen_and_serve_until_canceled() handles one client
synchronously, a stuck call here blocks the entire proxy -- no other
Wait.until retry can ever be serviced again for that pod, with no way to
recover.

Empirical testing of the two other suggested fixes in #2684 (bigger listen()
backlog, dropping stale queued connections) showed they're no-ops for
Wait.until's actual serial access pattern -- see the
follow-up comment
for the methodology/results. Only this one addresses a real, currently-unmitigated
gap, so it's the only one implemented here.

Separately verified on a real cluster-less repro (remapped container port,
mimicking the port-forward host/pod port mismatch) that this change is orthogonal
to the RStudio /api regression fixed in #2685: that failure is an instant
(~2ms) client-side ConnectionError to the wrong hardcoded port, happening
after the portforward tunnel is already established -- outside this function's
code path entirely.

Changes

  • exposing_contextmanager() gains a timeout: float = 30 parameter (well under
    the outer Wait.until(..., TestFrameConstants.TIMEOUT_2MIN, ...) 120s budget at
    the only call site, so a give-up still leaves room for several fresh retries).
    Once exceeded, cleans up any partial s/pf and raises TimeoutError.
  • Incidental fix bundled in because the same loop is being touched: added
    s.close()/pf.close() cleanup between retry iterations. Previously each
    failed attempt leaked the prior PortForward/socket (this is already how
    opendatahub-io/notebooks:main's copy of this function behaves -- rhoai-2.25
    had fallen behind on just this point).
  • SocketProxy.listen_and_serve_until_canceled() now also catches the new
    TimeoutError alongside the existing BrokenPipeError/ConnectionResetError,
    so the proxy gives up on just that one connection and keeps serving future
    retries. Without this, the exception would escape to the outer
    except Exception handler and kill the whole proxy thread instead.

Verification

  • ast.parse, uv run ruff check, uv run pyright all clean on both files.
  • No dedicated unit tests exist for exposing_contextmanager/SocketProxy
    (confirmed via grep) -- real coverage is via the openshift-container-tests
    CI job added in fix(tests): probe / instead of /api for OpenShift port-forward readiness #2685, which exercises this exact code path. Treating its 5
    matrix legs going green as the real verification for this PR.

Rollout

Sequenced as one enhancement PR per branch, this one first: rhoai-2.25 (this
PR) → opendatahub-io/notebooks:mainrhoai-3.5, since this is also the only
branch with CI coverage of this code path today (tracked for main/rhoai-3.5
separately by opendatahub-io#4257).

Summary by CodeRabbit

  • Bug Fixes
    • Added timeout protection when establishing port-forward connections, preventing indefinite waits.
    • Failed or incomplete connections are now cleaned up before retrying.
    • Remote connection timeouts are handled gracefully, allowing client retries to continue.
    • Improved recovery from interrupted or failed socket connections.

exposing_contextmanager() retried kubernetes.stream.portforward() forever with
no deadline and no give-up condition. Because SocketProxy handles one client
synchronously, a single stuck iteration (e.g. a wedged connection to the API
server -- the kubernetes client doesn't expose a per-call connect timeout for
portforward()) blocks the entire proxy, starving every later Wait.until retry
with no way to recover.

Add a bounded deadline (default 30s, well under the outer Wait.until 120s
budget) that raises TimeoutError once exceeded, and catch it in
SocketProxy.listen_and_serve_until_canceled() alongside the existing
BrokenPipeError/ConnectionResetError handling so the proxy gives up on just
that one connection and keeps serving future retries instead of the exception
escaping to the outer handler and killing the whole proxy thread.

Also adds the s.close()/pf.close()-before-retry cleanup between iterations
(previously each failed attempt leaked the prior PortForward/socket).

#2684
@openshift-ci
openshift-ci Bot requested review from daniellutz and dibryant August 2, 2026 20:09
@openshift-ci

openshift-ci Bot commented Aug 2, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign jiridanek for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: ac75bf59-dbfd-4afc-a530-16c36e4c5bad

📥 Commits

Reviewing files that changed from the base of the PR and between 824c53a and e691e4a.

📒 Files selected for processing (2)
  • tests/containers/kubernetes_utils.py
  • tests/containers/socket_proxy.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/containers/socket_proxy.py
  • tests/containers/kubernetes_utils.py

📝 Walkthrough

Walkthrough

exposing_contextmanager now bounds Kubernetes port-forward setup with a configurable timeout, cleans up failed resources, and raises TimeoutError after the deadline. SocketProxy treats remote connection timeouts as recoverable and continues accepting retries.

Changes

Port-forward timeout handling

Layer / File(s) Summary
Bound port-forward establishment
tests/containers/kubernetes_utils.py
_portforward_with_timeout limits port-forward creation. exposing_contextmanager uses a shared deadline, cleans up failed resources, retries within the deadline, and raises TimeoutError after expiration.
Proxy timeout recovery
tests/containers/socket_proxy.py
SocketProxy.listen_and_serve_until_canceled catches and logs remote TimeoutError failures, then continues accepting client retries.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: dibryant, daniellutz

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the fix to the port-forward retry loop and matches the main change.
Description check ✅ Passed The description covers the change, rationale, implementation, verification, and rollout, but does not complete the repository checklists.
Linked Issues check ✅ Passed The linked issue has no substantive acceptance criteria, and the implementation matches the stated objective to bound port-forward retries.
Out of Scope Changes check ✅ Passed The changes are limited to port-forward timeout and cleanup handling and related proxy error recovery.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/rhoai-2.25-socket-proxy-bounded-remote-timeout

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Superseded by newer run: https://github.com/red-hat-data-services/notebooks/actions/runs/30765447068

CI status [antigravity]

Run: Build Notebooks (pr) #307649938982/2 complete · 1 passed · 1 skipped
Last updated: 2026-08-02T20:10:40Z

No workbench image jobs ran; all matrix jobs were skipped.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

📋 Review Summary

This PR successfully implements timeout and cleanup hardening for the Kubernetes port-forward retry loop in tests/containers/kubernetes_utils.py and graceful TimeoutError handling in tests/containers/socket_proxy.py. The approach of running the un-timed portforward call in a daemon helper thread and joining it with a deadline prevents infinite hangs while properly cleaning up leaked sockets and streams.

🔍 General Feedback

  • The timeout implementation using a daemon thread and join(timeout) is a robust workaround for the underlying kubernetes python client library lacking a per-call connect timeout.
  • Proper cleanup of previous PortForward and socket instances on retry iterations prevents resource leaks.

I have no inline comments to post, as the changes are clean, correct, and well-thought-out.

I did not post any inline review comments.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/containers/kubernetes_utils.py`:
- Around line 524-545: The port-forward retry loop can block inside
kubernetes.stream.portforward beyond its deadline. Update the connection setup
around pf and pf.socket in the existing loop to apply a cancellable or
per-connection WebSocket timeout, without modifying process-wide WebSocket
settings, and re-check the deadline after the attempt returns before accepting
the connection.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 099ce4af-2db3-4aed-84ed-6f1992b87747

📥 Commits

Reviewing files that changed from the base of the PR and between 1660240 and 51a0006.

📒 Files selected for processing (2)
  • tests/containers/kubernetes_utils.py
  • tests/containers/socket_proxy.py

Comment thread tests/containers/kubernetes_utils.py
The log message wrapping the caught exception said "likely due to service not
being ready", which was accurate for the pre-existing BrokenPipeError/
ConnectionResetError cases but not necessarily for the new TimeoutError (could
also mean a genuinely wedged portforward() call, not just a slow-starting
pod). Reworded to state what's actually always true instead: the proxy gives
up on this one connection and the client will retry.
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Superseded by newer run: https://github.com/red-hat-data-services/notebooks/actions/runs/30765449231

CI status [antigravity]

Run: Build Notebooks (push) #307654470682/2 complete · 2 skipped
Last updated: 2026-08-02T20:22:07Z

Workflow completed with skipped jobs.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Superseded by newer run: https://github.com/red-hat-data-services/notebooks/actions/runs/30765871047

CI status [antigravity]

Run: Build Notebooks (pr) #307654492312/2 complete · 1 passed · 1 skipped
Last updated: 2026-08-02T20:22:45Z

No workbench image jobs ran; all matrix jobs were skipped.

CodeRabbit correctly flagged that the deadline check only ran between retry
loop iterations: a single kubernetes.stream.portforward() call that itself
hangs (the primary scenario this fix targets, e.g. a wedged connection to the
API server) would never let the loop's own deadline check run again, silently
defeating the bound entirely.

The kubernetes client doesn't expose a per-call connect timeout for
portforward(), and a process-wide websocket.setdefaulttimeout() isn't safe
here (multiple SocketProxy instances can call portforward() concurrently from
different threads). Run the call in a helper thread and bound it with
join(timeout) instead, via a new _portforward_with_timeout() -- on timeout the
call is abandoned (thread/connection leaked for the remainder of the test
process) rather than joined, which is an acceptable tradeoff for test
infrastructure that's about to fail the test and exit soon after anyway.

Verified locally against three scenarios: a portforward() call that hangs
forever (previously: hung forever; now: bounded correctly), a pod that fails
fast repeatedly (still converges to the loop's own deadline as before), and
one that succeeds on a later retry (unaffected).
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Superseded by newer run: https://github.com/red-hat-data-services/notebooks/actions/runs/30765873737

CI status [antigravity]

Run: Build Notebooks (push) #307658710472/2 complete · 2 skipped
Last updated: 2026-08-02T20:33:09Z

Workflow completed with skipped jobs.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Superseded by newer run: https://github.com/red-hat-data-services/notebooks/actions/runs/30766140573

CI status [antigravity]

Run: Build Notebooks (pr) #307658737372/2 complete · 1 passed · 1 skipped
Last updated: 2026-08-02T20:33:45Z

No workbench image jobs ran; all matrix jobs were skipped.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/containers/kubernetes_utils.py`:
- Around line 508-524: Update _portforward_with_timeout so timed-out
port-forward attempts are eventually closed even when callers catch TimeoutError
and retry. Track the helper thread’s late result and close any returned
PortForward, and ensure the abandoned worker or connection has a bounded
lifetime rather than leaking across readiness retries.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a0e43088-22ce-4e99-ac43-1de564e18cec

📥 Commits

Reviewing files that changed from the base of the PR and between fb85a53 and 824c53a.

📒 Files selected for processing (1)
  • tests/containers/kubernetes_utils.py

Comment on lines +508 to +524
def _portforward_with_timeout(
core_v1_api: kubernetes.client.CoreV1Api, pod: kubernetes.client.models.V1Pod, timeout: float
) -> kubernetes.stream.ws_client.PortForward:
"""Runs kubernetes.stream.portforward() with a wall-clock bound.

The kubernetes client doesn't expose a per-call connect timeout for portforward() -- it calls
websocket.connect() with no timeout, so a wedged connection to the API server can hang this call
forever. The only alternative the library offers is a process-wide `websocket.setdefaulttimeout()`,
which isn't safe to use here since multiple SocketProxy instances (one per ImageDeployment) can be
making concurrent portforward() calls from different threads. So we run the call in a helper thread
and bound it with join(timeout) instead.

If the call doesn't return in time, it is abandoned rather than joined: the daemon thread and any
partially-established connection are leaked for the remainder of the test process. That's an
accepted tradeoff for test infrastructure that's about to raise TimeoutError and fail the test
(and the process will exit soon after) rather than hang forever with no recovery.
"""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo '--- callers of exposing_contextmanager and any outer retry (Wait.until) ---'
rg -n -C 5 'exposing_contextmanager|class Wait\b|def until\b' tests

echo '--- pytest fail-fast configuration (addopts, -x, maxfail) ---'
rg -n 'addopts|maxfail|-x\b' pyproject.toml pytest.ini tox.ini .github 2>/dev/null || true

Repository: red-hat-data-services/notebooks

Length of output: 5171


🏁 Script executed:

#!/bin/bash
set -euo pipefail
printf '%s\n' '--- Wait.until implementation ---'
sed -n '380,455p' tests/containers/kubernetes_utils.py
printf '%s\n' '--- exposing_contextmanager and timeout helper ---'
sed -n '500,595p' tests/containers/kubernetes_utils.py
printf '%s\n' '--- SocketProxy retry loop and cleanup ---'
sed -n '1,135p' tests/containers/socket_proxy.py
printf '%s\n' '--- pytest configuration and workflow invocations ---'
cat pytest.ini
rg -n -C 3 'pytest(\s|$)|pytest\.|make test|make[[:space:]]+test' Makefile .github tests 2>/dev/null | head -200

Repository: red-hat-data-services/notebooks

Length of output: 28040


🏁 Script executed:

#!/bin/bash
set -euo pipefail
printf '%s\n' '--- remainder of Wait.until ---'
sed -n '430,510p' tests/containers/kubernetes_utils.py
printf '%s\n' '--- all Wait.until call sites ---'
rg -n -C 8 'Wait\.until\(' tests
printf '%s\n' '--- ImageDeployment setup and lifecycle around SocketProxy ---'
sed -n '210,285p' tests/containers/kubernetes_utils.py
printf '%s\n' '--- SocketProxy callers and client retry references ---'
rg -n -C 8 'get_actual_port|listen_and_serve_until_canceled|cancellation_token|remote_socket_factory|Wait\.until' tests/containers

Repository: red-hat-data-services/notebooks

Length of output: 28122


🏁 Script executed:

#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from __future__ import annotations

import ast
from pathlib import Path

utils = Path("tests/containers/kubernetes_utils.py").read_text()
proxy = Path("tests/containers/socket_proxy.py").read_text()
pytest_ini = Path("pytest.ini").read_text()

u = ast.parse(utils)
p = ast.parse(proxy)

def calls(tree: ast.AST, name: str) -> list[int]:
    return [
        node.lineno
        for node in ast.walk(tree)
        if isinstance(node, ast.Call)
        and isinstance(node.func, ast.Attribute)
        and node.func.attr == name
    ]

wait_until_calls = calls(u, "until")
portforward_calls = [
    node.lineno
    for node in ast.walk(u)
    if isinstance(node, ast.Call)
    and isinstance(node.func, ast.Attribute)
    and node.func.attr == "portforward"
]
print(f"Wait.until call lines: {wait_until_calls}")
print(f"kubernetes.stream.portforward call lines: {portforward_calls}")
print(f"pytest fail-fast options present: {any(x in pytest_ini for x in ('-x', '--exitfirst', 'maxfail'))}")

for node in ast.walk(p):
    if isinstance(node, ast.Try):
        caught = [
            handler.type.names[0]
            for handler in node.handlers
            if isinstance(handler.type, ast.Tuple)
            for _ in [0]
        ]
        if any(isinstance(handler.type, ast.Name) and handler.type.id == "TimeoutError" for handler in node.handlers):
            print(f"SocketProxy catches TimeoutError at line {node.lineno}")
            print(f"  handler types: {caught or ['TimeoutError']}")
            print(f"  handler contains continue: {any(isinstance(x, ast.Continue) for h in node.handlers for x in ast.walk(h))}")

for node in ast.walk(u):
    if isinstance(node, ast.FunctionDef) and node.name == "_portforward_with_timeout":
        thread_starts = [
            n.lineno for n in ast.walk(node)
            if isinstance(n, ast.Call)
            and isinstance(n.func, ast.Attribute)
            and n.func.attr == "start"
        ]
        joins = [
            n.lineno for n in ast.walk(node)
            if isinstance(n, ast.Call)
            and isinstance(n.func, ast.Attribute)
            and n.func.attr == "join"
        ]
        raises = [
            n.lineno for n in ast.walk(node)
            if isinstance(n, ast.Raise)
        ]
        print(f"_portforward_with_timeout starts threads at: {thread_starts}")
        print(f"_portforward_with_timeout joins at: {joins}")
        print(f"_portforward_with_timeout raises at: {raises}")
PY

Repository: red-hat-data-services/notebooks

Length of output: 450


🏁 Script executed:

#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
import re

utils = Path("tests/containers/kubernetes_utils.py").read_text()
proxy = Path("tests/containers/socket_proxy.py").read_text()
pytest_ini = Path("pytest.ini").read_text()

print("Wait.until call count:", len(re.findall(r"\bWait\.until\s*\(", utils)))
print("portforward call count:", len(re.findall(r"\bkubernetes\.stream\.portforward\s*\(", utils)))
print("SocketProxy TimeoutError handling:", bool(re.search(
    r"except\s*\([^)]*\bTimeoutError\b[^)]*\).*?:.*?continue",
    proxy,
    re.S,
)))
print("pytest fail-fast option configured:", bool(re.search(
    r"(?m)^\s*(?:addopts\s*=.*(?:^|\s)(?:-x|--exitfirst)|(?:maxfail\s*=))",
    pytest_ini,
)))
print("helper starts daemon thread:", bool(re.search(
    r"thread\s*=\s*threading\.Thread\(.*daemon=True\).*?thread\.start\(\)",
    utils,
    re.S,
)))
print("helper joins without a later join:", bool(re.search(
    r"thread\.join\(timeout\).*?if not pf_result:.*?raise TimeoutError",
    utils,
    re.S,
)))
PY

Repository: red-hat-data-services/notebooks

Length of output: 376


Close abandoned port-forward attempts.

SocketProxy catches TimeoutError and continues serving clients, so the exception does not fail the test or end the pytest process. The readiness Wait.until retries for up to TIMEOUT_2MIN; each retry can leave a daemon thread or a late-returning, unclosed PortForward. Close abandoned results when they complete, or otherwise bound their lifetime.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/containers/kubernetes_utils.py` around lines 508 - 524, Update
_portforward_with_timeout so timed-out port-forward attempts are eventually
closed even when callers catch TimeoutError and retry. Track the helper thread’s
late result and close any returned PortForward, and ensure the abandoned worker
or connection has a bounded lifetime rather than leaking across readiness
retries.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Superseded by newer run: https://github.com/red-hat-data-services/notebooks/actions/runs/30766142345

CI status [antigravity]

Run: Build Notebooks (push) #307661405732/2 complete · 2 skipped
Last updated: 2026-08-02T20:40:43Z

Workflow completed with skipped jobs.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

CI status [antigravity]

Run: Build Notebooks (pr) #307661423452/2 complete · 1 passed · 1 skipped
Last updated: 2026-08-02T20:41:06Z

No workbench image jobs ran; all matrix jobs were skipped.

ysok pushed a commit to ysok-opendatahub-io/notebooks that referenced this pull request Aug 3, 2026
exposing_contextmanager() retried kubernetes.stream.portforward() forever with
no deadline and no give-up condition. Because SocketProxy handles one client
synchronously, a single stuck iteration (e.g. a wedged connection to the API
server -- the kubernetes client doesn't expose a per-call connect timeout for
portforward()) blocks the entire proxy, starving every later Wait.until retry
with no way to recover.

Add a bounded deadline (default 30s) that raises TimeoutError once exceeded,
and catch it in SocketProxy.listen_and_serve_until_canceled() alongside the
existing BrokenPipeError/ConnectionResetError handling so the proxy gives up
on just that one connection and keeps serving future retries instead of the
exception escaping to the outer handler and killing the whole proxy thread.

The deadline check alone only runs between retry loop iterations, so a single
portforward() call that itself hangs would never let it fire again -- bound
that specific call too via a new _portforward_with_timeout() helper, which
runs it in a daemon thread bounded by join(timeout). On timeout the call is
abandoned (thread/connection leaked for the remainder of the test process)
rather than joined; deliberately not using a process-wide
websocket.setdefaulttimeout() since multiple SocketProxy instances can call
portforward() concurrently from different threads.

Straight port of red-hat-data-services#2691 (rhoai-2.25), where this
was implemented and CI-verified first (openshift-container-tests job exercises
this exact code path there; no equivalent job exists on main yet, tracked by
opendatahub-io#4257).

red-hat-data-services#2684
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant