Contributing to pgmq-cpp
July 26, 2026 ยท View on GitHub
Thank you for helping improve pgmq-cpp. This is an independent community
project and is not an official PGMQ support channel.
Suspected vulnerabilities must be reported privately as described in SECURITY.md, not through a public issue or pull request.
Before opening a change
For correctness bugs, include:
- PostgreSQL and PGMQ versions;
- operating system, compiler, CMake version, and build preset;
- the smallest reproducer;
- expected and actual delivery/transaction behavior;
- whether the test used a real PostgreSQL/PGMQ instance;
- SQLSTATE and
pgmq::Error::operation()where available.
Do not include credentials or production connection strings. Reliability claims based only on mocks are not sufficient for queue, transaction, lease, disconnect, or crash behavior.
Development setup
Requirements:
- C++20 compiler;
- CMake 3.25+;
- Ninja for the supplied Linux presets;
- libpq and nlohmann/json (the included vcpkg manifest is supported);
- Docker with Compose for the isolated integration database when running the real-database suite;
- optional Doxygen and clang-tidy.
Configure and build on Linux:
export VCPKG_ROOT=/path/to/vcpkg
cmake --preset linux-debug
cmake --build --preset linux-debug
ctest --test-dir build/linux-debug --output-on-failure
Run the sanitizer configuration:
cmake --preset linux-sanitize
cmake --build --preset linux-sanitize
ctest --preset linux-sanitize
On Windows:
$env:VCPKG_ROOT = 'C:\path\to\vcpkg'
cmake --preset windows-debug
cmake --build --preset windows-debug
ctest --preset windows-debug
The project windows-debug, windows-release, and linux-debug presets
explicitly set PGMQ_CPP_REGISTER_DOCKER_TESTS=ON. A direct configure defaults
that option to OFF, and linux-sanitize also keeps it off. Override it
explicitly when choosing whether the real Docker fixture should be registered.
Consult tests/ and the verification ledger for the
current integration database command and test labels. Never point destructive
tests at a shared, private, staging, or production database.
Design rules
- Keep the public API C++20-only and free of libpq types.
- Use RAII for connections, results, and transactions.
- Do not share one libpq connection concurrently between threads.
- Bind SQL values. A dynamic identifier is allowed only after
QueueNamevalidation and PostgreSQL identifier quoting. - Use
std::chronofor durations and time points. - Preserve
pgmq::Errorcategory, SQLSTATE, operation, and detail. - Do not introduce an alternative error model beside exceptions.
- Do not auto-commit a caller-owned
pgmq::Transaction. - Keep
WorkerTransactionhandlers free of transaction-control SQL and SQL that acknowledges or changes their current task;execute()is a trusted escape hatch, not a sandbox. - Keep queues bounded and stop-aware; no unbounded thread or task creation.
- Preserve the
read_ctownership guard for all regular-mode renewals and terminal actions. - Keep notifications advisory and polling authoritative.
- Never claim exactly-once behavior for arbitrary external effects.
- Do not add a web service, broker daemon, authentication layer, or workflow engine to this library.
Substantial design changes need an ADR under docs/adr/.
Tests required by change type
| Change | Minimum evidence |
|---|---|
| Value validation, parsing, backoff | Focused unit test |
| SQL function or result parsing | Unit test plus real PGMQ integration test |
| Pooling, worker scheduling, stop behavior | Deterministic unit/concurrency test |
| Lease, retry, dead-letter, transaction | Real PGMQ integration test |
| Disconnect or reconnect | Controlled local database interruption test |
| Crash boundary | Separate process terminated at a deterministic sync point |
| Installed CMake interface | Fresh external consumer configure/build |
| Performance claim | Raw benchmark output and full environment metadata |
Tests must have bounded timeouts and clean up only their uniquely named queues and project-owned containers/processes.
Documentation and API compatibility
Public additions require:
- API comments or Doxygen-visible declarations;
- a realistic usage example;
- compatibility-table updates when an upstream SQL capability is involved;
- reliability/failure-model updates when semantics change;
- a changelog entry.
Code snippets in README and docs/ must compile against the public headers.
QueueWorkerConfig is constructed with a QueueName; it is not a designated
aggregate.
Pull request checklist
- The change is scoped and has no unrelated formatting churn.
- Unit tests pass.
- Required real-database tests pass, or are clearly marked not run.
- Sanitizers/static analysis were run where relevant, or marked not run.
- Install-consumer verification passes for public package changes.
- Documentation and changelog are updated.
- No secrets, generated build trees, benchmark marketing claims, or upstream PGMQ source snapshots are committed accidentally.
- External-side-effect semantics remain described as at-least-once.
By contributing, you agree that your contribution is licensed under the project's MIT License.