PostgreSQLデータベースポーラーをリアクティブ非同期 postgres-async-driver に置き換え、新しく挿入された行を Josh Long のようなSpring 5 Webflux ReactiveWebSocketクライアントにストリーミングしようとしています。デモされた素晴らしい例 ここ そして SébastienDeleuze'sspring-reactive-playground に基づいています。
私のPublisher
は最初のrow
を取得しますが、その後は後続の行を返しません。 Observable
、Publisher
、またはpostgres-async-driver Db
の使用方法に問題がありますか?
public Observable<WebSocketMessage> getObservableWSM(WebSocketSession session){
return
// com.github.pgasync.Db
db.queryRows(sql)
// ~RowMapper method
.map(row -> mapRowToDto(row))
// serialize dto to String for websocket
.map(dto -> { return objectMapper.writeValueAsString(dto); })
// finally, write to websocket session
.map(str -> { return session.textMessage((String) str);
});
}
次に、RxReactiveStream.toPublisher
コンバーターを使用して、Observable
をWebSocketHandler
に配線します。
@Bean
WebSocketHandler dbWebSocketHandler() {
return session -> {
Observable<WebSocketMessage> o = getObservableWSM(session);
return session.send(Flux.from(RxReactiveStreams.toPublisher(o)));
};
}
これにより、row
ステートメントから最初のsql
が取得されますが、追加の行は取得されません。追加の行をストリーミングし続けるにはどうすればよいですか?
理想的には、MongoDBに相当するPostgreSQLが必要だと思います Tailable cursor 。
この例 に基づいてテーブルに対してINSERT
sで起動する Postgres Trigger を作成しました:
CREATE OR REPLACE FUNCTION table_update_notify() RETURNS trigger AS $$
DECLARE
id bigint;
BEGIN
IF TG_OP = 'INSERT' THEN
id = NEW.id;
ELSE
id = OLD.id;
END IF;
PERFORM pg_notify('my_trigger_name', json_build_object('table', TG_TABLE_NAME, 'id', id, 'type', TG_OP)::text);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
次に、 reactive-pg-client を使用してそのPostgresトリガーをサブスクライブしました。 Pub/Subの例のコードは次のとおりです。
@Bean
PgPool subscribedNotificationHandler() {
PgPool client = pgPool();
client.getConnection(asyncResult -> {
if (asyncResult.succeeded()) {
PgConnection connection = asyncResult.result();
connection.notificationHandler(notification -> {
notification.getPayload();
// do things with payload
});
connection.query("LISTEN my_trigger_name", ar -> {
log.info("Subscribed to channel");
});
}
});
return client;
}