mq-bridge-py-basic 0.3.10__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/.github/dependabot.yml +10 -1
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/.github/workflows/node.yml +6 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/.github/workflows/test-matrix.yml +2 -2
- mq_bridge_py_basic-0.4.0/CHANGELOG.md +182 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/CLAUDE.md +3 -2
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/Cargo.lock +130 -76
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/Cargo.toml +21 -7
- mq_bridge_py_basic-0.3.10/python/mq-bridge-py/README.md → mq_bridge_py_basic-0.4.0/PKG-INFO +67 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/README.md +60 -198
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/benches/performance_bench.rs +145 -72
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0/docs}/ARCHITECTURE.md +15 -2
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0/docs}/CONFIGURATION.md +38 -2
- mq_bridge_py_basic-0.4.0/docs/DELIVERY.md +454 -0
- mq_bridge_py_basic-0.4.0/docs/EXTENDING.md +457 -0
- mq_bridge_py_basic-0.4.0/docs/PLUGINS.md +309 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0/docs}/REFERENCE.md +58 -9
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/mq-bridge.schema.json +99 -26
- mq_bridge_py_basic-0.4.0/mq_bridge/__init__.py +88 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/mq_bridge/__init__.pyi +59 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/mq_bridge/config.pyi +10 -2
- mq_bridge_py_basic-0.4.0/mq_bridge/plugin_packaging.py +90 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/pyproject.toml +3 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/Cargo.toml +4 -2
- mq_bridge_py_basic-0.3.10/PKG-INFO → mq_bridge_py_basic-0.4.0/python/mq-bridge-py/README.md +40 -24
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/pyproject-basic.toml +3 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/src/lib.rs +795 -3
- mq_bridge_py_basic-0.4.0/python/mq-bridge-py/tests/test_custom_endpoint.py +444 -0
- mq_bridge_py_basic-0.4.0/python/mq-bridge-py/tests/test_plugin_package.py +32 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/tests/test_public_api.py +4 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/uv.lock +126 -1
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/canonical_message.rs +8 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/grpc.proto +3 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/grpc.rs +1085 -110
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/mod.rs +34 -23
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/mongodb/consumer.rs +0 -352
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/mongodb/mod.rs +29 -9
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/mongodb/publisher.rs +52 -18
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/mongodb/readers.rs +51 -19
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/mongodb/tests.rs +30 -9
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/object_store.rs +41 -7
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/structural/mod.rs +1 -1
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/zeromq/mod.rs +42 -13
- mq_bridge_py_basic-0.4.0/src/endpoints/zeromq/omq.rs +712 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/zeromq/zmq.rs +18 -2
- mq_bridge_py_basic-0.4.0/src/extensions.rs +162 -0
- mq_bridge_py_basic-0.4.0/src/lib.rs +187 -0
- mq_bridge_py_basic-0.4.0/src/middleware/id.rs +320 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/mod.rs +11 -1
- mq_bridge_py_basic-0.4.0/src/models/builders.rs +958 -0
- mq_bridge_py_basic-0.4.0/src/models/defaults.rs +247 -0
- mq_bridge_py_basic-0.4.0/src/models/secrets.rs +500 -0
- mq_bridge_py_basic-0.4.0/src/models/serde_support.rs +661 -0
- mq_bridge_py_basic-0.4.0/src/models/tests.rs +681 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/models.rs +93 -2644
- mq_bridge_py_basic-0.4.0/src/plugin/conformance.rs +323 -0
- mq_bridge_py_basic-0.4.0/src/plugin/endpoint.rs +548 -0
- mq_bridge_py_basic-0.4.0/src/plugin/message.rs +147 -0
- mq_bridge_py_basic-0.4.0/src/plugin/middleware.rs +365 -0
- mq_bridge_py_basic-0.4.0/src/plugin/mod.rs +349 -0
- mq_bridge_py_basic-0.4.0/src/plugin/sdk.rs +1156 -0
- mq_bridge_py_basic-0.4.0/src/plugin/test_support.rs +131 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/route.rs +165 -29
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/support/interpolation.rs +74 -15
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/support/mod.rs +4 -1
- mq_bridge_py_basic-0.4.0/src/support/plugin_abi.rs +705 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/test_utils.rs +48 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/traits.rs +92 -17
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/mongodb.rs +184 -29
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/route.rs +5 -4
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration_test.rs +20 -7
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/ref_test.rs +4 -2
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/reference_docs_test.rs +25 -15
- mq_bridge_py_basic-0.3.10/CHANGELOG.md +0 -76
- mq_bridge_py_basic-0.3.10/mq_bridge/__init__.py +0 -25
- mq_bridge_py_basic-0.3.10/src/endpoints/zeromq/omq.rs +0 -373
- mq_bridge_py_basic-0.3.10/src/extensions.rs +0 -37
- mq_bridge_py_basic-0.3.10/src/lib.rs +0 -85
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/.github/workflows/benchmark.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/.github/workflows/ci.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/.github/workflows/ibm-mq.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/.github/workflows/publish-node.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/.github/workflows/publish-python.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/.github/workflows/python.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/.github/workflows/release.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/.gitignore +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/CONTRIBUTING.md +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/LICENSE +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/LICENSE.python +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/SECURITY.md +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/benches/ETL_BENCHMARKS.md +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/benches/router_bench.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/benches/zeromq_backends.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/bindings-common/Cargo.toml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/bindings-common/src/lib.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/bindings-common/src/logging.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/build.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/deny.toml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/examples/ipc_worker_queue.yaml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/mq_bridge/config.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/mq_bridge/py.typed +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/package-lock.json +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/LICENSE.python +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/analysis/bench_http_native.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/example.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/examples/bench_memory.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/examples/bench_memory.yaml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/examples/consume_pull.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/examples/dlt_source.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/examples/json_route.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/examples/memory.yaml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/examples/raw_route.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/pyproject-reduced.toml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/scripts/gen_config_types.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/tests/test_config_types.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/tests/test_logging.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/tests/test_packaging.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/tests/test_performance_smoke.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/python/mq-bridge-py/tests/test_routes.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/analysis/benches/metadata_bench.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/analysis/debug_ibm_mq_tls.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/analysis/http/analyze_xctrace_time_profile.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/analysis/http/http_flamegraph.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/analysis/http/mq_bridge_http_profile.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/analysis/http/run_http_ladder.sh +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/ci/format_bench_output.sh +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/httparena/README.md +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/httparena/frameworks/mq-bridge-py/Dockerfile +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/httparena/frameworks/mq-bridge-py/meta.json +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/httparena/frameworks/mq-bridge-py/server.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/techempower/Python/mq-bridge-py/README.md +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/techempower/Python/mq-bridge-py/benchmark_config.json +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/techempower/Python/mq-bridge-py/mq-bridge-py.dockerfile +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/techempower/Python/mq-bridge-py/server.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/techempower/README.md +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/techempower/postgres.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/techempower/seed.sql +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/techempower/verify.sh +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/the-benchmarker/README.md +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/the-benchmarker/python/mq-bridge-py/config.yaml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/the-benchmarker/python/mq-bridge-py/pyproject.toml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/scripts/the-benchmarker/python/mq-bridge-py/server.py +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/checkpoint.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/command_handler.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/amqp.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/aws.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/clickhouse.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/file/mod.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/file/tests.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/http/mod.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/http/publisher.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/http/stream.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/http/tests.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/ibm_mq.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/kafka.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/memory/endpoint.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/memory/framed.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/memory/ipc_unix.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/memory/ipc_windows.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/memory/memory_transport.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/memory/mod.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/memory/transport.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/mongodb/dedup.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/mqtt.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/nats.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/poll.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/postgres/VENDORED.md +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/postgres/mod.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/postgres/pgoutput/decoder.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/postgres/pgoutput/messages.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/postgres/pgoutput/mod.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/postgres/pgoutput/registry.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/postgres/pgoutput/values.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/postgres/replication.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/postgres/state.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/redis_streams.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/sled.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/sqlx/dedup.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/sqlx/mod.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/sqlx/tests.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/structural/fanout.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/structural/null.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/structural/reader.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/structural/request.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/structural/response.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/structural/static_endpoint.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/structural/stream_buffer.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/structural/switch.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/websocket.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/endpoints/zeromq/codec.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/errors.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/event_handler.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/event_store.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/buffer.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/compression.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/cookie_jar.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/deduplication.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/delay.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/dlq.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/encryption.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/limiter.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/metrics.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/random_panic.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/retry.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/transform/coerce.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/transform/compiled.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/transform/error.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/transform/mod.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/transform/path.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/transform/schema.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/transform/tests.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/middleware/weak_join.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/outcomes.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/publisher.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/response.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/support/base64_engine.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/support/compression.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/support/connection_registry.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/support/crypto.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/support/crypto_envelope.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/support/source_ranges.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/src/type_handler.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/README.md +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/armature_integration.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/amqp.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/aws.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/clickhouse.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/config.toml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/amqp.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/aws.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/clickhouse.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/ibm-mq-certs/client.crl +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/ibm-mq-certs/client.kdb +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/ibm-mq-certs/client.p12 +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/ibm-mq-certs/client.rdb +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/ibm-mq-certs/client.sth +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/ibm_mq.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/ibm_mq_tls.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/kafka-tls.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/kafka.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/mariadb.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/mongodb-replica.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/mongodb-tls.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/mongodb.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/mosquitto.conf +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/mosquitto_performance.conf +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/mosquitto_persistence.conf +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/mq_init.mqsc +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/mq_init_tls.mqsc +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/mqtt.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/mqtt_performance.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/mysql.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/nats.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/object_store.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/postgres.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/postgres_cdc.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/docker-compose/redis.yml +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/file.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/grpc.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/grpc_tls.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/http.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/http_tls.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/ibm_mq.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/ibm_mq_tls.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/ipc.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/kafka.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/kafka_tls.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/logic_test.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/mariadb.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/memory.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/mod.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/mongodb_raw.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/mongodb_tls.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/mqtt.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/mysql.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/nats.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/object_store.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/performance_static.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/postgres.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/postgres_cdc.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/redis_streams.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/scripts/gen_certs.sh +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/sqlite.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/tls_helpers.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/websocket.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/integration/zeromq.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/memory_leak_test.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/sqlite_test.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/tls_example.rs +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/unit_tests.md +0 -0
- {mq_bridge_py_basic-0.3.10 → mq_bridge_py_basic-0.4.0}/tests/websocket_test.rs +0 -0
|
@@ -7,5 +7,14 @@ version: 2
|
|
|
7
7
|
updates:
|
|
8
8
|
- package-ecosystem: "cargo" # See documentation for possible values
|
|
9
9
|
directory: "/" # Location of package manifests
|
|
10
|
+
target-branch: "dev"
|
|
10
11
|
schedule:
|
|
11
|
-
interval: "
|
|
12
|
+
interval: "monthly"
|
|
13
|
+
groups:
|
|
14
|
+
minor-and-patch:
|
|
15
|
+
applies-to: version-updates
|
|
16
|
+
patterns:
|
|
17
|
+
- "*"
|
|
18
|
+
update-types:
|
|
19
|
+
- "minor"
|
|
20
|
+
- "patch"
|
|
@@ -48,6 +48,9 @@ jobs:
|
|
|
48
48
|
test:
|
|
49
49
|
name: Node binding smoke test
|
|
50
50
|
runs-on: ubuntu-latest
|
|
51
|
+
# Backstop only; the tests carry their own tighter cap. Keep this above a
|
|
52
|
+
# cold-cache `cargo check` + `napi build`, which the step timeouts don't cover.
|
|
53
|
+
timeout-minutes: 30
|
|
51
54
|
steps:
|
|
52
55
|
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
53
56
|
with:
|
|
@@ -86,6 +89,9 @@ jobs:
|
|
|
86
89
|
working-directory: node/mq-bridge-node
|
|
87
90
|
run: npm run build:ci
|
|
88
91
|
|
|
92
|
+
# A leaked ThreadsafeFunction keeps the event loop alive and the suite
|
|
93
|
+
# never exits; cap it here rather than burning the whole job budget.
|
|
89
94
|
- name: Run Node tests
|
|
90
95
|
working-directory: node/mq-bridge-node
|
|
96
|
+
timeout-minutes: 5
|
|
91
97
|
run: npm test
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `mq-bridge`. Newest first.
|
|
4
|
+
|
|
5
|
+
## 0.4.0
|
|
6
|
+
|
|
7
|
+
### Breaking
|
|
8
|
+
|
|
9
|
+
- **Changed defaults.** Four defaults were chosen for safety or speed rather than history.
|
|
10
|
+
Set the field explicitly to keep the old behaviour:
|
|
11
|
+
- `batch_size` is **512** instead of 1. Batches fill opportunistically — the consumer waits
|
|
12
|
+
for one message and takes whatever else is already there — so this raises throughput
|
|
13
|
+
without adding idle latency. It does widen the blast radius of a failed batch, and
|
|
14
|
+
nothing caps a batch by bytes, so lower it on routes carrying large payloads.
|
|
15
|
+
- MongoDB `consume` defaults to **`capture_all`** instead of `consumer`. The old default
|
|
16
|
+
claimed, re-fetched and **deleted** each document, so pointing a route at a collection to
|
|
17
|
+
read it destroyed it — and it only ever worked on collections written by the mq-bridge
|
|
18
|
+
MongoDB publisher. `capture_all` is non-destructive, reads arbitrary collections, and is
|
|
19
|
+
~5x faster. On a replica set it snapshots, then follows the change stream; a one-shot
|
|
20
|
+
`exit_on_empty` / `--drain` job finishes once that stream goes quiet.
|
|
21
|
+
**`capture_all` and `capture_new` now require a replica set** (a single-node one is enough)
|
|
22
|
+
and refuse to start without one. `capture_all` used to fall back to paging `_id` forward on
|
|
23
|
+
a standalone `mongod`; that reader only ever matches ids above its high-water mark, so any
|
|
24
|
+
document a concurrent writer commits below it was dropped — silently, with no error and no
|
|
25
|
+
gap in the delivery count. On a standalone server use the new `consume: snapshot`, or
|
|
26
|
+
`consume: consumer` for a work queue.
|
|
27
|
+
- MongoDB `consume: subscriber` and the `MongoDbSubscriber` type are **removed**. It polled
|
|
28
|
+
`seq > last_seq` and advanced the watermark to the highest seq it saw, so a batch whose seq
|
|
29
|
+
block was reserved first but committed second was skipped for good — the same silent loss as
|
|
30
|
+
above, and present on a replica set too. Once a replica set is required it is also redundant:
|
|
31
|
+
`consume: capture_new` without a `cursor_id` is ephemeral fan-out from now on, and reads
|
|
32
|
+
arbitrary collections rather than only the bridge's own wrapped documents. The deprecated
|
|
33
|
+
`change_stream: true` boolean now resolves to `capture_new` instead of `subscriber`.
|
|
34
|
+
- ZeroMQ `format` defaults to **`raw_framed`** instead of `json`: binary-safe payloads with
|
|
35
|
+
a JSON metadata frame in front, so headers still travel. This is a wire-format change —
|
|
36
|
+
a 0.4 peer and a 0.3 peer no longer interoperate on the same socket unless one sets
|
|
37
|
+
`format: json`.
|
|
38
|
+
- ZeroMQ `backend` defaults to **`try_omq`**, which uses the faster omq backend when the
|
|
39
|
+
`zeromq-omq` feature is compiled in and falls back to `zmq` otherwise. Naming `omq` or
|
|
40
|
+
`zmq` explicitly still makes that backend a hard requirement.
|
|
41
|
+
- `extensions::register_endpoint_factory` and `register_middleware_factory` return
|
|
42
|
+
`anyhow::Result<()>` instead of `()`, and registering a name that is already taken is now an
|
|
43
|
+
error instead of silently replacing the previous factory. A duplicate name meant one of the
|
|
44
|
+
two registrations was quietly ignored, which is impossible to diagnose from a route that then
|
|
45
|
+
behaves like the wrong endpoint. Existing callers add `?` or `.unwrap()`; anything that relied
|
|
46
|
+
on re-registering the same name must pick distinct names.
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
|
|
50
|
+
- MongoDB `consume: snapshot` — a one-shot, non-destructive read that pages the collection by
|
|
51
|
+
`_id` and ends the route on drain. It needs no replica set, reads arbitrary collections, and is
|
|
52
|
+
the supported way to read a standalone `mongod` without deleting anything. Its contract is
|
|
53
|
+
deliberately narrow: it delivers what exists when the run starts, and it is **not** a tail.
|
|
54
|
+
`cursor_id` is rejected at startup — resuming above a stored `_id` would skip whatever a
|
|
55
|
+
concurrent writer commits below that mark, and `_id` is assigned client-side before the insert,
|
|
56
|
+
so it does not follow commit order. Incremental reads need commit order, i.e. the oplog, i.e. a
|
|
57
|
+
replica set.
|
|
58
|
+
- gRPC consumers can call arbitrary unary and server-streaming services without generated
|
|
59
|
+
Rust clients. Point an endpoint at a compiled protobuf `FileDescriptorSet`, name the
|
|
60
|
+
service and method, and provide the request as JSON; responses are decoded dynamically
|
|
61
|
+
with `prost-reflect` and emitted using protobuf's canonical JSON representation. The
|
|
62
|
+
existing generated `mqbridge.Bridge` protocol remains the default.
|
|
63
|
+
- The omq ZeroMQ backend covers **REQ/REP** as well as PUSH/PULL and PUB/SUB, so the whole
|
|
64
|
+
`zeromq` endpoint surface — including request-reply — works on either backend. REQ exchanges
|
|
65
|
+
are serialised and bounded by `request_timeout_ms`, and a timed-out socket is rebuilt rather
|
|
66
|
+
than reused, because ZMTP requires strict send/recv alternation.
|
|
67
|
+
- Custom endpoints and middleware can be written in Python and Node.js, not just Rust —
|
|
68
|
+
`register_endpoint` / `register_middleware` in both bindings, with the same batch, ack and
|
|
69
|
+
request-reply semantics as a Rust `CustomEndpointFactory`. See [EXTENDING.md](docs/EXTENDING.md).
|
|
70
|
+
- Native endpoint plugins. An endpoint can live in its own crate and package and be loaded
|
|
71
|
+
into any mq-bridge process at runtime — `mq_bridge::plugin::load_endpoint_plugin(path)` in
|
|
72
|
+
Rust, `mq_bridge.load_endpoint_plugin(path)` in Python, `loadEndpointPlugin(path)` in
|
|
73
|
+
Node.js — so a broker's dependencies stay out of curated mq-bridge builds while every
|
|
74
|
+
language runs the same implementation and delivery semantics. The `plugin` feature (part of
|
|
75
|
+
`full` and `portable`) provides the loader; `plugin-sdk` provides the authoring side:
|
|
76
|
+
`export_endpoint_plugin!`, which exports an ordinary `CustomEndpointFactory` through the
|
|
77
|
+
stable C ABI with no handwritten `unsafe`, and a conformance suite to run against the
|
|
78
|
+
endpoint both linked directly and loaded as a plugin. A plugin can provide a
|
|
79
|
+
middleware too (`export_middleware_plugin!`, or `middleware:` alongside an
|
|
80
|
+
endpoint): it returns one entry per message — `None` drops it — while the
|
|
81
|
+
wrapper around the endpoint stays on the host side, so nothing calls back
|
|
82
|
+
across the boundary. See [PLUGINS.md](docs/PLUGINS.md).
|
|
83
|
+
|
|
84
|
+
### Fixed
|
|
85
|
+
|
|
86
|
+
- The built-in `mqbridge.Bridge` gRPC transport now commits messages with real ACK/NACK
|
|
87
|
+
RPCs instead of a no-op. Embedded publishers wait for downstream processing to commit
|
|
88
|
+
before receiving an ACK, and unacknowledged subscription messages are retained in memory
|
|
89
|
+
and redelivered to the same `consumer_id`. This provides at-least-once delivery while the
|
|
90
|
+
server process is running; durable restart recovery and exactly-once processing still
|
|
91
|
+
require persistent state or downstream deduplication by message ID. Arbitrary dynamic
|
|
92
|
+
services retain the delivery semantics of their own API because protobuf descriptors do
|
|
93
|
+
not define a generic acknowledgement operation.
|
|
94
|
+
Retention is capped (1024 messages per subscriber, 64 subscribers per route, oldest
|
|
95
|
+
evicted first) so a consumer that never acknowledges cannot grow the server without bound.
|
|
96
|
+
`consumer_id` defaults to a fresh id per consumer rather than to the topic, so competing
|
|
97
|
+
consumers on one topic no longer share a retention set; set it explicitly to be
|
|
98
|
+
redelivered unacknowledged messages after a reconnect.
|
|
99
|
+
- A **non-retryable handler failure no longer discards the rest of its batch**. The default
|
|
100
|
+
`Handler::handle_many` aborted the remaining messages after any failure; for retryable and
|
|
101
|
+
connection errors that is right (the batch is nacked and redelivered together), but a
|
|
102
|
+
non-retryable message is dropped and never redelivered, so every healthy message behind it
|
|
103
|
+
was silently lost. How many depended purely on `batch_size` — at the old default of 1 the
|
|
104
|
+
collateral was zero, which is why this went unnoticed. The behaviour now matches what
|
|
105
|
+
`CommandPublisher::send_batch` already documented and tested.
|
|
106
|
+
- ZeroMQ REQ/REP with `format: raw` or `raw_framed` decoded the reply using that format, but the
|
|
107
|
+
REP side always answers with a JSON array of canonical messages, so the caller got one message
|
|
108
|
+
whose payload was the JSON text instead of the decoded replies. Both backends now decode replies
|
|
109
|
+
as JSON. This was invisible while `json` was the default format.
|
|
110
|
+
|
|
111
|
+
## 0.3.10
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
### Changed
|
|
115
|
+
|
|
116
|
+
- DLQ and output middleware now run around the publish step, not inside the handler, so a
|
|
117
|
+
handler failure is no longer retried by the output chain. The tradeoff: a handler failure
|
|
118
|
+
now skips the output middleware entirely, so `dlq` on the output endpoint cannot capture
|
|
119
|
+
it — only publish failures reach the DLQ. Put a `dlq` on the input endpoint to catch
|
|
120
|
+
handler failures.
|
|
121
|
+
- Errors carry their full cause chain instead of only the outermost context.
|
|
122
|
+
- `deduplication` on an **output** endpoint is now a startup error instead of a warning and a
|
|
123
|
+
silent no-op. Move it to the route's input endpoint.
|
|
124
|
+
- `limiter` paces a single `send_batch` by its own message count, so one large batch is no
|
|
125
|
+
longer a free burst. Sustained throughput is unchanged.
|
|
126
|
+
- A `message_id` that is neither a UUID nor a `u128` is hashed to a stable id rather than
|
|
127
|
+
making the whole JSON envelope unparseable.
|
|
128
|
+
|
|
129
|
+
### Performance
|
|
130
|
+
|
|
131
|
+
- **Kafka consumer**: a long-lived prefetch task reads librdkafka continuously into a bounded
|
|
132
|
+
channel, instead of rebuilding the stream inside every `receive_batch`. librdkafka only keeps
|
|
133
|
+
requesting records while its queue is drained, so every pause the pipeline took — a transform,
|
|
134
|
+
a slow sink — was also a pause in fetching, and the fetch rate collapsed to well under what the
|
|
135
|
+
broker could serve. Batch offsets are also recorded once per partition rather than once per
|
|
136
|
+
message, which was O(n²) in the batch and allocated two `CString`s per record.
|
|
137
|
+
Kafka → transform → file: **192,854 → 824,983 rows/s** on the 1M-row, four-partition
|
|
138
|
+
benchmark, from 0.35x to 1.51x Arroyo on identical output. A 16,384-message passthrough
|
|
139
|
+
batch went from 11.5s to 2.2s, and from 10.4s to 0.9s of CPU.
|
|
140
|
+
- **Postgres / sqlx**: `test_before_acquire(false)` on the pool, zero-copy row encoding via
|
|
141
|
+
a prebuilt `JsonRowSchema`, and prebuilt first/next page queries on the cursor path.
|
|
142
|
+
- **Command handler**: `send_batch` no longer loops per-message `send()` (≈8x on batched routes).
|
|
143
|
+
- **File**: single-pass byte-array decode, faster CSV writes, compression sniffing.
|
|
144
|
+
- **Deduplication**: the two-phase reserve/commit no longer writes to the store twice per
|
|
145
|
+
message. Reservations are held in memory — sled takes an exclusive file lock on its directory,
|
|
146
|
+
so a claim only ever has to be visible to this process — leaving one write per message, on
|
|
147
|
+
commit.
|
|
148
|
+
|
|
149
|
+
### Fixed
|
|
150
|
+
|
|
151
|
+
- `insert_query` batch inserts dropped anything but a bare token from the `VALUES` tuple, so
|
|
152
|
+
`decode(${payload:x}, 'base64')` and casts were silently discarded — a binary (`bytea`)
|
|
153
|
+
column could not be written. The batch path now keeps the user's SQL and falls back to
|
|
154
|
+
iterative inserts when the tuple contains an expression.
|
|
155
|
+
- A payload string containing an embedded NUL byte was dropped by the driver and stored as
|
|
156
|
+
SQL `NULL` while the route reported success. It is now rejected as non-retryable.
|
|
157
|
+
- Database errors were rendered twice, because `sqlx` errors already display their own
|
|
158
|
+
source. Cause chains now skip a link an earlier one already contains.
|
|
159
|
+
- `cookie_jar`'s `inject_metadata` resolved only a bare stored name, so the namespaced
|
|
160
|
+
`cookie.<name>` / `value.<name>` spelling that `export_metadata_prefix` reports back
|
|
161
|
+
injected nothing. Both spellings now work.
|
|
162
|
+
- MQTT publishes are confirmed by PUBACK/PUBCOMP and guarded against session resets, which
|
|
163
|
+
took chaos-test message loss to zero.
|
|
164
|
+
- Postgres CDC advances its replication slot durably on shutdown instead of leaving the
|
|
165
|
+
feedback unflushed.
|
|
166
|
+
- `deduplication` could silently drop a message after a crash. The reservation was written to
|
|
167
|
+
the store *before* the message was processed, so a redelivery arriving within the 5s pending
|
|
168
|
+
TTL was classified as a duplicate and acked — without ever having been written to the sink.
|
|
169
|
+
Reservations are now in-memory and die with the process, so the redelivery is reprocessed.
|
|
170
|
+
- A Kafka record with no value — a tombstone, which is ordinary traffic on a compacted topic —
|
|
171
|
+
failed the whole batch. Its offset was never committed, so the route reconnected onto the same
|
|
172
|
+
record forever: one tombstone wedged the consumer permanently, and a compacted topic could not
|
|
173
|
+
be consumed at all. Tombstones now arrive as an empty payload flagged `mqb.kafka.tombstone`.
|
|
174
|
+
- `--drain` on a Kafka source could report success having copied only part of a topic, or none
|
|
175
|
+
of it. An idle wait was taken to mean "source exhausted", but an idle channel means nothing on
|
|
176
|
+
its own: before the first fetch lands, or in an ordinary gap between fetches, it looks exactly
|
|
177
|
+
the same as the end of the data. The shorter the idle timeout the more went missing — at 1ms a
|
|
178
|
+
1,000,000-row topic landed 0 rows, and the copy still exited successfully. A drain now
|
|
179
|
+
completes only once every assigned partition has reached the offset it held when the drain
|
|
180
|
+
began, and lands all 1,000,000 rows at every idle timeout including 0.
|
|
181
|
+
- Drain no longer hangs on an empty source, and reconnect attempts are bounded.
|
|
182
|
+
- CSV reader handles quoted newlines; file endpoints fail fast on an unopenable path.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# mq-bridge Project Context
|
|
2
2
|
|
|
3
3
|
> **Looking for what middleware or structural endpoints exist, and how to configure them?**
|
|
4
|
-
> [REFERENCE.md](REFERENCE.md) is the complete, authoritative list — every middleware
|
|
5
|
-
> (`retry`, `dlq`, `transform`, `deduplication`, `weak_join`, `buffer`, `limiter`, `delay`,
|
|
4
|
+
> [REFERENCE.md](docs/REFERENCE.md) is the complete, authoritative list — every middleware
|
|
5
|
+
> (`retry`, `dlq`, `transform`, `id`, `deduplication`, `weak_join`, `buffer`, `limiter`, `delay`,
|
|
6
6
|
> `cookie_jar`, `encryption`, `compression`, `metrics`, `random_panic`, `custom`) and every structural endpoint (`ref`,
|
|
7
7
|
> `fanout`, `switch`, `request`, `response`, `reader`, `static`, `stream_buffer`, `null`,
|
|
8
8
|
> `custom`), each with its fields, defaults, and a working YAML example. Do not infer these
|
|
@@ -79,6 +79,7 @@ src/
|
|
|
79
79
|
│ ├── delay.rs # Artificial delay
|
|
80
80
|
│ ├── dlq.rs # Dead-letter queue
|
|
81
81
|
│ ├── encryption.rs # AEAD payload encryption
|
|
82
|
+
│ ├── id.rs # Replay-stable business identity into `mqb.id`
|
|
82
83
|
│ ├── limiter.rs # Throughput limiting (msg/s)
|
|
83
84
|
│ ├── metrics.rs # Metrics collection
|
|
84
85
|
│ ├── random_panic.rs # Testing middleware
|