Feature request: live: allow pausing the notify triggers during bulk writes (e.g. pglite-sync applies) and refresh once on resume
I maintainer di solito rispondono entro 1 giorno
@tdrz ci sta già lavorando.
Dal 2/11/2026.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 25/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Stack tecnologico
- postgresql, typescript
- Ambito
- databases
Direzione di ricerca
Start with addNotifyTriggersToTables() in packages/pglite/src/live/index.ts, where the generated _notify_ trigger function body is created, and read the setup comment about triggers being added but never removed. Before any code, the open question is design: whether a GUC check, live.pause()/live.resume(), or both should be adopted, which the maintainers have not yet answered. Done means a maintainer-agreed design and tests showing that a bulk write with notifications suspended emits no notify, with one refresh on resume.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
This was prepared by my AI tools (GLM 5.3, refined by Claude Fable 5.1). Applying it solved my performance issue but I must admit I could not have done this myself. So make of it what you want. I hope it helps others but also that I'm not spamming you with garbage.
Summary
The live extension's notify triggers fire unconditionally, so during bulk writes — in particular @electric-sql/pglite-sync applying a shape snapshot — every mounted live query re-runs back-to-back for the entire duration of the write. A supported way to pause notifications (and refresh once on resume) would remove this.
Current behaviour
addNotifyTriggersToTables() in packages/pglite/src/live/index.ts creates, per table a live query depends on, one function _notify_<schema_oid>_<table_oid>() that does PERFORM pg_notify('table_change__…', ''), attached as an AFTER INSERT OR UPDATE OR DELETE … FOR EACH STATEMENT trigger. There is no condition under which it stays silent. (As the comment in setup notes, the triggers are only ever added, never removed; tableNotifyTriggersAdded guarantees exactly one function per table.)
pglite-sync applies each batch in a transaction with SET LOCAL electric.syncing = true. Postgres de-duplicates identical notifications within a transaction, so after each commit every table written in that batch notifies once, and every live query reading any of those tables calls refresh().
refresh() is wrapped in debounceMutex, so a single query never has more than one run in flight plus one pending. That bounds it per query — but the net effect is that every mounted live query re-runs continuously for as long as the sync is applying, each run a full query through the same serialized execution queue the applies themselves use.
Impact
Our app: ~60 shapes, a navigation tree with up to a few hundred mounted live queries, a few hundred thousand rows on first sync or on a shape 409 re-snapshot. Unmodified, the notify traffic roughly doubled initial sync time, drove memory up noticeably and starved interactive reads until the sync settled.
Workaround we use
After boot (and periodically, because the functions are created lazily when a table gets its first live query) we rewrite the generated function bodies:
CREATE OR REPLACE FUNCTION "_notify_<s>_<t>"() RETURNS trigger AS $$
BEGIN
IF COALESCE(NULLIF(current_setting('electric.syncing', true), ''), 'false')::boolean THEN
RETURN NULL;
END IF;
PERFORM pg_notify('table_change__<s>__<t>', '');
RETURN NULL;
END $$ LANGUAGE plpgsql;
and when the sync reports up-to-date we fire one pg_notify per live channel so queries that were mounted during the sync pick up the applied data. It works, but it reaches into generated internals, couples live to pglite-sync's private GUC, and the settle round is easy to get wrong (without it, queries mounted mid-sync show empty results until the next real write).
Proposal
Keep live generic, but give bulk writers a supported way to suspend notifications:
- A GUC checked by the generated trigger function, e.g.
pglite.live_notify(default on). Any bulk writer canSET LOCAL pglite.live_notify = offinside its transaction — pglite-sync applies, imports,COPY-style loads. Since there is exactly one generated function per table, this is a one-line change inaddNotifyTriggersToTables()with no new bookkeeping. live.pause()/live.resume()on the namespace (or a transaction-scoped helper), whereresume()issues one notification per table written while paused, so live queries mounted mid-pause are refreshed exactly once instead of never.- pglite-sync uses (1) in its apply transaction and calls (2) when a batch ends up-to-date.
(1) alone removes the amplification; (2) is what makes the home-grown settle round unnecessary.
Happy to open a PR for (1) and the pglite-sync side if this direction is acceptable.
Environment
@electric-sql/pglite0.5.14,@electric-sql/pglite-sync0.6.15,@electric-sql/client1.5.28- PGlite in a web worker with IndexedDB persistence, Chrome on Linux
- Lingua principale
- TypeScript
- Stelle
- 16.3k
- Fork
- 474
- Merge medio
- 23h 53m
- PR unite (30g)
- 53
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di electric-sql/pglite
-
Feature request: Nitro 3 support (`unwasm` export condition)Forse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Aperta
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 85/100
electric-sql/pglite#1120 · 16 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 25/100
electric-sql/pglite#1200 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 54/100
electric-sql/pglite#1192 ·
I maintainer di solito rispondono entro 1 giorno
-
[BUG]: syncToFs() resolves immediately, without syncing, when another sync is already queuedForse già presa @PrabalParihar l’ha presa 11 giorni fa. Apertabug
Difficoltà 3/5 1-2 giorni Idoneità per principianti 35/100
electric-sql/pglite#1191 ·
I maintainer di solito rispondono entro 1 giorno
-
pglite-socket: handleData copies the whole buffer for every chunk (quadratic time for large messages)Forse già presa @benclmnt l’ha presa 10 giorni fa. Aperta
Difficoltà 3/5 1-2 giorni Idoneità per principianti 62/100
electric-sql/pglite#1181 · 3 commenti ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di electric-sql/pglite
Issue simili
-
Bug: Broken RTL / BiDi text rendering when mixing Persian (Farsi) with English or numbersForse già presa Una pull request collegata a questa issue è aperta o già unita. Apertabug
Difficoltà 2/5 Mezza giornata Idoneità per principianti 68/100
amosblomqvist/learnharness#758 ·
I maintainer di solito rispondono entro 2 giorni
-
Change WorkspacesAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
bitfocus/companion-module-renewedvision-propresenter-api#134 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
rcpch/digital-growth-charts-react-component-library#304 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
dsh-market/dsh-market#1210 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
good first issue
Difficoltà 2/5 1-3 ore Idoneità per principianti 86/100
trustjonathan/STUDY-HUB#13 ·