mq-bridge-py-basic 0.3.8__tar.gz → 0.3.9__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.
Files changed (263) hide show
  1. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/.gitignore +4 -0
  2. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/Cargo.lock +30 -10
  3. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/Cargo.toml +2 -2
  4. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/PKG-INFO +1 -1
  5. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/README.md +9 -4
  6. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/REFERENCE.md +70 -34
  7. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/benches/ETL_BENCHMARKS.md +5 -5
  8. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/mq-bridge.schema.json +20 -5
  9. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/mq_bridge/config.pyi +30 -0
  10. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/Cargo.toml +17 -2
  11. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/src/lib.rs +70 -9
  12. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/httparena/README.md +1 -1
  13. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/httparena/frameworks/mq-bridge-py/server.py +1 -1
  14. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/checkpoint.rs +24 -5
  15. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/clickhouse.rs +4 -3
  16. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/file/mod.rs +222 -57
  17. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/file/tests.rs +275 -0
  18. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/http/publisher.rs +23 -1
  19. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/http/stream.rs +9 -5
  20. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/memory/framed.rs +81 -13
  21. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/mod.rs +3 -2
  22. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/mongodb/consumer.rs +14 -9
  23. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/mongodb/readers.rs +24 -13
  24. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/nats.rs +33 -2
  25. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/object_store.rs +31 -24
  26. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/postgres/mod.rs +69 -21
  27. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/postgres/replication.rs +83 -23
  28. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/redis_streams.rs +130 -19
  29. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/sqlx/dedup.rs +23 -3
  30. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/sqlx/mod.rs +160 -40
  31. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/sqlx/tests.rs +40 -0
  32. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/structural/reader.rs +17 -2
  33. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/structural/stream_buffer.rs +34 -13
  34. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/zeromq/omq.rs +12 -3
  35. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/zeromq/zmq.rs +25 -0
  36. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/errors.rs +18 -2
  37. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/lib.rs +4 -1
  38. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/deduplication.rs +187 -14
  39. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/dlq.rs +141 -2
  40. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/encryption.rs +133 -24
  41. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/retry.rs +90 -5
  42. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/transform/schema.rs +3 -5
  43. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/models.rs +32 -3
  44. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/route.rs +34 -2
  45. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/support/compression.rs +1 -1
  46. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/support/connection_registry.rs +3 -3
  47. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/support/crypto.rs +3 -5
  48. mq_bridge_py_basic-0.3.9/src/support/crypto_envelope.rs +17 -0
  49. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/support/mod.rs +1 -0
  50. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/traits.rs +6 -0
  51. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/mariadb.rs +16 -0
  52. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/mod.rs +32 -0
  53. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/mongodb.rs +40 -1
  54. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/mysql.rs +137 -0
  55. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/nats.rs +48 -0
  56. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/object_store.rs +102 -0
  57. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/postgres_cdc.rs +113 -0
  58. mq_bridge_py_basic-0.3.9/tests/integration/redis_streams.rs +434 -0
  59. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration_test.rs +95 -0
  60. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/reference_docs_test.rs +134 -177
  61. mq_bridge_py_basic-0.3.8/tests/integration/redis_streams.rs +0 -227
  62. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  63. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  64. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  65. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/.github/workflows/benchmark.yml +0 -0
  66. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/.github/workflows/ci.yml +0 -0
  67. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/.github/workflows/ibm-mq.yml +0 -0
  68. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/.github/workflows/node.yml +0 -0
  69. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/.github/workflows/publish-node.yml +0 -0
  70. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/.github/workflows/publish-python.yml +0 -0
  71. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/.github/workflows/python.yml +0 -0
  72. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/.github/workflows/release.yml +0 -0
  73. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/.github/workflows/test-matrix.yml +0 -0
  74. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/ARCHITECTURE.md +0 -0
  75. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/CLAUDE.md +0 -0
  76. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/CONFIGURATION.md +0 -0
  77. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/CONTRIBUTING.md +0 -0
  78. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/LICENSE +0 -0
  79. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/LICENSE.python +0 -0
  80. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/benches/performance_bench.rs +0 -0
  81. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/benches/router_bench.rs +0 -0
  82. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/benches/zeromq_backends.rs +0 -0
  83. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/bindings-common/Cargo.toml +0 -0
  84. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/bindings-common/src/lib.rs +0 -0
  85. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/bindings-common/src/logging.rs +0 -0
  86. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/build.rs +0 -0
  87. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/examples/ipc_worker_queue.yaml +0 -0
  88. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/mq_bridge/__init__.py +0 -0
  89. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/mq_bridge/__init__.pyi +0 -0
  90. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/mq_bridge/config.py +0 -0
  91. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/mq_bridge/py.typed +0 -0
  92. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/package-lock.json +0 -0
  93. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/pyproject.toml +0 -0
  94. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/LICENSE.python +0 -0
  95. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/README.md +0 -0
  96. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/analysis/bench_http_native.py +0 -0
  97. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/example.py +0 -0
  98. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/examples/bench_memory.py +0 -0
  99. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/examples/bench_memory.yaml +0 -0
  100. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/examples/consume_pull.py +0 -0
  101. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/examples/dlt_source.py +0 -0
  102. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/examples/json_route.py +0 -0
  103. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/examples/memory.yaml +0 -0
  104. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/examples/raw_route.py +0 -0
  105. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/pyproject-basic.toml +0 -0
  106. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/pyproject-reduced.toml +0 -0
  107. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/scripts/gen_config_types.py +0 -0
  108. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/tests/test_config_types.py +0 -0
  109. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/tests/test_logging.py +0 -0
  110. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/tests/test_packaging.py +0 -0
  111. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/tests/test_performance_smoke.py +0 -0
  112. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/tests/test_public_api.py +0 -0
  113. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/tests/test_routes.py +0 -0
  114. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/python/mq-bridge-py/uv.lock +0 -0
  115. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/analysis/benches/metadata_bench.rs +0 -0
  116. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/analysis/debug_ibm_mq_tls.rs +0 -0
  117. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/analysis/http/analyze_xctrace_time_profile.py +0 -0
  118. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/analysis/http/http_flamegraph.py +0 -0
  119. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/analysis/http/mq_bridge_http_profile.rs +0 -0
  120. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/analysis/http/run_http_ladder.sh +0 -0
  121. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/ci/format_bench_output.sh +0 -0
  122. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/httparena/frameworks/mq-bridge-py/Dockerfile +0 -0
  123. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/httparena/frameworks/mq-bridge-py/meta.json +0 -0
  124. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/techempower/Python/mq-bridge-py/README.md +0 -0
  125. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/techempower/Python/mq-bridge-py/benchmark_config.json +0 -0
  126. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/techempower/Python/mq-bridge-py/mq-bridge-py.dockerfile +0 -0
  127. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/techempower/Python/mq-bridge-py/server.py +0 -0
  128. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/techempower/README.md +0 -0
  129. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/techempower/postgres.yml +0 -0
  130. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/techempower/seed.sql +0 -0
  131. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/techempower/verify.sh +0 -0
  132. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/the-benchmarker/README.md +0 -0
  133. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/the-benchmarker/python/mq-bridge-py/config.yaml +0 -0
  134. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/the-benchmarker/python/mq-bridge-py/pyproject.toml +0 -0
  135. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/scripts/the-benchmarker/python/mq-bridge-py/server.py +0 -0
  136. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/canonical_message.rs +0 -0
  137. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/command_handler.rs +0 -0
  138. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/amqp.rs +0 -0
  139. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/aws.rs +0 -0
  140. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/grpc.proto +0 -0
  141. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/grpc.rs +0 -0
  142. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/http/mod.rs +0 -0
  143. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/http/tests.rs +0 -0
  144. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/ibm_mq.rs +0 -0
  145. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/kafka.rs +0 -0
  146. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/memory/endpoint.rs +0 -0
  147. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/memory/ipc_unix.rs +0 -0
  148. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/memory/ipc_windows.rs +0 -0
  149. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/memory/memory_transport.rs +0 -0
  150. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/memory/mod.rs +0 -0
  151. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/memory/transport.rs +0 -0
  152. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/mongodb/dedup.rs +0 -0
  153. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/mongodb/mod.rs +0 -0
  154. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/mongodb/publisher.rs +0 -0
  155. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/mongodb/tests.rs +0 -0
  156. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/mqtt.rs +0 -0
  157. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/poll.rs +0 -0
  158. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/postgres/VENDORED.md +0 -0
  159. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/postgres/pgoutput/decoder.rs +0 -0
  160. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/postgres/pgoutput/messages.rs +0 -0
  161. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/postgres/pgoutput/mod.rs +0 -0
  162. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/postgres/pgoutput/registry.rs +0 -0
  163. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/postgres/pgoutput/values.rs +0 -0
  164. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/postgres/state.rs +0 -0
  165. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/sled.rs +0 -0
  166. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/structural/fanout.rs +0 -0
  167. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/structural/mod.rs +0 -0
  168. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/structural/null.rs +0 -0
  169. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/structural/request.rs +0 -0
  170. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/structural/response.rs +0 -0
  171. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/structural/static_endpoint.rs +0 -0
  172. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/structural/switch.rs +0 -0
  173. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/websocket.rs +0 -0
  174. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/zeromq/codec.rs +0 -0
  175. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/endpoints/zeromq/mod.rs +0 -0
  176. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/event_handler.rs +0 -0
  177. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/event_store.rs +0 -0
  178. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/extensions.rs +0 -0
  179. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/buffer.rs +0 -0
  180. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/compression.rs +0 -0
  181. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/cookie_jar.rs +0 -0
  182. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/delay.rs +0 -0
  183. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/limiter.rs +0 -0
  184. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/metrics.rs +0 -0
  185. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/mod.rs +0 -0
  186. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/random_panic.rs +0 -0
  187. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/transform/coerce.rs +0 -0
  188. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/transform/compiled.rs +0 -0
  189. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/transform/error.rs +0 -0
  190. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/transform/mod.rs +0 -0
  191. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/transform/path.rs +0 -0
  192. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/transform/tests.rs +0 -0
  193. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/middleware/weak_join.rs +0 -0
  194. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/outcomes.rs +0 -0
  195. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/publisher.rs +0 -0
  196. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/response.rs +0 -0
  197. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/support/interpolation.rs +0 -0
  198. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/test_utils.rs +0 -0
  199. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/src/type_handler.rs +0 -0
  200. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/README.md +0 -0
  201. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/armature_integration.rs +0 -0
  202. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/amqp.rs +0 -0
  203. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/aws.rs +0 -0
  204. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/clickhouse.rs +0 -0
  205. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/config.toml +0 -0
  206. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/amqp.yml +0 -0
  207. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/aws.yml +0 -0
  208. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/clickhouse.yml +0 -0
  209. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/ibm-mq-certs/client.crl +0 -0
  210. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/ibm-mq-certs/client.kdb +0 -0
  211. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/ibm-mq-certs/client.p12 +0 -0
  212. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/ibm-mq-certs/client.rdb +0 -0
  213. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/ibm-mq-certs/client.sth +0 -0
  214. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/ibm_mq.yml +0 -0
  215. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/ibm_mq_tls.yml +0 -0
  216. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/kafka-tls.yml +0 -0
  217. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/kafka.yml +0 -0
  218. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/mariadb.yml +0 -0
  219. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/mongodb-replica.yml +0 -0
  220. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/mongodb-tls.yml +0 -0
  221. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/mongodb.yml +0 -0
  222. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/mosquitto.conf +0 -0
  223. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/mosquitto_performance.conf +0 -0
  224. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/mosquitto_persistence.conf +0 -0
  225. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/mq_init.mqsc +0 -0
  226. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/mq_init_tls.mqsc +0 -0
  227. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/mqtt.yml +0 -0
  228. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/mqtt_performance.yml +0 -0
  229. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/mysql.yml +0 -0
  230. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/nats.yml +0 -0
  231. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/object_store.yml +0 -0
  232. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/postgres.yml +0 -0
  233. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/postgres_cdc.yml +0 -0
  234. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/docker-compose/redis.yml +0 -0
  235. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/file.rs +0 -0
  236. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/grpc.rs +0 -0
  237. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/grpc_tls.rs +0 -0
  238. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/http.rs +0 -0
  239. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/http_tls.rs +0 -0
  240. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/ibm_mq.rs +0 -0
  241. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/ibm_mq_tls.rs +0 -0
  242. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/ipc.rs +0 -0
  243. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/kafka.rs +0 -0
  244. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/kafka_tls.rs +0 -0
  245. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/logic_test.rs +0 -0
  246. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/memory.rs +0 -0
  247. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/mongodb_raw.rs +0 -0
  248. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/mongodb_tls.rs +0 -0
  249. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/mqtt.rs +0 -0
  250. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/performance_static.rs +0 -0
  251. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/postgres.rs +0 -0
  252. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/route.rs +0 -0
  253. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/scripts/gen_certs.sh +0 -0
  254. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/sqlite.rs +0 -0
  255. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/tls_helpers.rs +0 -0
  256. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/websocket.rs +0 -0
  257. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/integration/zeromq.rs +0 -0
  258. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/memory_leak_test.rs +0 -0
  259. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/ref_test.rs +0 -0
  260. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/sqlite_test.rs +0 -0
  261. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/tls_example.rs +0 -0
  262. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/unit_tests.md +0 -0
  263. {mq_bridge_py_basic-0.3.8 → mq_bridge_py_basic-0.3.9}/tests/websocket_test.rs +0 -0
@@ -48,3 +48,7 @@ tests/**/*.pkcs12
48
48
  .pytest_cache/
49
49
  python/mq-bridge-py/.venv/
50
50
  python/mq-bridge-py/dist/
51
+
52
+ # Local build setup (shared cargo target dir with mq-bridge-app), not for git
53
+ .cargo/
54
+ .vscode/
@@ -2976,6 +2976,15 @@ dependencies = [
2976
2976
  "windows-link",
2977
2977
  ]
2978
2978
 
2979
+ [[package]]
2980
+ name = "libmimalloc-sys"
2981
+ version = "0.1.49"
2982
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2983
+ checksum = "6a45a52f43e1c16f667ccfe4dd8c85b7f7c204fd5e3bf46c5b0db9a5c3c0b8e9"
2984
+ dependencies = [
2985
+ "cc",
2986
+ ]
2987
+
2979
2988
  [[package]]
2980
2989
  name = "libmqm-constants"
2981
2990
  version = "0.8.4"
@@ -3200,6 +3209,15 @@ dependencies = [
3200
3209
  "sketches-ddsketch",
3201
3210
  ]
3202
3211
 
3212
+ [[package]]
3213
+ name = "mimalloc"
3214
+ version = "0.1.52"
3215
+ source = "registry+https://github.com/rust-lang/crates.io-index"
3216
+ checksum = "2d4139bb28d14ad1facf21d5eb8825051b326e172d216b39f6d31df53cc97862"
3217
+ dependencies = [
3218
+ "libmimalloc-sys",
3219
+ ]
3220
+
3203
3221
  [[package]]
3204
3222
  name = "mime"
3205
3223
  version = "0.3.17"
@@ -3330,7 +3348,7 @@ dependencies = [
3330
3348
 
3331
3349
  [[package]]
3332
3350
  name = "mq-bridge"
3333
- version = "0.3.8"
3351
+ version = "0.3.9"
3334
3352
  dependencies = [
3335
3353
  "aes-gcm",
3336
3354
  "anyhow",
@@ -3411,7 +3429,7 @@ dependencies = [
3411
3429
 
3412
3430
  [[package]]
3413
3431
  name = "mq-bridge-bindings-common"
3414
- version = "0.3.8"
3432
+ version = "0.3.9"
3415
3433
  dependencies = [
3416
3434
  "anyhow",
3417
3435
  "fast-uuid-v7",
@@ -3425,12 +3443,13 @@ dependencies = [
3425
3443
 
3426
3444
  [[package]]
3427
3445
  name = "mq-bridge-node"
3428
- version = "0.3.8"
3446
+ version = "0.3.9"
3429
3447
  dependencies = [
3430
3448
  "anyhow",
3431
3449
  "async-trait",
3432
3450
  "bytes",
3433
3451
  "fast-uuid-v7",
3452
+ "mimalloc",
3434
3453
  "mq-bridge",
3435
3454
  "mq-bridge-bindings-common",
3436
3455
  "napi",
@@ -3446,12 +3465,13 @@ dependencies = [
3446
3465
 
3447
3466
  [[package]]
3448
3467
  name = "mq-bridge-py"
3449
- version = "0.3.8"
3468
+ version = "0.3.9"
3450
3469
  dependencies = [
3451
3470
  "anyhow",
3452
3471
  "async-trait",
3453
3472
  "bytes",
3454
3473
  "fast-uuid-v7",
3474
+ "mimalloc",
3455
3475
  "mq-bridge",
3456
3476
  "mq-bridge-bindings-common",
3457
3477
  "pyo3",
@@ -3725,9 +3745,9 @@ dependencies = [
3725
3745
 
3726
3746
  [[package]]
3727
3747
  name = "omq-proto"
3728
- version = "0.24.1"
3748
+ version = "0.25.0"
3729
3749
  source = "registry+https://github.com/rust-lang/crates.io-index"
3730
- checksum = "c9335ef21d570294464c491837af5477caddb05cf3c7223af1c4341a127e6035"
3750
+ checksum = "856d18f6b58f39153fcf0b574efe3f04362ff44d3a46829eb984c1f9ef2d121c"
3731
3751
  dependencies = [
3732
3752
  "bytes",
3733
3753
  "patricia_tree",
@@ -3739,9 +3759,9 @@ dependencies = [
3739
3759
 
3740
3760
  [[package]]
3741
3761
  name = "omq-tokio"
3742
- version = "0.20.1"
3762
+ version = "0.20.3"
3743
3763
  source = "registry+https://github.com/rust-lang/crates.io-index"
3744
- checksum = "4a9d9c6caa88d29df5b9dc9638ea9f0f33b087ecc0f149b70e61149f97bcdb80"
3764
+ checksum = "98aaa33702e7d723de268dd9fe725f93d469afef3f1bedb14cfa7f579f61a7b7"
3745
3765
  dependencies = [
3746
3766
  "arc-swap",
3747
3767
  "bytes",
@@ -7191,9 +7211,9 @@ dependencies = [
7191
7211
 
7192
7212
  [[package]]
7193
7213
  name = "yring"
7194
- version = "0.3.10"
7214
+ version = "0.3.11"
7195
7215
  source = "registry+https://github.com/rust-lang/crates.io-index"
7196
- checksum = "39146d2147cfb9f71b9f071f93f7b5dbcfb28eee528dafcaf5f500f4917cb69f"
7216
+ checksum = "f8545becda6379f37e13fbdf5d9de464849bdd1565a995368648f11fe9d96d13"
7197
7217
  dependencies = [
7198
7218
  "loom",
7199
7219
  ]
@@ -16,7 +16,7 @@ members = ["bindings-common", "python/mq-bridge-py"]
16
16
  resolver = "2"
17
17
 
18
18
  [workspace.package]
19
- version = "0.3.8"
19
+ version = "0.3.9"
20
20
 
21
21
  [workspace.dependencies]
22
22
  anyhow = "1.0"
@@ -210,7 +210,7 @@ float-roundtrip = ["serde_json/float_roundtrip"]
210
210
  # runtime the client is loaded lazily only when an ibm-mq endpoint is opened
211
211
  # (clear error if the client isn't installed). Use `ibm-mq-static` instead for
212
212
  # static linking.
213
- full = ["middleware", "mongodb", "kafka", "amqp", "nats", "mqtt", "http", "aws", "zeromq", "redis-streams", "sled", "grpc", "sqlx", "clickhouse", "websocket", "postgres-cdc", "object-store", "rustls-aws-lc", "ibm-mq"]
213
+ full = ["middleware", "mongodb", "kafka", "amqp", "nats", "mqtt", "http", "aws", "zeromq", "zeromq-omq", "redis-streams", "sled", "grpc", "sqlx", "clickhouse", "websocket", "postgres-cdc", "object-store", "rustls-aws-lc", "ibm-mq"]
214
214
 
215
215
  # Endpoints that build across most OS targets (glibc/musl/Alpine, macOS,
216
216
  # Windows, aarch64/armv7) without a special toolchain — no librdkafka, protoc,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mq-bridge-py-basic
3
- Version: 0.3.8
3
+ Version: 0.3.9
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: License :: OSI Approved :: MIT License
6
6
  Classifier: Programming Language :: Python :: 3
@@ -33,7 +33,7 @@ If you need to move data reliably between systems and you write code (Rust, Pyth
33
33
  * **TLS everywhere, one config shape**: a single `TlsConfig` block (CA bundle, client cert/key for mTLS, insecure-skip) is reused across transports.
34
34
  * **Self-hosted, no daemon**: generate config in the optional UI, paste it into your code, run it in-process. No hosted control plane, no separate scheduler.
35
35
 
36
- > **Throughput & footprint.** In our own benchmarks, the same engine — driven the zero-code way through [`mq-bridge-app`](https://github.com/marcomq/mq-bridge-app) — sustained ~267,000 rows/s copying 1,000,000 rows from Postgres to JSONL on commodity hardware at **~20 MiB peak RSS**, keeping it well in the range of dedicated data-movement tools. On a CSV→JSONL file conversion (1,000,000 mixed-type rows, ~116 MiB), it sustained **833,333 rows/s** at the same ~20 MiB, about **~43x faster** and **~22x leaner in memory** than Meltano (`tap-csv` → `target-jsonl`, ~19,500 rows/s / ~444 MiB). Full setup, methodology, and the exact parameters are in [`benches/ETL_BENCHMARKS.md`](benches/ETL_BENCHMARKS.md).
36
+ > **Throughput & footprint.** In our own benchmarks, the same engine — driven the zero-code way through [`mq-bridge-app`](https://github.com/marcomq/mq-bridge-app) — on a CSV→JSONL file conversion (1,000,000 mixed-type rows, ~116 MiB) sustained **1,133,786 rows/s** at ~22 MiB, about **~58x faster** and **~20x leaner in memory** than Meltano (`tap-csv` → `target-jsonl`, ~19,500 rows/s / ~444 MiB). Full setup, methodology, and the exact parameters are in [`benches/ETL_BENCHMARKS.md`](benches/ETL_BENCHMARKS.md).
37
37
 
38
38
 
39
39
  ## Language Bindings
@@ -306,9 +306,14 @@ server-side (default one-hour window) — `insert_deduplication_token` lets you
306
306
  mq-bridge does not set one, so rely on `ReplacingMergeTree` for logical dedup and treat block-level
307
307
  dedup only as retry-safety.
308
308
 
309
- **Postgres CDC — deterministic id + `postgres.key`.** The `postgres_cdc` source already resumes from a
310
- durable LSN checkpoint (no re-delivery on clean restart). For the crash window (row written, then a
311
- crash before the checkpoint flush) it is at-least-once, so make the sink idempotent. Each change event
309
+ **Postgres CDC — deterministic id + `postgres.key`.** The `postgres_cdc` source resumes from the slot's
310
+ durable `confirmed_flush_lsn`. In-band standby feedback is asynchronous and is *not* flushed when the
311
+ stream stops, so the last acks are made durable by the consumer's `Drop`, which stops the stream and
312
+ advances the slot synchronously. Re-delivery is therefore avoided only on a restart that actually runs
313
+ that teardown — a host process that exits without dropping the route (or one on a current-thread Tokio
314
+ runtime, where the blocking advance is skipped) replays everything since the last asynchronous feedback
315
+ tick. Set `checkpoint_store` to a `file://` path for a second, per-ack durable position that survives
316
+ teardown regardless. Treat the source as at-least-once and make the sink idempotent. Each change event
312
317
  carries the full row (so the primary key is in the payload), `postgres.lsn` (a monotonic version),
313
318
  `postgres.operation`/`schema`/`table`, and — when the table has a primary key / replica identity —
314
319
  `postgres.key` (the key value). The event's `message_id` is a stable hash of `schema.table + key +
@@ -17,7 +17,7 @@ endpoints, shape routing, or terminate a request. Data endpoints (`kafka`, `nats
17
17
  Middleware attaches to an endpoint via a `middlewares:` list, on the **input**, the
18
18
  **output**, or both:
19
19
 
20
- ```yaml
20
+ ```yaml route
21
21
  my_route:
22
22
  input:
23
23
  middlewares:
@@ -38,6 +38,11 @@ layer and sees the failures of the ones before it.** Put `dlq` last.
38
38
  **Input (consumer) middlewares are applied in reverse, so the *first* entry is outermost**
39
39
  and runs first on an incoming message.
40
40
 
41
+ **Consequence: a route that reads back what another route wrote needs the *reversed* list.**
42
+ Writing with `[compression, encryption]` produces `compress(encrypt(payload))`; a reader
43
+ given that same list would try to decrypt first and fail. The reading route must say
44
+ `[encryption, compression]`. The lists mirror — they are not copied.
45
+
41
46
  > This is asserted by `route::tests::test_dlq_and_retry_batch_integration`,
42
47
  > `middleware::transform::tests::test_rejected_message_reaches_the_dlq_through_the_config_wiring`,
43
48
  > and `reference_docs_test::publisher_middleware_wraps_last_entry_outermost`, and is
@@ -58,7 +63,7 @@ middlewares:
58
63
  | [`retry`](#retry) | – | ✅ | – | Exponential-backoff retry of failed sends |
59
64
  | [`dlq`](#dlq) | – | ✅ | – | Route permanently-failed messages to another endpoint |
60
65
  | [`transform`](#transform) | ✅ | ✅ | – | Declarative JSON mapping, coercion, validation |
61
- | [`deduplication`](#deduplication) | ✅ | – | `dedup` | Drop repeated message IDs within a TTL |
66
+ | [`deduplication`](#deduplication) | ✅ | – | `dedup` | Drop repeated keys within a TTL |
62
67
  | [`weak_join`](#weak_join) | ✅ | – | – | Correlate and join related messages |
63
68
  | [`buffer`](#buffer) | ✅ | ✅ | – | Coalesce single sends into batches |
64
69
  | [`limiter`](#limiter) | ✅ | ✅ | – | Cap throughput to a message rate |
@@ -103,7 +108,7 @@ Retries failed sends with exponential backoff. Output only.
103
108
  | `max_interval_ms` | integer | `5000` |
104
109
  | `multiplier` | float | `2.0` |
105
110
 
106
- ```yaml
111
+ ```yaml middleware
107
112
  - retry: { max_attempts: 5, initial_interval_ms: 200, max_interval_ms: 10000, multiplier: 2.0 }
108
113
  ```
109
114
 
@@ -119,7 +124,7 @@ Sends permanently-failed messages to a separate endpoint instead of failing the
119
124
  |---|---|---|
120
125
  | `endpoint` | Endpoint | yes |
121
126
 
122
- ```yaml
127
+ ```yaml middleware
123
128
  - dlq:
124
129
  endpoint:
125
130
  file: { path: "dead-letters.jsonl" }
@@ -161,7 +166,7 @@ validation — over a single parse. Input and output.
161
166
  `schema` and `schema_file` are mutually exclusive. A mapping rule is either a bare path
162
167
  string or `{ path, default, required }`.
163
168
 
164
- ```yaml
169
+ ```yaml middleware
165
170
  - transform:
166
171
  mapping:
167
172
  firstName: "$.first_name"
@@ -185,7 +190,7 @@ lossless ones: `string → integer`, `string → number`, `string → boolean` (
185
190
  A field carrying a JSON document as a string is decoded by `contentMediaType`, following
186
191
  JSON Schema 2020-12:
187
192
 
188
- ```yaml
193
+ ```yaml middleware
189
194
  - transform:
190
195
  schema:
191
196
  type: object
@@ -227,7 +232,7 @@ with neither stage configured leaves the payload untouched without parsing it.
227
232
 
228
233
  ### `deduplication`
229
234
 
230
- Drops messages whose ID was already seen within the TTL. Input only. Requires the `dedup`
235
+ Drops messages whose key was already seen within the TTL. Input only. Requires the `dedup`
231
236
  feature (pulls `sled`).
232
237
 
233
238
  | Field | Type | Required |
@@ -235,13 +240,22 @@ feature (pulls `sled`).
235
240
  | `store` | string | one of `store`/`sled_path` |
236
241
  | `sled_path` | string | one of `store`/`sled_path` |
237
242
  | `ttl_seconds` | integer | yes |
243
+ | `key` | string | no (defaults to `message_id`) |
244
+
245
+ `key` is an interpolation template (see `${namespace:selector}`), typically
246
+ `"${payload:order_id}"`. Without it the key is the `message_id`, which most sources
247
+ regenerate on every read — so re-reading the same source deduplicates nothing and only
248
+ in-flight redeliveries are suppressed. Set `key` to a business key whenever you need
249
+ dedup to survive a re-read.
238
250
 
239
251
  `store` selects the backend by URL scheme:
240
252
 
241
253
  - `sled:///path` (or a bare path) — a local sled database; per-process, not cluster-wide.
242
254
  - `mongodb://host/db[/collection]` — a shared collection, so multiple instances of a route
243
- deduplicate against one another. Requires the `mongodb` feature. Entries expire via a
244
- MongoDB TTL index; the collection defaults to `mqb_dedup_<route>`. Point it at the same
255
+ deduplicate against one another. Requires the `mongodb` feature. Expiry is judged on read,
256
+ so a `ttl_seconds` boundary is honoured exactly; the TTL index only reclaims space
257
+ afterwards (MongoDB's sweep can lag by up to a minute). The collection defaults to
258
+ `mqb_dedup_<route>`. Point it at the same
245
259
  deployment your sink already uses to avoid running extra infrastructure.
246
260
  - `postgres|mysql|mariadb|sqlite://…[/table]` — a shared SQL table (`dedup_key` PK,
247
261
  `expire_at`), so multiple instances deduplicate against one another. Requires the `sqlx`
@@ -250,18 +264,22 @@ feature (pulls `sled`).
250
264
 
251
265
  `sled_path` is the legacy spelling of a local sled store and is equivalent to `store: "sled://<path>"`.
252
266
 
253
- ```yaml
267
+ ```yaml middleware
254
268
  - deduplication: { store: "sled:///var/lib/mq-bridge/dedup", ttl_seconds: 3600 }
255
269
  ```
256
270
 
257
- ```yaml
271
+ ```yaml middleware
258
272
  - deduplication: { store: "mongodb://localhost:27017/etl", ttl_seconds: 3600 }
259
273
  ```
260
274
 
261
- ```yaml
275
+ ```yaml middleware
262
276
  - deduplication: { store: "postgres://user:pass@localhost/etl", ttl_seconds: 3600 }
263
277
  ```
264
278
 
279
+ ```yaml middleware
280
+ - deduplication: { store: "sled:///var/lib/mq-bridge/dedup", ttl_seconds: 3600, key: "${payload:order_id}" }
281
+ ```
282
+
265
283
  When MongoDB is your sink and messages carry a business key, prefer the sink's own unique
266
284
  index (`id_field` on the mongodb output) over this middleware — the target collection then
267
285
  *is* the deduplication authority, with no second write. See the idempotency notes in README.
@@ -279,7 +297,7 @@ Correlates messages by a metadata key and emits them as one joined message. Inpu
279
297
  | `required` | list of branch names | `[]` |
280
298
  | `on_timeout` | `fire` \| `discard` | `fire` |
281
299
 
282
- ```yaml
300
+ ```yaml middleware
283
301
  # Count mode: wait for any 3 messages sharing a correlation_id, emit a JSON array.
284
302
  - weak_join: { group_by: "correlation_id", expected_count: 3, timeout_ms: 5000 }
285
303
 
@@ -307,7 +325,7 @@ Accumulates single sends and forwards them as one batch. Input and output.
307
325
  | `max_messages` | integer | yes |
308
326
  | `max_delay_ms` | integer | yes |
309
327
 
310
- ```yaml
328
+ ```yaml middleware
311
329
  - buffer: { max_messages: 500, max_delay_ms: 20 }
312
330
  ```
313
331
 
@@ -322,7 +340,7 @@ Paces throughput to a target rate. Input and output.
322
340
  |---|---|---|
323
341
  | `messages_per_second` | float (> 0) | yes |
324
342
 
325
- ```yaml
343
+ ```yaml middleware
326
344
  - limiter: { messages_per_second: 250 }
327
345
  ```
328
346
 
@@ -336,7 +354,7 @@ Sleeps a fixed duration before each receive or send. Input and output.
336
354
  |---|---|---|
337
355
  | `delay_ms` | integer | yes |
338
356
 
339
- ```yaml
357
+ ```yaml middleware
340
358
  - delay: { delay_ms: 100 }
341
359
  ```
342
360
 
@@ -356,7 +374,7 @@ Persists HTTP cookies and arbitrary session values across messages. Input and ou
356
374
  | `export_metadata_prefix` | string | – |
357
375
  | `inject_metadata` | map string→string | `{}` |
358
376
 
359
- ```yaml
377
+ ```yaml middleware
360
378
  - cookie_jar:
361
379
  shared_scope: "login-session"
362
380
  capture_metadata_keys: ["x-csrf-token"]
@@ -380,7 +398,7 @@ output. Requires the `encryption` feature.
380
398
  | `key` | string — base64-encoded 32-byte key; `${env:VAR}` reads it from the environment | required |
381
399
  | `decrypt_keys` | map key_id → key | `{}` |
382
400
 
383
- ```yaml
401
+ ```yaml middleware
384
402
  - encryption: { key: "${env:MQB_ENC_KEY}" }
385
403
  ```
386
404
 
@@ -402,7 +420,7 @@ Do **not** combine this middleware with a sink's batch `compression` on the same
402
420
  ciphertext does not compress. For compressed *and* encrypted data at rest, use the `file` /
403
421
  `object_store` endpoints' own fields instead, which apply compress-then-encrypt per batch:
404
422
 
405
- ```yaml
423
+ ```yaml endpoint
406
424
  output:
407
425
  file:
408
426
  path: "data.enc"
@@ -443,7 +461,7 @@ feature.
443
461
  | `algorithm` | `none` \| `gzip` \| `lz4` \| `zstd` | `zstd` |
444
462
  | `max_decompressed_bytes` | integer — reject a payload that decompresses larger than this (bomb guard); consumer side only | unset (no limit) |
445
463
 
446
- ```yaml
464
+ ```yaml middleware
447
465
  - compression: { algorithm: zstd }
448
466
  ```
449
467
 
@@ -464,7 +482,7 @@ endpoints' own `compression`/`encryption` fields instead.
464
482
  Emits throughput, latency and error metrics for the endpoint. Input and output. Requires the
465
483
  `metrics` feature. Takes no options; its presence enables collection.
466
484
 
467
- ```yaml
485
+ ```yaml middleware
468
486
  - metrics: {}
469
487
  ```
470
488
 
@@ -480,7 +498,7 @@ Deliberate fault injection for testing recovery paths. Input and output.
480
498
  | `trigger_on_message` | integer (1-indexed) | – (every message) |
481
499
  | `enabled` | bool | `true` |
482
500
 
483
- ```yaml
501
+ ```yaml middleware
484
502
  - random_panic: { mode: disconnect, trigger_on_message: 500 }
485
503
  ```
486
504
 
@@ -488,6 +506,24 @@ Deliberate fault injection for testing recovery paths. Input and output.
488
506
  non-retryable one — useful for exercising a `dlq`. Keep `enabled: false` in committed configs
489
507
  rather than deleting the block.
490
508
 
509
+ The middleware block alone is **not** enough: fault injection is gated per route by
510
+ `allow_fault_injection`, which defaults to `false`. Copying only the snippet above leaves the
511
+ middleware inert (the route logs that it is disabled). A complete, working configuration:
512
+
513
+ ```yaml route
514
+ flaky_test_route:
515
+ allow_fault_injection: true
516
+ input:
517
+ memory: { topic: "in" }
518
+ middlewares:
519
+ - random_panic: { mode: disconnect, trigger_on_message: 500 }
520
+ output:
521
+ memory: { topic: "out" }
522
+ ```
523
+
524
+ `allow_fault_injection: true` is intended for test configurations only. Do not enable it — or
525
+ the `random_panic` middleware — in production configs.
526
+
491
527
  ### `custom` (middleware)
492
528
 
493
529
  Delegates to a factory you registered programmatically.
@@ -497,7 +533,7 @@ Delegates to a factory you registered programmatically.
497
533
  | `name` | string | yes |
498
534
  | `config` | any JSON | yes |
499
535
 
500
- ```yaml
536
+ ```yaml middleware
501
537
  - custom:
502
538
  name: "my_enricher"
503
539
  config: { lookup_url: "http://enrich.internal" }
@@ -545,7 +581,7 @@ use mq_bridge::route::register_endpoint;
545
581
  register_endpoint("common_queue", Endpoint::new_memory("shared_memory_topic", 100));
546
582
  ```
547
583
 
548
- ```yaml
584
+ ```yaml route
549
585
  enrich:
550
586
  input: { ref: "common_queue" }
551
587
  output: { nats: { subject: "enriched", url: "nats://localhost:4222" } }
@@ -564,7 +600,7 @@ nesting depth is bounded.
564
600
 
565
601
  Publishes each message to every listed endpoint. Output only.
566
602
 
567
- ```yaml
603
+ ```yaml endpoint
568
604
  output:
569
605
  fanout:
570
606
  - kafka: { topic: "audit", url: "localhost:9092" }
@@ -585,7 +621,7 @@ Content-based routing: picks a destination by the value of a **metadata key**.
585
621
  | `cases` | map value → Endpoint | yes |
586
622
  | `default` | Endpoint | no |
587
623
 
588
- ```yaml
624
+ ```yaml endpoint
589
625
  output:
590
626
  switch:
591
627
  metadata_key: "http_status_code"
@@ -611,7 +647,7 @@ turning a request/reply exchange into a one-way flow.
611
647
  | `to` | Endpoint (request-capable) | yes |
612
648
  | `forward_to` | Endpoint | yes |
613
649
 
614
- ```yaml
650
+ ```yaml endpoint
615
651
  output:
616
652
  request:
617
653
  to: { http: { url: "https://api.internal/score" } }
@@ -628,7 +664,7 @@ status key such as `http_status_code`.
628
664
  Replies to the origin of the current request. Output only, and the recommended way to build
629
665
  request/reply routes.
630
666
 
631
- ```yaml
667
+ ```yaml route
632
668
  http_echo:
633
669
  input: { http: { url: "0.0.0.0:8080" } }
634
670
  output: { response: {} }
@@ -644,7 +680,7 @@ pipeline. See [README.md](README.md#patterns-request-response).
644
680
  An output endpoint that **ignores the incoming payload** and instead reads one message from
645
681
  the wrapped consumer, returning it as the response. The inbound message is purely a trigger.
646
682
 
647
- ```yaml
683
+ ```yaml route
648
684
  # HTTP GET pulls the next message off a Kafka topic.
649
685
  poll_api:
650
686
  input: { http: { url: "0.0.0.0:8080", method: "GET" } }
@@ -670,7 +706,7 @@ source).
670
706
 
671
707
  Accepts either a bare string or the full map form:
672
708
 
673
- ```yaml
709
+ ```yaml endpoint
674
710
  output: { static: "OK" } # shorthand, body JSON-encoded
675
711
 
676
712
  output:
@@ -707,7 +743,7 @@ structure — append `| raw` to a token to splice it verbatim. To emit a literal
707
743
  `${…}`, write `$${…}` (a bare `$$` is left as-is); any `${…}` with an unknown namespace is also
708
744
  left untouched.
709
745
 
710
- ```yaml
746
+ ```yaml endpoint
711
747
  output:
712
748
  static:
713
749
  body: '{"error":"not found","id":"${message:id}","at":"${gen:now}"}'
@@ -726,7 +762,7 @@ bodies between routes.
726
762
  | `correlation_id` | string | **required on consumers, must be unset on publishers** |
727
763
  | `capacity` | integer | default `100`, per partition |
728
764
 
729
- ```yaml
765
+ ```yaml endpoint
730
766
  output:
731
767
  stream_buffer: { topic: "responses" } # publisher: no correlation_id
732
768
 
@@ -741,7 +777,7 @@ and ignores it. Primarily wired up via `HttpConfig::stream_response_to`.
741
777
 
742
778
  Discards every message. Output only. This is the **default output** when a route omits one.
743
779
 
744
- ```yaml
780
+ ```yaml route
745
781
  drain:
746
782
  input: { kafka: { topic: "noisy", url: "localhost:9092" } }
747
783
  output: null # a bare YAML null
@@ -762,7 +798,7 @@ Delegates to a factory you registered programmatically.
762
798
  | `name` | string | yes |
763
799
  | `config` | any JSON | yes |
764
800
 
765
- ```yaml
801
+ ```yaml endpoint
766
802
  output:
767
803
  custom:
768
804
  name: "my_sink"
@@ -72,7 +72,7 @@ theirs. The run brief lives in [`mq-bridge-app-benchmark-prompt.md`](mq-bridge-a
72
72
 
73
73
  | Scenario | Payload | Batch | Concurrency | Source → Sink | Result |
74
74
  | --- | --- | --- | --- | --- | --- |
75
- | Bulk-copy throughput | 7-col mixed-type rows, 1,000,000 rows | 1024 | 4 | postgres (keyset cursor) → file (JSONL) | **303,398 rows/s** (3.296 s) |
75
+ | Bulk-copy throughput | 7-col mixed-type rows, 1,000,000 rows | 1024 | 4 | postgres (keyset cursor) → file (JSONL) | **384,615 rows/s** (2.600 s) |
76
76
 
77
77
  Command: `mq-bridge-app copy --from postgres://…?table=…&cursor_column=id --to file://…?format=raw --drain --batch-size 1024 --concurrency 4`, wall-clocked. Requires an index on the cursor column (`CREATE INDEX ON <table>(id)`) — without it the keyset-pagination reader (`WHERE id > $cursor ORDER BY id LIMIT batch`) does a full scan per batch (near-quadratic).
78
78
 
@@ -82,10 +82,10 @@ Same source table (`bench`: 1,000,000 rows, 7 mixed-type columns), same Postgres
82
82
 
83
83
  | Scenario | Payload | Batch | Concurrency | Source → Sink | Throughput | Peak RSS |
84
84
  | --- | --- | --- | --- | --- | --- | --- |
85
- | mq-bridge-app `copy` | 7-col, 1,000,000 rows | 1024 | 1 | postgres (keyset cursor) → file (JSONL) | **266,951 rows/s** | 19.9 MiB |
85
+ | mq-bridge-app `copy` | 7-col, 1,000,000 rows | 1024 | 1 | postgres (keyset cursor) → file (JSONL) | **338,066 rows/s** | 39.8 MiB |
86
86
  | Meltano (`tap-postgres` → `target-jsonl`) | 7-col, 1,000,000 rows | default Singer config | — | postgres → JSONL | 15,356 rows/s | 599.7 MiB |
87
87
 
88
- **~17.4x faster and ~30x leaner in peak memory** than Meltano in this scenario. Full setup (including the Meltano project config) is in [mq-bridge-app's `benches/etl/README.md`](https://github.com/marcomq/mq-bridge-app/blob/dev/benches/etl/README.md#5--postgres--jsonl-vs-meltano-tap-postgres--target-jsonl).
88
+ **~22x faster and ~15x leaner in peak memory** than Meltano in this scenario. Full setup (including the Meltano project config) is in [mq-bridge-app's `benches/etl/README.md`](https://github.com/marcomq/mq-bridge-app/blob/dev/benches/etl/README.md#5--postgres--jsonl-vs-meltano-tap-postgres--target-jsonl).
89
89
 
90
90
  ### Preliminary run — CSV → JSONL vs. Meltano
91
91
 
@@ -93,10 +93,10 @@ Same seeded dataset both sides, same machine, one-shot full-file CSV → local J
93
93
 
94
94
  | Scenario | Payload | Batch | Concurrency | Source → Sink | Throughput | Peak RSS |
95
95
  | --- | --- | --- | --- | --- | --- | --- |
96
- | mq-bridge-app `copy` | 7-col mixed-type, 1,000,000 rows (~116 MiB) | 1024 | 1 | file (CSV) → file (JSONL) | **833,333 rows/s** | 20.0 MiB |
96
+ | mq-bridge-app `copy` | 7-col mixed-type, 1,000,000 rows (~116 MiB) | 1024 | 1 | file (CSV) → file (JSONL) | **1,133,786 rows/s** | 21.9 MiB |
97
97
  | Meltano (`tap-csv` → `target-jsonl`) | 7-col mixed-type, 1,000,000 rows | default Singer config | — | file (CSV) → JSONL | ~19,500 rows/s | 443.8 MiB |
98
98
 
99
- **~43x faster and ~22x leaner in peak memory** than Meltano in this scenario. Full setup is in [mq-bridge-app's `benches/etl/README.md`](https://github.com/marcomq/mq-bridge-app/blob/dev/benches/etl/README.md#6--csv--jsonl-vs-meltano).
99
+ **~58x faster and ~20x leaner in peak memory** than Meltano in this scenario. Full setup is in [mq-bridge-app's `benches/etl/README.md`](https://github.com/marcomq/mq-bridge-app/blob/dev/benches/etl/README.md#6--csv--jsonl-vs-meltano).
100
100
 
101
101
  ## Status
102
102
 
@@ -478,6 +478,14 @@
478
478
  "description": "Deduplication middleware configuration.\n\nPrevents duplicate messages from being processed using a sled, MongoDB, or SQL backend.\nMessages are identified by their deduplication key and removed after the TTL expires.",
479
479
  "type": "object",
480
480
  "properties": {
481
+ "key": {
482
+ "description": "Dedup key template, e.g. `${payload:order_id}`. Defaults to `message_id`.",
483
+ "type": [
484
+ "string",
485
+ "null"
486
+ ],
487
+ "default": null
488
+ },
481
489
  "sled_path": {
482
490
  "description": "Local Sled directory (legacy). Prefer `store`.",
483
491
  "type": [
@@ -922,9 +930,16 @@
922
930
  ]
923
931
  },
924
932
  {
925
- "type": "string",
933
+ "type": "object",
926
934
  "format": "structural_endpoint",
927
- "const": "null"
935
+ "properties": {
936
+ "null": {
937
+ "type": "null"
938
+ }
939
+ },
940
+ "required": [
941
+ "null"
942
+ ]
928
943
  }
929
944
  ],
930
945
  "unevaluatedProperties": false
@@ -963,7 +978,7 @@
963
978
  "type": "object",
964
979
  "properties": {
965
980
  "compression": {
966
- "description": "Per-batch compression (`none`, `gzip`, `lz4`, `zstd`). Requires the `compression` feature; consume mode only.",
981
+ "description": "Per-batch compression (`none`, `gzip`, `lz4`, `zstd`). Requires the `compression` feature. Publishers: always. Consumers: must match, and only the default `consume` mode reads it.",
967
982
  "$ref": "#/$defs/Compression",
968
983
  "default": "none"
969
984
  },
@@ -975,7 +990,7 @@
975
990
  ]
976
991
  },
977
992
  "encryption": {
978
- "description": "At-rest AEAD encryption applied after compression. Requires the `encryption` feature; consume mode only.",
993
+ "description": "At-rest AEAD encryption applied after compression. Requires the `encryption` feature. Publishers: always. Consumers: must match, and only the default `consume` mode reads it.",
979
994
  "anyOf": [
980
995
  {
981
996
  "$ref": "#/$defs/EncryptionConfig"
@@ -2609,7 +2624,7 @@
2609
2624
  "minimum": 0
2610
2625
  },
2611
2626
  "temporary_slot": {
2612
- "description": "Use a temporary slot (dropped on disconnect). Not restart-safe; default is a permanent slot.",
2627
+ "description": "Ephemeral run: drop the slot when the route stops. Not restart-safe; a hard crash leaks it.",
2613
2628
  "type": "boolean",
2614
2629
  "default": false
2615
2630
  },
@@ -86,6 +86,7 @@ class DeadLetterQueueMiddleware(TypedDict, total=False):
86
86
 
87
87
  class DeduplicationMiddleware(TypedDict, total=False):
88
88
  """Deduplication middleware configuration."""
89
+ key: Optional[str]
89
90
  sled_path: Optional[str]
90
91
  store: Optional[str]
91
92
  ttl_seconds: Required[int]
@@ -113,7 +114,36 @@ class EncryptionConfig(TypedDict, total=False):
113
114
 
114
115
  class Endpoint(TypedDict, total=False):
115
116
  """Represents a connection point for messages, which can be a source (input) or a sink (output)."""
117
+ amqp: AmqpConfig
118
+ aws: AwsConfig
119
+ clickhouse: ClickHouseConfig
120
+ custom: Dict[str, Any]
121
+ fanout: List[Endpoint]
122
+ file: FileConfig
123
+ grpc: GrpcConfig
124
+ http: HttpConfig
125
+ ibmmq: IbmMqConfig
126
+ kafka: KafkaConfig
127
+ memory: MemoryConfig
116
128
  middlewares: List[Middleware]
129
+ mongodb: MongoDbConfig
130
+ mqtt: MqttConfig
131
+ nats: NatsConfig
132
+ null: Any
133
+ object_store: ObjectStoreConfig
134
+ postgres_cdc: PostgresCdcConfig
135
+ reader: Endpoint
136
+ redis_streams: RedisStreamsConfig
137
+ ref: str
138
+ request: RequestForwardConfig
139
+ response: ResponseConfig
140
+ sled: SledConfig
141
+ sqlx: SqlxConfig
142
+ static: StaticConfig
143
+ stream_buffer: StreamBufferConfig
144
+ switch: SwitchConfig
145
+ websocket: WebSocketConfig
146
+ zeromq: ZeroMqConfig
117
147
 
118
148
 
119
149
  class FileConfig(TypedDict, total=False):