Pluggable sinks: write to any target, not just Elasticsearch
- PGSync can now sync to targets other than a search engine, such as ClickHouse, a warehouse, or a queue.
- A new Sink interface defines what PGSync needs from a write target. You plug yours in through the existing
Sync.make_search_client() hook. - Only two methods are required: bulk() to write a batch, and _create_setting() to create the target schema, whether that is an
index mapping or a CREATE TABLE. - Everything else, including refresh, search, teardown and close, has a safe default you can ignore if your target has no
equivalent. - Building a custom sink no longer means forking PGSync.
- Elasticsearch and OpenSearch support is unchanged. SearchClient is now the reference implementation of the interface.
- Quirks that only apply to Elasticsearch, such as the legacy _type field on versions below 7, now live inside the sink instead
of the core sync loop.
Graceful shutdown
- New Sync.stop() tells every background worker to finish and waits for them, so the process exits cleanly.
- No more relying on the interpreter to tear down threads on Ctrl+C.
- Workers on long timers, such as replication slot cleanup, now exit immediately instead of sleeping out the rest of their
interval. - stop() is safe to call more than once and safe to call from a signal handler.
- Makes PGSync much easier to run under systemd, Kubernetes, or any supervisor that expects a graceful SIGTERM.
- Daemon behaviour is unchanged if you never call it.
Import PGSync without environment variables
- Importing pgsync previously failed unless PG_USER was already set.
- The setting is now resolved the first time it is actually needed.
- You still get the same clear error if it is genuinely missing when connecting.
- Useful for tooling, tests, and subclassing Sync to build a custom sink.