-- Test: audience-bound subscriptions (finding F1, 0.1.2) CREATE EXTENSION pg_reactive; CREATE TABLE inv (id serial PRIMARY KEY, player_id text, val int); INSERT INTO inv (player_id, val) VALUES ('42', 100), ('99', 200); -- 1. Subscribe without audience (legacy public). audience is NULL. SELECT pgr.subscribe('aud_pub', 'SELECT id, val FROM inv'); subscribe ------------------------------------------------------------------------------- {"mode": "delta", "status": "subscribed", "tables": 1, "query_id": "aud_pub"} (1 row) SELECT query_id, audience FROM pgr.get_subscriptions() WHERE query_id = 'aud_pub'; query_id | audience ----------+---------- aud_pub | (1 row) -- 2. Subscribe with single-key audience {"sub":"42"}. SELECT pgr.subscribe( 'aud_42', 'SELECT id, val FROM inv WHERE player_id = ''42''', 'delta', '{"sub":"42"}'::jsonb); subscribe ------------------------------------------------------------------------------ {"mode": "delta", "status": "subscribed", "tables": 1, "query_id": "aud_42"} (1 row) SELECT query_id, audience FROM pgr.get_subscriptions() WHERE query_id = 'aud_42'; query_id | audience ----------+--------------- aud_42 | {"sub": "42"} (1 row) -- 3. Subscribe with multi-key audience. SELECT pgr.subscribe( 'aud_multi', 'SELECT id, val FROM inv', 'delta', '{"sub":"42","org":"acme"}'::jsonb); subscribe --------------------------------------------------------------------------------- {"mode": "delta", "status": "subscribed", "tables": 1, "query_id": "aud_multi"} (1 row) SELECT query_id, audience FROM pgr.get_subscriptions() WHERE query_id = 'aud_multi'; query_id | audience -----------+------------------------------ aud_multi | {"org": "acme", "sub": "42"} (1 row) -- 4. Notify-mode with audience also works. SELECT pgr.subscribe( 'aud_notify', 'SELECT id FROM inv', 'notify', '{"role":"admin"}'::jsonb); subscribe ----------------------------------------------------------------------------------- {"mode": "notify", "status": "subscribed", "tables": 1, "query_id": "aud_notify"} (1 row) SELECT query_id, mode, audience FROM pgr.get_subscriptions() WHERE query_id = 'aud_notify'; query_id | mode | audience ------------+--------+------------------- aud_notify | notify | {"role": "admin"} (1 row) -- 5. Re-subscribe with different audience updates in place (entry reuse). SELECT pgr.subscribe( 'aud_42', 'SELECT id, val FROM inv WHERE player_id = ''42''', 'delta', '{"sub":"99"}'::jsonb); subscribe ------------------------------------------------------------------------------ {"mode": "delta", "status": "subscribed", "tables": 1, "query_id": "aud_42"} (1 row) SELECT query_id, audience FROM pgr.get_subscriptions() WHERE query_id = 'aud_42'; query_id | audience ----------+--------------- aud_42 | {"sub": "99"} (1 row) -- 6. Audience too long is rejected (>512 bytes). SELECT pgr.subscribe( 'aud_huge', 'SELECT id FROM inv', 'delta', ('{"k":"' || repeat('x', 600) || '"}')::jsonb); ERROR: audience too long (609 bytes, max 511) HINT: audience must be a small JSON object of claim predicates. CONTEXT: PL/pgSQL function pgr.subscribe(text,text,text,jsonb) line 13 at assignment -- 7. List all subscriptions sorted. SELECT query_id, mode, audience FROM pgr.get_subscriptions() ORDER BY query_id; query_id | mode | audience ------------+--------+------------------------------ aud_42 | delta | {"sub": "99"} aud_multi | delta | {"org": "acme", "sub": "42"} aud_notify | notify | {"role": "admin"} aud_pub | delta | (4 rows) -- 8. Unsubscribe each. SELECT pgr.unsubscribe('aud_pub'); unsubscribe ------------- t (1 row) SELECT pgr.unsubscribe('aud_42'); unsubscribe ------------- t (1 row) SELECT pgr.unsubscribe('aud_multi'); unsubscribe ------------- t (1 row) SELECT pgr.unsubscribe('aud_notify'); unsubscribe ------------- t (1 row) -- Cleanup. DROP TABLE inv; DROP EXTENSION pg_reactive;