-- Channel TTL refresh (keep in sync with migrations/0024). Runs deferred, in -- the transaction that makes a channel-scoped event durable, so a TTL -- transition committed while ingest was in flight is never missed. The -- per-channel advisory lock is SHARED here — permanent-channel commits admit -- each other — and taken EXCLUSIVE by TTL transitions (update_channel in -- crates/buzz-db/src/channel.rs), which forces the same total order the -- 0022 row lock provided without serializing the hot path. CREATE FUNCTION refresh_channel_ttl_after_event_insert() RETURNS trigger LANGUAGE plpgsql AS $$ DECLARE channel_ttl INTEGER; BEGIN -- Kind 9007 creates the channel and initializes its deadline itself. IF NEW.channel_id IS NOT NULL AND NEW.kind <> 9007 THEN BEGIN PERFORM pg_advisory_xact_lock_shared(hashtextextended( 'buzz_channel_ttl:' || NEW.community_id::text || ':' || NEW.channel_id::text, 0)); SELECT ttl_seconds INTO channel_ttl FROM channels WHERE community_id = NEW.community_id AND id = NEW.channel_id; IF channel_ttl IS NOT NULL THEN UPDATE channels SET ttl_deadline = clock_timestamp() + make_interval(secs => ttl_seconds) WHERE community_id = NEW.community_id AND id = NEW.channel_id AND ttl_seconds IS NOT NULL AND archived_at IS NULL AND deleted_at IS NULL; END IF; EXCEPTION WHEN OTHERS THEN -- Preserve the existing best-effort contract: a TTL refresh failure -- must not reject an otherwise valid durable event. RAISE WARNING 'channel TTL refresh failed for community %, channel %: %', NEW.community_id, NEW.channel_id, SQLERRM; END; END IF; RETURN NULL; END $$;