Re: NOTIFY in asynchronous mode

Поиск
Список
Период
Сортировка
От Jan Urbański
Тема Re: NOTIFY in asynchronous mode
Дата
Msg-id 4EB52352.2040802@wulczer.org
обсуждение исходный текст
Ответ на NOTIFY in asynchronous mode  (Tobias Oberstein <tobias.oberstein@tavendo.de>)
Ответы Re: NOTIFY in asynchronous mode  (Tobias Oberstein <tobias.oberstein@tavendo.de>)
Список psycopg
On 05/11/11 11:54, Tobias Oberstein wrote:
> -- Original message -----
>>> What would be provided to the callback?
>>>
>>> Channel (from NOTIFIY), Payload (from NOTIFIY), Connection (txpostgres)
>> ?
>>
>> Probably simply the psycopg2 Notify object.
>
> Ok, fine also.
>
> And not the Connection object on which it was received? Ok, maybe it's
>  not needed: When I want to do some db stuff within the callback, should
> not make a difference on what connection I do that.

You would register the callback on the Connection object, so you could
tell it which connection it will get registered on beforehand.

> Few other design Qs:
>
> Is it possible to UNLISTEN?

Sure, because you'd call both LISTEN and UNLISTEN as SQL statements with
runQuery.

> Or unregister a callback on a channel? Or set it to None?
>
> Are callbacks for channels registered "globally" or per connection?

The callbacks would be registered per connection, since it's the
connection who receives notifications.

> Can there be only one callback at most registered per channel?

Channel handling would be entirely up to the client. Here's a quick
example of how it could work (based on the patch I previously mentioned
from Jan Pobrislo, with a slightly changed callback API):


from twisted.python import log
from twisted.python.util import println

class NotifyObserver(object):

    def __init__(self, conn):
        self.conn = conn

    def __call__(self, notify):
        if notify.channel == 'channel1':
            println('got notify on channel 1, unlistening and removing')
            self.conn.removeNotifyObserver(self)
            d = conn.runQuery('UNLISTEN *')
            d.addCallback(lambda _: println('unlistened'))
            d.addErrback(log.err)
        else:
            println('got some other notify')


# conn is a txpostgres Connection
observer = NotifyObserver(conn)
# any number of different callables can be registered, here we just
register one
conn.addNotifyObserver(observer)

d = conn.runQuery('LISTEN channel1')
d.addCallback(lambda _: conn.runQuery('LISTEN channel2'))
d.addCallback(lanbda _: println('listening')

# then, after the program prints "listening" execute from psql in
another session
=$ NOTIFY channel2;
=$ NOTIFY channel2;
=$ NOTIFY channel1;
=$ NOTIFY channel2;

# which would yield the following from the running program
"got some other notify"
"got some other notify"
"got notify on channel 1, unlistening and removing"

# note that after a notify on channel1 is received, the observer is gone
and no more notifies are processed

I think that's a reasonably simple API and one that allows you to do
anything you want without introducing some extra interfaces that notify
observers have to implement, just requiring that they are callable.

Cheers,
Jan

В списке psycopg по дате отправления:

Предыдущее
От: Daniele Varrazzo
Дата:
Сообщение: Re: NOTIFY in asynchronous mode
Следующее
От: Jan Urbański
Дата:
Сообщение: Re: NOTIFY in asynchronous mode