I am trying to subscribe to two different notifications using libpqxx
. I found this unit test which I modified to serve my objective.
class TestListener final : public pqxx::notification_receiver
{
bool m_done;
public:
explicit TestListener(pqxx::connection &conn, std::string Name) :
pqxx::notification_receiver(conn, Name), m_done(false)
{}
void operator()(std::string const &, int be_pid) override
{
m_done = true;
std::cout << "Received notification: " << channel() << " pid=" << be_pid
<< std::endl;
}
bool done() const { return m_done; }
};
I am trying to create a function that simply waits for the notifications and exits as soon as it receives them.
// ...
void waitForChannel(TestListener &L){
while(!L.done()){};
std::cout << "received notificaton for channel " << L.channel() << "\n";
};
int main(){
// assume the connection is made
// ...
TestListener L1{conn, "channel1"};
TestListener L2{conn, "channel2"};
pqxx::perform([&conn, &L1] {
pqxx::work tx{conn};
tx.exec0("NOTIFY " + tx.quote_name(L1.channel()));
tx.commit();
});
pqxx::perform([&conn, &L2] {
pqxx::work tx{conn};
tx.exec0("NOTIFY " + tx.quote_name(L2.channel()));
tx.commit();
});
while(true){
waitForChannel(L1);
waitForChannel(L2);
}
return 0;
}
However, I have not been able to receive any signal and gets stuck in while(!L.done())
.
Could someone kindly help?
If you wish to listen for database changes, there should be a database trigger set on the table of interest such as
CREATE OR REPLACE FUNCTION notification_trigger() RETURNS TRIGGER AS
$$
BEGIN
PERFORM pg_notify('<notification_channel>',
to_json(NEW)::TEXT
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE TRIGGER capture_change_trigger AFTER INSERT OR UPDATE OR DELETE ON <db_table>
FOR EACH ROW EXECUTE FUNCTION notification_trigger();
And also make sure to await for notifications using the await_notification method.
TestListener L1{conn, "channel1"};
conn.await_notification();
If you don't want to block awaiting for notifications, you could use get_notifs.