You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -51,6 +52,7 @@ Always get Arrow types from the library's `get_schema()` during discovery — th
51
52
- Cache invalidation: `engine_cache.invalidate(name)` after catalog operations (keeps shared pool). `engine_cache.invalidate_all(name)` after datasource edit/delete (removes pool too). Never swap these — see README § Performance.
52
53
- Discovery jobs: one active job per datasource enforced by `JobStore.active_by_ds`; cancellation via `CancellationToken` passed through all `DiscoveryProvider` methods
53
54
- Catalog UUID v5 key format: `"{parent_uuid}:{child_name}"` — same natural key → same ID → re-discovery is a safe upsert
55
+
- Idle timeout: `process_socket_with_idle_timeout` in `server.rs` replaces `pgwire::tokio::process_socket`. Env var `BR_IDLE_TIMEOUT_SECS` (default 900). Tests use `tokio::time::pause()` + `advance()` — do not add real `sleep()` calls in server tests.
54
56
55
57
## Pre-commit Hook
56
58
A `.githooks/pre-commit` script runs `cargo fmt --check` and `cargo clippy -p proxy -- -D warnings`. Enable it once per clone:
@@ -210,6 +211,7 @@ cargo run -p proxy -- user create --username alice --password secret --tenant ac
210
211
|`BR_ADMIN_USER`|`admin`| Auto-seed username |
211
212
|`BR_ADMIN_PASSWORD`|*(required on first boot)*| Auto-seed password. **Must be set** when no users exist in DB. |
212
213
|`BR_ADMIN_TENANT`|`default`| Auto-seed tenant |
214
+
|`BR_IDLE_TIMEOUT_SECS`|`900` (15 min) | Close pgwire connections that receive no messages for this many seconds. Enables Fly.io `auto_stop_machines` to work correctly with GUI clients (e.g. TablePlus) that hold idle connections indefinitely. Set to `0` to disable (not recommended on Fly.io). |
213
215
|`BR_CORS_ALLOWED_ORIGINS`|*(empty, same-origin only)*| Comma-separated list of allowed CORS origins for the Admin API |
@@ -225,6 +227,19 @@ Data sources are configured via the Admin UI (`/datasources`) or REST API — no
225
227
226
228
## Performance
227
229
230
+
### Idle Connection Timeout
231
+
232
+
pgwire 0.38 has no built-in idle timeout — `socket.next().await` blocks indefinitely after authentication. This prevents Fly.io `auto_stop_machines` from ever triggering when a GUI client like TablePlus is open, because the VM only stops when it has zero connections.
233
+
234
+
`proxy/src/server.rs` replaces pgwire's `process_socket` with a custom message loop (`process_socket_with_idle_timeout`) that adds a `tokio::select!` branch racing each `socket.next()` against a `sleep(idle_timeout)`. The timer resets after every received message — a running query does not count as idle.
235
+
236
+
Default timeout is 15 minutes (`BR_IDLE_TIMEOUT_SECS=900`). TCP keepalive (60 s time, 10 s interval) is also set on each accepted socket to detect dead connections from crashed clients or network failures.
237
+
238
+
When idle timeout fires, a log line is emitted at `INFO` level:
239
+
```
240
+
Idle connection timed out after 900s
241
+
```
242
+
228
243
### Arrow Type Alignment (query time)
229
244
230
245
During catalog discovery, column types are captured using `datafusion-table-providers`' own `get_schema()` function rather than a manual PG-to-Arrow mapping. This guarantees that the stored schema matches exactly what the library produces at query time.
0 commit comments