SPB Git

spb/findata

Public

raise open-file limit for wide scans; date-only SQL scopes use the catalog too

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed (Nov 2, 2026) parent 6665d8e Browse files

2 changed files +11 −4

modified infra/scripts/run-under-sshd.sh +1 −1
@@ -26,7 +26,7 @@ if [ -f "$PIDFILE" ]; then
26 fi 26 fi
27 fi 27 fi
28 CMD=$(printf '%q ' "$@") 28 CMD=$(printf '%q ' "$@")
29−"${SSH[@]}" "cd $(printf '%q' "$WORKDIR") && export PATH=$REMOTE_PATH FINDATA_ROOT=$(printf '%q' "$WORKDIR") PYTHONUNBUFFERED=1 && echo \$\$ > $(printf '%q' "$PIDFILE") && exec $CMD" & 29+"${SSH[@]}" "ulimit -n 65536 2>/dev/null; cd $(printf '%q' "$WORKDIR") && export PATH=$REMOTE_PATH FINDATA_ROOT=$(printf '%q' "$WORKDIR") PYTHONUNBUFFERED=1 && echo \$\$ > $(printf '%q' "$PIDFILE") && exec $CMD" &
30 SSHPID=$! 30 SSHPID=$!
31 stop() { 31 stop() {
32 REMOTE=$(cat "$PIDFILE" 2>/dev/null) 32 REMOTE=$(cat "$PIDFILE" 2>/dev/null)
modified services/ingest/src/findata_ingest/reader.py +10 −3
@@ -21,6 +21,13 @@ from findata_ingest.lake import Lake, live_files
21 21
22 22
23 def _con(read_only: bool = True) -> duckdb.DuckDBPyConnection: 23 def _con(read_only: bool = True) -> duckdb.DuckDBPyConnection:
24+ import resource
25+ try: # scans over many Parquet files need file descriptors (macOS default soft limit is 256)
26+ soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
27+ if soft < 65536:
28+ resource.setrlimit(resource.RLIMIT_NOFILE, (min(65536, hard), hard))
29+ except (ValueError, OSError):
30+ pass
24 con = duckdb.connect(database=":memory:", config={"threads": 4, "memory_limit": "4GB", "TimeZone": "UTC"}) 31 con = duckdb.connect(database=":memory:", config={"threads": 4, "memory_limit": "4GB", "TimeZone": "UTC"})
25 return con 32 return con
26 33
@@ -243,12 +250,12 @@ def extract_scope(sql: str) -> dict[str, Any]:
243 250
244 def scoped_view_sql(dataset_id: str, kind: str, scope: dict[str, Any], lake: Lake) -> str | None: 251 def scoped_view_sql(dataset_id: str, kind: str, scope: dict[str, Any], lake: Lake) -> str | None:
245 """Explicit file list from the catalog for symbol-scoped statements (fast path). None → use the glob view.""" 252 """Explicit file list from the catalog for symbol-scoped statements (fast path). None → use the glob view."""
246− if not scope["symbols"]: 253+ if not scope["symbols"] and not (scope["start"] or scope["end"]):
247 return None 254 return None
248 with connection() as conn: 255 with connection() as conn:
249− files = live_files(conn, dataset_id, scope["symbols"], scope["start"], scope["end"]) 256+ files = live_files(conn, dataset_id, scope["symbols"] or None, scope["start"], scope["end"])
250 if len(files) > 20000: 257 if len(files) > 20000:
251− return None 258+ return None # too broad for an explicit list: directory scan instead
252 if not files: 259 if not files:
253 return "SELECT * FROM (VALUES (NULL)) t(empty) WHERE false" 260 return "SELECT * FROM (VALUES (NULL)) t(empty) WHERE false"
254 lst = ", ".join("'" + str(lake.resolve(f["path"])).replace("'", "''") + "'" for f in files) 261 lst = ", ".join("'" + str(lake.resolve(f["path"])).replace("'", "''") + "'" for f in files)
255 262
Menu

Theme