Powiadomienia w czasie rzeczywistym (SSE)

2 min czytania

Powiadomienia w czasie rzeczywistym (SSE)

Subskrybuj kanały PostgreSQL NOTIFY za pomocą Server-Sent Events:

# Token Bearer (JWT lub token API)
curl -N "http://localhost:8080/db/my_database/sse?channels=orders,users" \
  -H "Authorization: Bearer $TOKEN"

# Bezpośrednie dane logowania (HTTP Basic Auth — GRANT … TO pgarachne nie jest wymagany)
curl -N "http://localhost:8080/db/my_database/sse?channels=orders,users" \
  -u "alice:secret"

Każda wiadomość jest w formacie JSON i zawiera nazwę kanału oraz payload:

{"channel":"orders","data":{"id":123,"status":"created"}}

Jeśli payload jest zwykłym tekstem, zostaje zapakowany jako string w polu data.

Kanały nie są ograniczone rolą

W przeciwieństwie do endpointów JSON-RPC i MCP, SSE nie stosuje SET LOCAL ROLE ani w żaden inny sposób nie sprawdza uprawnień uwierzytelnionej roli przed subskrypcją. PgArachne uwierzytelnia wywołującego (ważny JWT, token API lub bezpośrednie dane logowania do docelowej bazy danych), ale każdy uwierzytelniony wywołujący — niezależnie od tego, jakiej roli odpowiadają jego dane logowania — może zasubskrybować dowolny kanał NOTIFY i będzie otrzymywać wszystko, co jest w nim publikowane. Wynika to ze sposobu, w jaki zbudowany jest ten endpoint: wszyscy klienci SSE dla danej bazy danych współdzielą jedno połączenie LISTEN otwarte jako konto usługowe DB_USER, a sam PostgreSQL nie ma żadnego GRANTu na poziomie kanału, na który mógłby delegować uprawnienia — kanały LISTEN/NOTIFY nie są obiektami bazy danych.

Nie wysyłaj przez NOTIFY payloadów zawierających dane, których nie powinna widzieć każda uwierzytelniona rola. Jeśli potrzebujesz kontroli dostępu na poziomie kanału, zaimplementuj ją we własnej logice aplikacji (np. konwencje nazewnictwa kanałów zależne od roli lub filtrowanie zawartości payloadu) — PgArachne nie zrobi tego za Ciebie na tym endpointcie.

Wysyłanie powiadomień z PostgreSQL

Z psql lub innej sesji bazy danych:

-- Prosty tekstowy payload
NOTIFY orders, 'new order';

-- Payload JSON
NOTIFY orders, '{"id":123,"status":"created"}';

Z triggera lub procedury składowanej:

PERFORM pg_notify('orders', json_build_object('id', NEW.id, 'status', NEW.status)::text);
Uwaga: NOTIFY jest dostarczany do innych sesji tylko po zatwierdzeniu (commit) transakcji wysyłającej. Jeśli wykonasz je w otwartej transakcji w psql, subskrybenci nie otrzymają powiadomienia, dopóki nie wykonasz COMMIT.