mirror of
https://github.com/nearai/ironclaw.git
synced 2026-09-03 08:06:01 +08:00
* Add hosted single-tenant Postgres profile * Persist hosted extension state under tenant storage * fix(reborn): bound filesystem event tail reads * fix(reborn): reduce hosted postgres read amplification * fix(reborn): batch filesystem thread history reads * fix(filesystem): avoid postgres prefix scans * fix(reborn): harden hosted postgres bootstrap * fix(webui): advance empty projection cursors * fix(reborn): batch llm secret metadata reads * perf(webui): back off idle stream polling * perf(turns): cache fresh filesystem snapshots for reads * fix(reborn): authorize extension lifecycle catalog mounts * fix(reborn): time out wedged turn drivers * fix(reborn): bound stuck heartbeat calls * refactor: split postgres PR hot path helpers * reborn: address hosted postgres review feedback * turns: move test module after production items * reborn: fix hosted postgres review feedback * reborn: fix projection ci regressions * tests: relax reborn harness heartbeat * tests: widen reborn harness heartbeat * ci: harden cargo network fetches * reborn: fix hosted runtime gate diagnostic * tests: wait for budget gate materialization * reborn: fix hosted postgres review and ci issues * reborn: tighten hosted postgres review fixes * reborn: keep nearai bootstrap outcome local * reborn: clarify hosted local-runtime seams * fix(reborn): address CodeRabbit review feedback (#5081) * test(reborn): stabilize runtime no-gateway failure check * fix(ci): update test secret metadata expiry plumbing * fix(threads): make postgres message acceptance atomic * fix(filesystem): retry postgres migration connect * fix(reborn): lower default postgres pool size * fix(reborn): allow postgres pool cap override * fix(filesystem): extend postgres startup retry window * fix(railway): disable reborn deployment overlap * fix(reborn): serve startup health before postgres runtime * fix(reborn): harden startup and inbound accept paths * fix(ci): restore reborn bootstrap build * fix(ci): stabilize reborn harness heartbeat * fix(reborn): collapse repeated auto-approve lookups * fix(reborn): suppress noisy debug logs in hosted serve * fix(reborn): raise hosted-single-tenant postgres pool to 16 The hosted profile shared a single deadpool across every Postgres-backed subsystem (turns, threads, messages, events, secrets), and every filesystem op checks out a connection. With pool_max_size=2 a single turn's reads plus an open transaction monopolize both connections, so the runner heartbeat and webui block indefinitely on pool.get() (no get() timeout), the 90s lease expires, and the turn wedges with failure_category=lease_expired. The cap was lowered to fit a managed session-pool limit during blue-green deploy overlap; that overlap is resolved, so restore a healthy pool (16, the prior default). Runtime override via IRONCLAW_REBORN_POSTGRES_POOL_MAX_SIZE is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * perf(reborn): cache prepared statements + bound postgres pool checkout Two latency/deadlock fixes for the Postgres-backed root filesystem, which backs every Reborn subsystem (turns, threads, messages, events, secrets) and checks out a pooled connection per op. Caching: every fixed-SQL read/write went through `client.query_opt(sql, ..)` with a string, so tokio_postgres issued a fresh `Parse` (prepare) on every call — ~2.77ms RTT to remote Postgres measured from production logs, ~48% of each read, and a monotonically growing set of server-side prepared statements (s1625, s1626, ... never reused). Route the deadpool `Object` (not the deref'd `Client`) through new `cached_query_opt`/`cached_query`/ `cached_query_one`/`cached_execute` helpers that use deadpool's per-connection `prepare_cached`. The Parse round-trip is now paid once per connection per distinct statement; the pooled connection is held for ~half as long per op, which is what relieves the pool contention behind the lease-expiry wedge. Dynamic SQL (filter `query`, index DDL, create_dir_all's txn) stays uncached to keep the cache bounded. Helpers return `tokio_postgres::Error` so existing `db_error` mapping at call sites is unchanged. Deadlock guard: the pool was built with no checkout timeout, so `Pool::get()` blocks forever once all connections are busy — an unbounded wait wedges the runner heartbeat and webui until the 90s lease expires. Add 30s wait/create/recycle timeouts (well under the lease) so a saturated pool surfaces a retryable error instead of hanging the process. Verified: `cargo clippy` clean and `cargo check` pass for ironclaw_filesystem, ironclaw_reborn_event_store, and ironclaw_reborn_composition with postgres[,webui-v2-beta]. Live Postgres behavior + latency delta verified via PR CI and Railway (no local live-pg test / Docker). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(reborn): size hosted postgres pool for the Supabase pooler (10) The reference hosted deployment fronts Postgres with the Supabase Supavisor session pooler (default pool size ~15), so the shared app pool must stay under that cap. 16 could exceed it; 10 covers runtime concurrency (heartbeat, webui, trigger poller, turn driver reads + open txn) with headroom for migrations and admin sessions. Runtime override IRONCLAW_REBORN_POSTGRES_POOL_MAX_SIZE still wins over this file. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
47 lines
1.7 KiB
SQL
47 lines
1.7 KiB
SQL
-- Use bytewise ordering for virtual filesystem paths.
|
|
--
|
|
-- The Postgres backend uses half-open path ranges (`path >= prefix AND
|
|
-- path < next_prefix`) for prefix scans. Those ranges are only stable across
|
|
-- locales when the stored path column uses the C collation.
|
|
--
|
|
-- Rollback plan:
|
|
-- 1. Stop writers that depend on bytewise path range semantics.
|
|
-- 2. Revert both path columns to the database default collation:
|
|
-- ALTER TABLE root_filesystem_entries
|
|
-- ALTER COLUMN path TYPE TEXT COLLATE "default";
|
|
-- ALTER TABLE root_filesystem_events
|
|
-- ALTER COLUMN path TYPE TEXT COLLATE "default";
|
|
-- 3. Recreate any dependent path indexes if PostgreSQL reports they were
|
|
-- rebuilt or invalidated during the ALTER COLUMN TYPE operation.
|
|
|
|
DO $$
|
|
BEGIN
|
|
IF to_regclass('root_filesystem_entries') IS NOT NULL
|
|
AND EXISTS (
|
|
SELECT 1
|
|
FROM pg_attribute
|
|
WHERE attrelid = to_regclass('root_filesystem_entries')
|
|
AND attname = 'path'
|
|
AND NOT attisdropped
|
|
AND attcollation <> 'pg_catalog."C"'::regcollation
|
|
)
|
|
THEN
|
|
ALTER TABLE root_filesystem_entries
|
|
ALTER COLUMN path TYPE TEXT COLLATE "C";
|
|
END IF;
|
|
|
|
IF to_regclass('root_filesystem_events') IS NOT NULL
|
|
AND EXISTS (
|
|
SELECT 1
|
|
FROM pg_attribute
|
|
WHERE attrelid = to_regclass('root_filesystem_events')
|
|
AND attname = 'path'
|
|
AND NOT attisdropped
|
|
AND attcollation <> 'pg_catalog."C"'::regcollation
|
|
)
|
|
THEN
|
|
ALTER TABLE root_filesystem_events
|
|
ALTER COLUMN path TYPE TEXT COLLATE "C";
|
|
END IF;
|
|
END $$;
|