Обсуждение: Asynchronous Communication across two independent components

Поиск
Список
Период
Сортировка

Asynchronous Communication across two independent components

От
Damien Dougan
Дата:
Hi All,

I have a problem with how the interface to Postgres works (specifically the
libpq) and was wondering if there is a known solution to the type of
communication I wish to perform.


Basically, I have two components - one which is responsible for submitting
calls to stored procedures (the Sender), and one which is responsible for
handling the results (the Receiver).

(I've done it this way for a number of reasons - based on our platform
architecture, the need to avoid tying up threads in our platform, and the
need to store binary data in-memory whilst the stored procedure is being
executed - this data will not be held on the database during the life of the
database operation).


Thus my communication problems boil down to having two separate processes - I
want the Receiver to be able to deal with the results of stored procedures
that the Sender has executed.


I looked at the Client Interface functions, and they (PQsendQuery and
PQgetResult) seem to require both the Sender and Receiver to be available on
the same connection (which I don't want to have to do - since I'd be tying up
threads in our platform waiting for PGgetResult to return NULL before I could
subtmit another PQsendQuery).

So I'm pretty sure this is not what I'm after.


I also looked at the LISTEN/NOTIFY, which seemed promising. However, there
does not appear to be any mechanism to identify the event that caused the
notification. I was hoping to be able to have the Receiver handle the
notification by going to the appropriate relation and picking up the data
which was now ready for it - but there's no way to know which entry it is!


Is there a known Postgres solution to the problem of asynchronous
communication with separate sender/receiver?

Is there an alternative to this approach (bearing in mind I want to avoid
tying up threads in our platform whilst the database is doing its thing -
especially when there may be delays due to locks from other requests). The
key goal in the design of the solution is request throughput with a limited
number of threads - I don't mind the database locking until some requests are
continued, but I can't have the thread pool available to my own service being
consumed with idle listeners!


Many thanks for any advice and pointers,

Damien



Re: Asynchronous Communication across two independent components

От
Darko Prenosil
Дата:
On Monday 24 March 2003 15:35, Damien Dougan wrote:
> Hi All,
>
> I have a problem with how the interface to Postgres works (specifically the
> libpq) and was wondering if there is a known solution to the type of
> communication I wish to perform.
>
>
> Basically, I have two components - one which is responsible for submitting
> calls to stored procedures (the Sender), and one which is responsible for
> handling the results (the Receiver).
>
> (I've done it this way for a number of reasons - based on our platform
> architecture, the need to avoid tying up threads in our platform, and the
> need to store binary data in-memory whilst the stored procedure is being
> executed - this data will not be held on the database during the life of
> the database operation).
>
>
> Thus my communication problems boil down to having two separate processes -
> I want the Receiver to be able to deal with the results of stored
> procedures that the Sender has executed.
>
>
> I looked at the Client Interface functions, and they (PQsendQuery and
> PQgetResult) seem to require both the Sender and Receiver to be available
> on the same connection (which I don't want to have to do - since I'd be
> tying up threads in our platform waiting for PGgetResult to return NULL
> before I could subtmit another PQsendQuery).
>
> So I'm pretty sure this is not what I'm after.
>

You can send whole bunch of SQL commands using PQsendQuery, not only one !
After that you can get more than one PGResults depending on what commands you
send to Postgres. You only need to terminate it with ";".
For example:
PQSendQuery("SELECT * FROM pg_table; BEGIN TRANSACTION; DELETE FROM tbl WHERE
id = 1; COMMIT;");
When PQSendQuery command is executed, queries are just send to server.
Non-blocking means: program will not block and wait for results to come !!!
After that you should use combination of PQconsumeInput, PQisBusy and
PQgetResult. You can even cancel rest of the queries with PQrequestCancel.
It is all explained at:
http://developer.postgresql.org/docs/postgres/libpq-async.html , and it works
perfectly (spiking from my experience) !!!

If You need to wait to see if first command passes, and then send another,
threads and non-blocking commands can't help You! Then You simple must
execute with PQExec and wait for result !

>
> I also looked at the LISTEN/NOTIFY, which seemed promising. However, there
> does not appear to be any mechanism to identify the event that caused the
> notification. I was hoping to be able to have the Receiver handle the
> notification by going to the appropriate relation and picking up the data
> which was now ready for it - but there's no way to know which entry it is!
>
You can RAISE NOTICE inside of the function("stored procedure") with
custom text. But You do not need this. PQsendQuery with multiple sql commands
is what you need !

>
> Is there a known Postgres solution to the problem of asynchronous
> communication with separate sender/receiver?
>
> Is there an alternative to this approach (bearing in mind I want to avoid
> tying up threads in our platform whilst the database is doing its thing -
> especially when there may be delays due to locks from other requests). The
> key goal in the design of the solution is request throughput with a limited
> number of threads - I don't mind the database locking until some requests
> are continued, but I can't have the thread pool available to my own service
> being consumed with idle listeners!
>
>
> Many thanks for any advice and pointers,
>
> Damien
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/docs/faqs/FAQ.html



Re: Asynchronous Communication across two independent components

От
Damien Dougan
Дата:
Darko,

Thanks for the response, but I'm not sure if your suggestions will meet my
needs - as the page you referenced seems to suggest that these operations
must all go over the same connection (and I have a Sender and a Receiver on
separate connections).

Some comments embedded below ...

On Monday 24 March 2003 9:27 pm, you wrote:

> You can send whole bunch of SQL commands using PQsendQuery, not only one !
> After that you can get more than one PGResults depending on what commands
> you send to Postgres. You only need to terminate it with ";".
> For example:
> PQSendQuery("SELECT * FROM pg_table; BEGIN TRANSACTION; DELETE FROM tbl
> WHERE id = 1; COMMIT;");
> When PQSendQuery command is executed, queries are just send to server.
> Non-blocking means: program will not block and wait for results to come !!!
> After that you should use combination of PQconsumeInput, PQisBusy and
> PQgetResult. You can even cancel rest of the queries with PQrequestCancel.
> It is all explained at:
> http://developer.postgresql.org/docs/postgres/libpq-async.html , and it
> works perfectly (spiking from my experience) !!!

I did have a read through this before posting - and I was hoping the above
mechanisms would do the trick for me - but there appears to be two problems
with the PQsendQuery and PQgetResult.

(1) You cannot call PQsendQuery on the same connection until PQgetResult has
returned null.

(2) You cannot call PQgetResult on a different connection from PQsendQuery to
obtain the results of a query.

So whilst your solution would be fine for asynchronous comms within a single
connection, I'm afraid its not what I'm looking for!

> If You need to wait to see if first command passes, and then send another,
> threads and non-blocking commands can't help You! Then You simple must
> execute with PQExec and wait for result !
>
> > I also looked at the LISTEN/NOTIFY, which seemed promising. However,
> > there does not appear to be any mechanism to identify the event that
> > caused the notification. I was hoping to be able to have the Receiver
> > handle the notification by going to the appropriate relation and picking
> > up the data which was now ready for it - but there's no way to know which
> > entry it is!
>
> You can RAISE NOTICE inside of the function("stored procedure") with
> custom text. But You do not need this. PQsendQuery with multiple sql
> commands is what you need !
>

Thanks for the RAISE NOTICE heads-up - I'll take a look at this.

Damien



Re: Asynchronous Communication across two independent components

От
Darko Prenosil
Дата:
On Tuesday 25 March 2003 09:15, Damien Dougan wrote:
> Darko,
>
> Thanks for the response, but I'm not sure if your suggestions will meet my
> needs - as the page you referenced seems to suggest that these operations
> must all go over the same connection (and I have a Sender and a Receiver on
> separate connections).
>
How about sharing connections between sender and receiver. After all
PGConnection is only pointer that can be same for Sender and Receiver.
How do you mean to connect Sender and Receiver ? How should postgres know
which Sender will post results to which Receiver ?

The only way to have sender and receiver on different connections is to write
some kind of own server that will connect server and receiver to "Pair", but
I did newer heard for such "construction" in SQL server philosophy.
It is also possible to store the "results" from Sender to tables, and
Receiver can periodically check if something happened and get the results!

It all seems a little fuzzy to me. Maybe You can explain it with more details.

> Some comments embedded below ...
>
> On Monday 24 March 2003 9:27 pm, you wrote:
> > You can send whole bunch of SQL commands using PQsendQuery, not only one
> > ! After that you can get more than one PGResults depending on what
> > commands you send to Postgres. You only need to terminate it with ";".
> > For example:
> > PQSendQuery("SELECT * FROM pg_table; BEGIN TRANSACTION; DELETE FROM tbl
> > WHERE id = 1; COMMIT;");
> > When PQSendQuery command is executed, queries are just send to server.
> > Non-blocking means: program will not block and wait for results to come
> > !!! After that you should use combination of PQconsumeInput, PQisBusy and
> > PQgetResult. You can even cancel rest of the queries with
> > PQrequestCancel. It is all explained at:
> > http://developer.postgresql.org/docs/postgres/libpq-async.html , and it
> > works perfectly (spiking from my experience) !!!
>
> I did have a read through this before posting - and I was hoping the above
> mechanisms would do the trick for me - but there appears to be two problems
> with the PQsendQuery and PQgetResult.
>
> (1) You cannot call PQsendQuery on the same connection until PQgetResult
> has returned null.

That is true, but why do you wish to send another query if you send them all
in one PQSendQuery ?

>
> (2) You cannot call PQgetResult on a different connection from PQsendQuery
> to obtain the results of a query.
>
> So whilst your solution would be fine for asynchronous comms within a
> single connection, I'm afraid its not what I'm looking for!
>
> > If You need to wait to see if first command passes, and then send
> > another, threads and non-blocking commands can't help You! Then You
> > simple must execute with PQExec and wait for result !
> >
> > > I also looked at the LISTEN/NOTIFY, which seemed promising. However,
> > > there does not appear to be any mechanism to identify the event that
> > > caused the notification. I was hoping to be able to have the Receiver
> > > handle the notification by going to the appropriate relation and
> > > picking up the data which was now ready for it - but there's no way to
> > > know which entry it is!
> >
> > You can RAISE NOTICE inside of the function("stored procedure") with
> > custom text. But You do not need this. PQsendQuery with multiple sql
> > commands is what you need !
>
> Thanks for the RAISE NOTICE heads-up - I'll take a look at this.
>
Unfortunately RAISE NOTICE can only function through same connection, and if
You insist on different connection, this will not help.


> Damien
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/docs/faqs/FAQ.html



Re: Asynchronous Communication across two independent components

От
Damien Dougan
Дата:
On Tuesday 25 March 2003 1:13 pm, Darko Prenosil wrote:

> How about sharing connections between sender and receiver. After all
> PGConnection is only pointer that can be same for Sender and Receiver.
> How do you mean to connect Sender and Receiver ? How should postgres know
> which Sender will post results to which Receiver ?

I understand why the PQsendQuery and PQgetResult won't work across
connections, so that's not an issue.

> The only way to have sender and receiver on different connections is to
> write some kind of own server that will connect server and receiver to
> "Pair", but I did newer heard for such "construction" in SQL server
> philosophy.
>
>  It is also possible to store the "results" from Sender to tables, and
> Receiver can periodically check if something happened and get the results!

Yes - that's what I intend doing with the LISTEN and NOTIFY - I will have a
Trigger StoredProc that will be called when a table is updated in response to
the Sender issuing a request. The Trigger StoredProc will then insert an
entry in another table that will result in a notification.

I've separated out the logic of insertion into the notification table into a
Trigger StoredProc because its not really part of the logic of updating our
schema tables - effectively the notification table is meta-data to help the
Receiver determine what has been changed.

I just think this is a little clunky and was hoping for something cleaner ...

> That is true, but why do you wish to send another query if you send them
> all in one PQSendQuery ?

Our architecture is message based, so I can't delay the Sender waiting for
incoming messages (buffering them together) into a single PQsendQuery because
its all asynchronous communication.

> Unfortunately RAISE NOTICE can only function through same connection, and
> if You insist on different connection, this will not help.

Again, thanks for the heads-up on this!

Damien