Repository navigation
REST: rest.client.* timeouts are ignored when rest.sigv4-enabled is set聽#4076
Description
Apache Iceberg version
main (development)
Please describe the bug 馃悶
rest.client.connection-timeout-ms and rest.client.socket-timeout-ms (added in #3418, not released yet) have no effect when rest.sigv4-enabled is set, so a catalog request to AWS (S3 Tables, Glue REST) can still wait forever for a response.
_create_session mounts the timeout adapter on http:// and https://, then _init_sigv4 mounts SigV4Adapter on self.uri. requests picks the adapter with the longest matching prefix, so every catalog request goes through SigV4Adapter, which is a plain HTTPAdapter and never sets a timeout. The code already says so in a comment (L577-L581, L1148), and the docs don't mention the limitation.
Repro with a local server that answers after 8 s and a 2 s timeout (fake credentials are enough, since the request is signed locally):
import threading, time
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pyiceberg.catalog.rest import RestCatalog
class Slow(BaseHTTPRequestHandler):
def do_GET(self):
time.sleep(8)
body = b'{"defaults": {}, "overrides": {}}'
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
server = ThreadingHTTPServer(("127.0.0.1", 0), Slow)
threading.Thread(target=server.serve_forever, daemon=True).start()
base = {
"uri": f"http://127.0.0.1:{server.server_port}",
"rest.client.connection-timeout-ms": "1000",
"rest.client.socket-timeout-ms": "1000",
}
sigv4 = {
"rest.sigv4-enabled": "true",
"rest.signing-region": "eu-west-1",
"rest.signing-name": "s3tables",
"client.access-key-id": "AKIAEXAMPLE",
"client.secret-access-key": "secret",
"client.region": "eu-west-1",
}
for label, props in [("without SigV4", base), ("with SigV4", {**base, **sigv4})]:
start = time.monotonic()
try:
RestCatalog("t", **props)
outcome = "response received"
except Exception as e:
outcome = type(e).__name__
print(f"{label}: {outcome} after {time.monotonic() - start:.1f} s")without SigV4: ConnectionError after 2.0 s
with SigV4: response received after 8.1 s
I ran into this while looking at #2512, where a delete on S3 Tables through the REST catalog is reported to hang. I can't tell yet whether that hang comes from a missing timeout, but on 0.10 there was no way to set one, and on main the new setting doesn't reach SigV4 users.
The fix I have in mind is small: make SigV4Adapter extend _RetryTimeoutHTTPAdapter and pass it the same timeout, keeping rest.sigv4.max-retries for its retries. With that change the repro above times out with SigV4 too. Since SigV4Adapter retries 10 times by default with no backoff, a GET then waits up to 11 times the timeout before failing, which is the retry problem tracked in #3008.
#3120 rewrites SigV4 signing and replaces SigV4Adapter with a plain HTTPAdapter(max_retries=...) on the catalog URI, so the timeout would still be skipped there. I'm happy to align with it if that PR lands first.
Willingness to contribute
- I can contribute a fix for this bug independently
- I would be willing to contribute a fix for this bug with guidance from the Iceberg community
- I cannot contribute a fix for this bug at this time
Activity