Spring Webflux Async PostgreSQL Publisher останавливается после первого результата
Я пытаюсь заменить обработчика базы данных PostgreSQL реактивным асинхронным postgres-асинхронным драйвером и потоком вновь вставленных строк на сайт Spring 5 Webflux Reactive websocket client, например, Josh Long, примерный пример, продемонстрированный здесь, и основанный на весенне-реактивной площадке Sébastien Deleuze.
Мой 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
с помощью конвертера RxReactiveStream.toPublisher
:
@Bean
WebSocketHandler dbWebSocketHandler() {
return session -> {
Observable<WebSocketMessage> o = getObservableWSM(session);
return session.send(Flux.from(RxReactiveStreams.toPublisher(o)));
};
}
Это захватит первую row
из моей инструкции sql
, но никаких дополнительных строк. Как продолжить поток дополнительных строк?
В идеале, я думаю, что я хочу, чтобы PostgreSQL эквивалент курсора MongoDB Tailable.
Ответы
Ответ 1
Я создал триггер Postgres, который запускает INSERT
для моей таблицы на основе этого примера:
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;
Затем я подписался на этот триггер Postgres, используя реактивный-pg-клиент. Вот код из их примера 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;
}