mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-08-24 21:57:19 +02:00
Client-side fixes for delayed NOTIFY receipt.
PQnotifies() is defined to just process already-read data, not try to read any more from the socket. (This is a debatable decision, perhaps, but I'm hesitant to change longstanding library behavior.) The documentation has long recommended calling PQconsumeInput() before PQnotifies() to ensure that any already-arrived message would get absorbed and processed. However, psql did not get that memo, which explains why it's not very reliable about reporting notifications promptly. Also, most (not quite all) callers called PQconsumeInput() just once before a PQnotifies() loop. Taking this recommendation seriously implies that we should do PQconsumeInput() before each call. This is more important now that we have "payload" strings in notification messages than it was before; that increases the probability of having more than one packet's worth of notify messages. Hence, adjust code as well as documentation examples to do it like that. Back-patch to 9.5 to match related server fixes. In principle we could probably go back further with these changes, but given lack of field complaints I doubt it's worthwhile. Discussion: https://postgr.es/m/CAOYf6ec-TmRYjKBXLLaGaB-jrd=mjG1Hzn1a1wufUAR39PQYhw@mail.gmail.com
This commit is contained in:
parent
7aaeb7b45a
commit
d30d27a528
@ -5284,7 +5284,7 @@ typedef struct pgNotify
|
|||||||
<para>
|
<para>
|
||||||
<function>PQnotifies</function> does not actually read data from the
|
<function>PQnotifies</function> does not actually read data from the
|
||||||
server; it just returns messages previously absorbed by another
|
server; it just returns messages previously absorbed by another
|
||||||
<application>libpq</application> function. In prior releases of
|
<application>libpq</application> function. In ancient releases of
|
||||||
<application>libpq</application>, the only way to ensure timely receipt
|
<application>libpq</application>, the only way to ensure timely receipt
|
||||||
of <command>NOTIFY</command> messages was to constantly submit commands, even
|
of <command>NOTIFY</command> messages was to constantly submit commands, even
|
||||||
empty ones, and then check <function>PQnotifies</function> after each
|
empty ones, and then check <function>PQnotifies</function> after each
|
||||||
@ -8677,6 +8677,7 @@ main(int argc, char **argv)
|
|||||||
notify->relname, notify->be_pid);
|
notify->relname, notify->be_pid);
|
||||||
PQfreemem(notify);
|
PQfreemem(notify);
|
||||||
nnotifies++;
|
nnotifies++;
|
||||||
|
PQconsumeInput(conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -836,7 +836,8 @@ PrintNotifications(void)
|
|||||||
{
|
{
|
||||||
PGnotify *notify;
|
PGnotify *notify;
|
||||||
|
|
||||||
while ((notify = PQnotifies(pset.db)))
|
PQconsumeInput(pset.db);
|
||||||
|
while ((notify = PQnotifies(pset.db)) != NULL)
|
||||||
{
|
{
|
||||||
/* for backward compatibility, only show payload if nonempty */
|
/* for backward compatibility, only show payload if nonempty */
|
||||||
if (notify->extra[0])
|
if (notify->extra[0])
|
||||||
@ -847,6 +848,7 @@ PrintNotifications(void)
|
|||||||
notify->relname, notify->be_pid);
|
notify->relname, notify->be_pid);
|
||||||
fflush(pset.queryFout);
|
fflush(pset.queryFout);
|
||||||
PQfreemem(notify);
|
PQfreemem(notify);
|
||||||
|
PQconsumeInput(pset.db);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1729,12 +1729,13 @@ ecpg_process_output(struct statement *stmt, bool clear_result)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check for asynchronous returns */
|
/* check for asynchronous returns */
|
||||||
notify = PQnotifies(stmt->connection->connection);
|
PQconsumeInput(stmt->connection->connection);
|
||||||
if (notify)
|
while ((notify = PQnotifies(stmt->connection->connection)) != NULL)
|
||||||
{
|
{
|
||||||
ecpg_log("ecpg_process_output on line %d: asynchronous notification of \"%s\" from backend PID %d received\n",
|
ecpg_log("ecpg_process_output on line %d: asynchronous notification of \"%s\" from backend PID %d received\n",
|
||||||
stmt->lineno, notify->relname, notify->be_pid);
|
stmt->lineno, notify->relname, notify->be_pid);
|
||||||
PQfreemem(notify);
|
PQfreemem(notify);
|
||||||
|
PQconsumeInput(stmt->connection->connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
@ -2239,6 +2239,9 @@ sendFailed:
|
|||||||
* no unhandled async notification from the backend
|
* no unhandled async notification from the backend
|
||||||
*
|
*
|
||||||
* the CALLER is responsible for FREE'ing the structure returned
|
* the CALLER is responsible for FREE'ing the structure returned
|
||||||
|
*
|
||||||
|
* Note that this function does not read any new data from the socket;
|
||||||
|
* so usually, caller should call PQconsumeInput() first.
|
||||||
*/
|
*/
|
||||||
PGnotify *
|
PGnotify *
|
||||||
PQnotifies(PGconn *conn)
|
PQnotifies(PGconn *conn)
|
||||||
|
@ -140,6 +140,7 @@ main(int argc, char **argv)
|
|||||||
notify->relname, notify->be_pid);
|
notify->relname, notify->be_pid);
|
||||||
PQfreemem(notify);
|
PQfreemem(notify);
|
||||||
nnotifies++;
|
nnotifies++;
|
||||||
|
PQconsumeInput(conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user