Tablet 50: a socket reply is one line, however long — and a failed retry closes its socket
Both Unix-socket clients (Korban Processor, Talmudic Engine) read a reply with a single :gen_tcp.recv/3, which returns at most one receive buffer — 1460 bytes, measured — whatever the packet mode. A bedikah of forty claims answered in 18 KB: the client decoded the first 1460 bytes, failed, reconnected, failed again, and returned an error with the retry's socket still open. The single-threaded Korban Processor then sat on that dead conversation and every later bedikah, however small, timed out at 15 s. Live, for every caller, from the first long output. Clients now read until the newline (recv_line/2, 16 MiB ceiling) in raw mode, and close the retry's socket on failure. The Korban Processor drops a connection that says nothing for 120 s, so one stuck client can no longer hold the door. tablet50_socket_line_test stands up a 60 KB-line server and asks both clients. Elixir 552/0 (L3 on and off), korban 280. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
1c387820d3
commit
b8522ea098
4 files changed
+159
-6
No files matched your search
@@ -35,6 +35,7 @@ from korban_processor.bedikah import examine
|
||||
from korban_processor.korban import Provenance
|
||||
|
||||
DEFAULT_SOCKET_PATH = "/tmp/shorashim/korban.sock"
|
||||
IDLE_SECONDS = 120.0 # a client that says nothing for this long is dropped (tablet 50)
|
||||
|
||||
|
||||
def handle_request(line: str) -> dict:
|
||||
@@ -84,6 +85,10 @@ def handle_request(line: str) -> dict:
|
||||
|
||||
|
||||
def _serve_connection(conn: socket.socket) -> None:
|
||||
# One reader at a time means one stuck reader stops everyone (tablet
|
||||
# 50: a client that left a connection open held the door for every
|
||||
# later caller). A conversation that goes quiet is closed.
|
||||
conn.settimeout(IDLE_SECONDS)
|
||||
with conn, conn.makefile("rb") as reader, conn.makefile("wb") as writer:
|
||||
for raw in reader:
|
||||
line = raw.decode("utf-8", errors="replace").strip()
|
||||
@@ -117,7 +122,7 @@ def serve(socket_path: str = DEFAULT_SOCKET_PATH, stop: Optional[threading.Event
|
||||
continue
|
||||
try:
|
||||
_serve_connection(conn)
|
||||
except (BrokenPipeError, ConnectionResetError):
|
||||
except (BrokenPipeError, ConnectionResetError, socket.timeout, TimeoutError):
|
||||
pass
|
||||
finally:
|
||||
server.close()
|
||||
|
||||
Reference in new issue
Block a user