Output logical messages sent via pg_logical_emit_message#20
Output logical messages sent via pg_logical_emit_message#20dpirotte wants to merge 15 commits intoeulerto:masterfrom
Conversation
`change` now includes messages sent via pg_logical_emit_message when used transactionally. (i.e. first arg is true)
594d674 to
f222f15
Compare
f222f15 to
9cfeaf5
Compare
This helps easily build against several versions of Postgres.
|
@eulerto @dvarrazzo Any thoughts on this? I fixed a build issue against < 9.6 and added support for non-transactional logical messages. |
dvarrazzo
left a comment
There was a problem hiding this comment.
@dpirotte it's a cool feature, I didn't know of pg_logical_emit_message.
I am not an active participant to this project: my needs were surpassing the scope of this project so I've put together replisome which has not been released yet and is being used experimentally by my company (ideally it should be released when the experimental projects it is part of will become production).
The codebase has largely diverged so it won't be possible to apply your MR as it is, however the feature is cool indeed and I will probably backport it (or happily accept your contribution :).
| delete3 delete4 savepoint specialvalue toast bytea | ||
|
|
||
| PG_VERSION ?= 9.6 | ||
| PG_CONFIG = /usr/lib/postgresql/${PG_VERSION}/bin/pg_config |
There was a problem hiding this comment.
This is pretty hardcoded. You should allow overriding PG_CONFIG from outside and use pg_config --version to get the version number.
| PG_VERSION ?= 9.6 | ||
| PG_CONFIG = /usr/lib/postgresql/${PG_VERSION}/bin/pg_config | ||
|
|
||
| ifeq ($(PG_VERSION),9.6) |
There was a problem hiding this comment.
This is not future proof, it shoud be >= 9.6, which is a bit painful in Makefile but doable: see https://github.com/dvarrazzo/pgparts/blob/master/Makefile (see PG_CONFIG, PGVERSION, INTVERSION).
|
|
||
| -- Two messages | ||
| BEGIN; | ||
| SELECT 'emit' FROM pg_logical_emit_message(true, 'foo', 'bar'); |
There was a problem hiding this comment.
ISTM there is no test for bytea test. I'd check if all the bytes from 0x00 to 0xFF are sent ok.
| if(data->pretty_print) | ||
| { | ||
| appendStringInfoString(ctx->out, "\t\t\t\"kind\": \"message\",\n"); | ||
| appendStringInfo(ctx->out, "\t\t\t\"transactional\": \"%d\",\n", transactional); |
There was a problem hiding this comment.
transactional is a bool, JSON has bool... I don't think this value should be the string "0" or "1".
|
@dvarrazzo Thanks for the feedback! I'll incorporate as time permits and take a look at modifying for replisome. |
* Allow passing in PG_CONFIG instead and infer PG_VERSION from there * Run `pg_logical_emit_message` tests if >= 9.6 Note: The version check works still needs refactoring. It works against `9.6`, `10.0`, but not `10beta2`. `dpkg --compare-versions` works beautifully on Debian flavors, but it would be uncouth to require dpkg.
* Write `true`/`false` instead of "1"/"0" when emitting messages.
This adds a test around bytea output. I don't think is quite correct, and I believe we actually want to force escape or hex output.
Non-transactional messages don't show up in WAL right away. They show up after short wait (< 0.5s) or with the next commit. This test simply demonstrates the former case.
I make an assumption that any letter in `pg_config --version` will be the start of alpha, beta, or rc. Simply axe all of that and replace with `.0`, i.e `10beta2` => `10.0`.
This feature allows software to insert data into WAL stream that can be read by wal2json. Those messages could be useful to control replication, for example. Messages can be sent as transactional or not. Non-transactional messages mean that it is sent even if the transaction is rollbacked. There was a PR #20 for this same feature but I didn't use it. Indeed, this code was dusty in my computer for a few months. NOTE: 'message' test will fail on <= 9.5 because this feature was coded in 9.6 (I don't want to complicate Makefile).
In 9.6, the
pg_logical_emit_messagefunction sends arbitrary data to WAL for logical decoding. One can leverage this infrastructure to transactionally send application/domain events along with "change data capture" events. The events are presented like so:{"change":[{"kind":"message","transactional":"1","prefix":"foo","content":"bar"}]}This change supports transactional messages and ignores non-transactional messages. (I left "transactional" in the JSON anticipating support for non-transactional messages in the future.)
This is useful for me, and I hope it is useful for others as well. Feedback welcome on any/all aspects.