Skip to content

Commit a8b885b

Browse files
rustyconoverclaude
andcommitted
fix(windows): drive-letter worker refs, win32 mypy guards, client read timeout
- serve: a bare 'C:\path\worker.py' reference split at the drive-letter colon and tried to import module 'C'; only treat ':' as the module:Class separator when the head isn't a lone drive letter. - Guard AF_UNIX (transactor), SIGKILL (crash fixture), and getpgrp (schema_reconcile db path) behind sys.platform for Windows mypy, with Windows-appropriate fallbacks. - Client: httpx's 5s default read timeout is too aggressive for RPC calls that do real server-side work; use 60s read / 10s connect. (Fixes resumable-scan flakiness on slow Windows runners.) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 6925f65 commit a8b885b

5 files changed

Lines changed: 25 additions & 4 deletions

File tree

‎vgi/_test_fixtures/schema_reconcile/worker.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import os
2929
import pickle
3030
import sqlite3
31+
import sys
3132
import threading
3233
from dataclasses import dataclass
3334
from typing import Any
@@ -185,6 +186,11 @@ def _db_path() -> str:
185186
# because ``uv run`` inserts an intermediate process per worker; PGID
186187
# propagates across fork/exec by default and stays stable for the
187188
# life of one test session.
189+
if sys.platform == "win32": # pragma: no cover - PGID is POSIX; PPID is the
190+
# closest stable-per-session stand-in.
191+
import tempfile
192+
193+
return os.path.join(tempfile.gettempdir(), f"vgi_schema_reconcile.{os.getppid()}.sqlite")
188194
return f"/tmp/vgi_schema_reconcile.{os.getpgrp()}.sqlite"
189195

190196

‎vgi/_test_fixtures/table_in_out.py‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
import os
4040
import signal
41+
import sys
4142
import time
4243
from dataclasses import dataclass
4344
from typing import Annotated, Any
@@ -945,7 +946,10 @@ def process(
945946
batch: pa.RecordBatch,
946947
params: TableBufferingParams[SingleTableArguments],
947948
) -> bytes:
948-
os.kill(os.getpid(), signal.SIGKILL)
949+
if sys.platform == "win32": # pragma: no cover - hard-crash equivalent
950+
os.kill(os.getpid(), signal.SIGABRT)
951+
else:
952+
os.kill(os.getpid(), signal.SIGKILL)
949953
return params.execution_id # unreachable
950954

951955

‎vgi/client/client.py‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@
7171
import logging
7272
import os
7373
import shlex
74-
import sys
7574
import subprocess
75+
import sys
7676
import threading
7777
from collections.abc import Callable, Generator, Iterator
7878
from contextlib import AbstractContextManager
@@ -616,6 +616,9 @@ def _get_or_create_httpx_client(self) -> Any:
616616
base_url=self._base_url or "",
617617
follow_redirects=True,
618618
headers=headers,
619+
# httpx's 5s default read timeout is too aggressive for RPC
620+
# calls that do real server-side work (scans, cold workers).
621+
timeout=httpx.Timeout(60.0, connect=10.0),
619622
)
620623
self._httpx_client_owned = True
621624
return self._httpx_client

‎vgi/serve.py‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,11 @@ def load_worker_class(reference: str) -> type[Worker]:
8383
module_ref: str = reference
8484

8585
if ":" in reference:
86-
module_ref, class_name = reference.rsplit(":", 1)
86+
head, tail = reference.rsplit(":", 1)
87+
# A lone Windows drive-letter colon ("C:\path\worker.py") is part
88+
# of the path, not a module:Class separator.
89+
if not (len(head) == 1 and head.isalpha() and tail[:1] in ("\\", "/")):
90+
module_ref, class_name = head, tail
8791

8892
# Load the module
8993
module = _load_module(module_ref)

‎vgi/transactor/client.py‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import logging
2626
import os
2727
import subprocess
28+
import sys
2829
import time
2930
from pathlib import Path
3031
from typing import Any
@@ -81,14 +82,17 @@ def _try_connect(self) -> bool:
8182
"""Try to connect to an existing transactor socket."""
8283
import socket
8384

85+
if sys.platform == "win32": # pragma: no cover - AF_UNIX transactor is POSIX-only
86+
return False
87+
8488
if not os.path.exists(self._socket_path):
8589
return False
8690

8791
try:
8892
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
8993
sock.connect(self._socket_path)
9094
self._transport = UnixTransport(sock)
91-
self._connection = RpcConnection(TransactorProtocol, self._transport) # type: ignore[type-abstract]
95+
self._connection = RpcConnection(TransactorProtocol, self._transport) # type: ignore[type-abstract, unused-ignore]
9296
self._proxy = self._connection.__enter__()
9397
logger.info("Connected to transactor: %s", self._socket_path)
9498
return True

0 commit comments

Comments
 (0)