愛と勇気と缶ビール

ふしぎとぼくらはなにをしたらよいか

PostgreSQLのLISTEN/NOTIFYでJSONデータを飛ばす

PostgreSQLではJSON, JSONBデータ型のサポートがあります。MySQLも5.7からあるようです。

アプリに対してちょっとした通知を飛ばしたくなったのですが、ちょっとした通知のために別のミドルウェアを導入するのは明らかに筋が悪いのでPostgresのLISTEN/NOTIFYを使うことにしました。

PostgresのLISTEN/NOTIFYはtext型しか渡せないので、ここは構造化されたデータををJSONなどで渡したくなるのが人情というものです。

以下のようなTRIGGERと

DROP TRIGGER IF EXISTS my_table_inserted ON my_table;

CREATE TRIGGER my_table_inserted
    AFTER INSERT ON my_table
    FOR EACH ROW
    EXECUTE PROCEDURE on_my_table_inserted();

以下のようなFUNCTIONで人情を達成します。

CREATE OR REPLACE FUNCTION on_my_table_inserted() RETURNS trigger AS $$
BEGIN
    PERFORM pg_notify('my_table_inserted', json_build_object(
        'id', NEW.id,
        'data_1', NEW.data_1,
        'data_2', NEW.data_2
    )::text);
    RETURN NEW;
END;
$$ LANGUAGE 'plpgsql';

結局のところ送っているのはtext型なのですが、受け取る側でJSON decodeすれば問題ないです。

Pythonで非同期に通知を受け取るコードは別記事に書きます。

完全に余談ですが、現状のPipelineDBではTRIGGERとLISTEN/NOTIFYをこのように組み合わせてCONTINUOUS VIEWの更新通知を受け取ることは出来ません。 CONTINUOUS TRIGGERの実現方法が原因だと思うのですが、多分そのうち何とかなると思います。