web-dev-qa-db-ja.com

Spring Webflux Async PostgreSQLPublisherが最初の結果後に停止する

PostgreSQLデータベースポーラーをリアクティブ非同期 postgres-async-driver に置き換え、新しく挿入された行を Josh Long のようなSpring 5 Webflux ReactiveWebSocketクライアントにストリーミングしようとしています。デモされた素晴らしい例 ここ そして SébastienDeleuze'sspring-reactive-playground に基づいています。

私のPublisherは最初のrowを取得しますが、その後は後続の行を返しません。 ObservablePublisher、または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コンバーターを使用して、ObservableWebSocketHandlerに配線します。

@Bean
WebSocketHandler dbWebSocketHandler() {
    return session -> {
        Observable<WebSocketMessage> o = getObservableWSM(session);
        return session.send(Flux.from(RxReactiveStreams.toPublisher(o)));
    };
}

これにより、rowステートメントから最初のsqlが取得されますが、追加の行は取得されません。追加の行をストリーミングし続けるにはどうすればよいですか?

理想的には、MongoDBに相当するPostgreSQLが必要だと思います Tailable cursor

12
JJ Zabkar

この例 に基づいてテーブルに対してINSERTsで起動する 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;
}
2
JJ Zabkar