Re: Discussion on a LISTEN-ALL syntax

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Trey Boudreau <trey(at)treysoft(dot)com>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: Discussion on a LISTEN-ALL syntax
Date: 2024-12-20 22:07:42
Message-ID: 737106.1734732462@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Trey Boudreau <trey(at)treysoft(dot)com> writes:
> My first pass at the documentation looks like this:

> <para>
> The special wildcard <literal>*</literal> cancels all listener
> registrations for the current session and replaces them with a
> virtual registration that matches all channels. Further
> <command>LISTEN</command> and <command>UNLISTEN <replaceable
> class="parameter">channel</replaceable></command> commands will
> be ignored until the session sees the <command>UNLISTEN *</command>
> command.
> </para>

Hmph. After thinking about it a bit I have a different idea
(and I see David has yet a third one). So maybe this is more
contentious than it seems. But at any rate, I have two
fundamental thoughts:

* "Listen to all but X" seems like a reasonable desire.

* The existing implementation already has the principle that
you can't listen to a channel more than once; that is,
LISTEN foo;
LISTEN foo; -- this is a no-op, not a duplicate subscription

Therefore I propose:

* "LISTEN *" wipes away all previous listen state, and
sets up a state where you're listening to all channels
(within your database).

* "UNLISTEN *" wipes away all previous listen state, and
sets up a state where you're listening to no channels
(which is the same as it does now).

* "LISTEN foo" adds "foo" to what you are listening to,
with no effect if you already were listening to foo
(whether it was a virtual or explicit listen).

* "UNLISTEN foo" removes "foo" from what you are listening to,
with no effect if you already weren't listening to foo.

This is just about the same as the current behavior, and it makes
"LISTEN *" act the same as though you had somehow explicitly listed
every possible channel. Which I think is a lot cleaner than
conceptualizing it as an independent gating behavior, as well
as more useful because it'll permit "all but" behavior.

The implementation of this could be something like

struct {
bool all; /* true if listening to all */
List *plus; /* channels explicitly listened */
List *minus; /* channels explicitly unlistened */
} ListenChannels;

with the proviso that "plus" must be empty if "all" is true,
while "minus" must be empty if "all" is false. The two lists
are always empty right after LISTEN * or UNLISTEN *, but could
be manipulated by subsequent channel-specific LISTEN/UNLISTEN.

(Since only one list would be in use at a time, you could
alternatively combine "plus" and "minus" into a single list
of exceptions to the all/none state. I suspect that would
be confusingly error-prone to code; but perhaps it would turn
out elegantly.)

One other thing that needs to be thought about in any case
is what the pg_listening_channels() function ought to return
in these newly-possible states.

regards, tom lane

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Daniel Gustafsson 2024-12-20 22:20:58 Re: [PoC] Federated Authn/z with OAUTHBEARER
Previous Message Pavel Stehule 2024-12-20 22:00:12 Re: Re: proposal: schema variables