libpqでLISTENを書いてからlibpqxxで書き直したら凄くすっきりしました。
単にLISTENする
notification_receiverを継承して
#include <iostream>
#include <pqxx/pqxx>
class cout_rec : pqxx::notification_receiver
{
public:
cout_rec(pqxx::connection & conn, const std::string & channel) : notification_receiver(conn, channel)
{
}
virtual void operator() (const std::string & payload, int pid)
{
std::cout << payload << std::endl;
}
};
int main(int argc, char * * argv)
{
std::string table = "todos";
pqxx::connection conn("host=localhost user=dev password=password dbname=db_dev");
cout_rec receiver(conn, table);
conn.await_notification();
return 0;
}
NOTIFY todos "hello"すると"hello"が標準出力に出ます。
ある条件を満たす行が最初からあったらそれでいい場合
レシーバはそのままで
int main(int argc, char * * argv)
{
pqxx::connection conn("host=localhost user=dev password=password dbname=db_dev");
cout_rec receiver(conn, "todos");
pqxx::work tran(conn);
tran.exec("LOCK TABLE todos"); // You must wait until commit if you want to insert into the table.
pqxx::result r = tran.exec("SELECT id FROM todos WHERE done=FALSE");
tran.commit();
if (0 < r.size())
{
std::cout << r[0][0] << std::endl;
}
else
{
conn.await_notification();
}
return 0;
}
SELECTとcommit()の間で誰かがINSERTすると取りこぼすので"LOCK TABLE"してます。バグなのか仕様なのかは知りません。