mq-bridge-py-basic 0.4.0__tar.gz → 0.4.1__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 (288) hide show
  1. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/Cargo.lock +15 -14
  2. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/Cargo.toml +1 -1
  3. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/PKG-INFO +1 -1
  4. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/benches/performance_bench.rs +6 -4
  5. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/route.rs +174 -3
  6. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  7. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  8. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  9. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/.github/dependabot.yml +0 -0
  10. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/.github/workflows/benchmark.yml +0 -0
  11. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/.github/workflows/ci.yml +0 -0
  12. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/.github/workflows/ibm-mq.yml +0 -0
  13. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/.github/workflows/node.yml +0 -0
  14. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/.github/workflows/publish-node.yml +0 -0
  15. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/.github/workflows/publish-python.yml +0 -0
  16. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/.github/workflows/python.yml +0 -0
  17. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/.github/workflows/release.yml +0 -0
  18. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/.github/workflows/test-matrix.yml +0 -0
  19. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/.gitignore +0 -0
  20. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/CHANGELOG.md +0 -0
  21. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/CLAUDE.md +0 -0
  22. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/CONTRIBUTING.md +0 -0
  23. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/LICENSE +0 -0
  24. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/LICENSE.python +0 -0
  25. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/README.md +0 -0
  26. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/SECURITY.md +0 -0
  27. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/benches/ETL_BENCHMARKS.md +0 -0
  28. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/benches/router_bench.rs +0 -0
  29. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/benches/zeromq_backends.rs +0 -0
  30. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/bindings-common/Cargo.toml +0 -0
  31. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/bindings-common/src/lib.rs +0 -0
  32. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/bindings-common/src/logging.rs +0 -0
  33. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/build.rs +0 -0
  34. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/deny.toml +0 -0
  35. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/docs/ARCHITECTURE.md +0 -0
  36. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/docs/CONFIGURATION.md +0 -0
  37. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/docs/DELIVERY.md +0 -0
  38. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/docs/EXTENDING.md +0 -0
  39. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/docs/PLUGINS.md +0 -0
  40. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/docs/REFERENCE.md +0 -0
  41. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/examples/ipc_worker_queue.yaml +0 -0
  42. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/mq-bridge.schema.json +0 -0
  43. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/mq_bridge/__init__.py +0 -0
  44. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/mq_bridge/__init__.pyi +0 -0
  45. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/mq_bridge/config.py +0 -0
  46. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/mq_bridge/config.pyi +0 -0
  47. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/mq_bridge/plugin_packaging.py +0 -0
  48. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/mq_bridge/py.typed +0 -0
  49. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/package-lock.json +0 -0
  50. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/pyproject.toml +0 -0
  51. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/Cargo.toml +0 -0
  52. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/LICENSE.python +0 -0
  53. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/README.md +0 -0
  54. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/analysis/bench_http_native.py +0 -0
  55. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/example.py +0 -0
  56. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/examples/bench_memory.py +0 -0
  57. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/examples/bench_memory.yaml +0 -0
  58. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/examples/consume_pull.py +0 -0
  59. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/examples/dlt_source.py +0 -0
  60. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/examples/json_route.py +0 -0
  61. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/examples/memory.yaml +0 -0
  62. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/examples/raw_route.py +0 -0
  63. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/pyproject-basic.toml +0 -0
  64. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/pyproject-reduced.toml +0 -0
  65. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/scripts/gen_config_types.py +0 -0
  66. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/src/lib.rs +0 -0
  67. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/tests/test_config_types.py +0 -0
  68. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/tests/test_custom_endpoint.py +0 -0
  69. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/tests/test_logging.py +0 -0
  70. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/tests/test_packaging.py +0 -0
  71. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/tests/test_performance_smoke.py +0 -0
  72. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/tests/test_plugin_package.py +0 -0
  73. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/tests/test_public_api.py +0 -0
  74. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/tests/test_routes.py +0 -0
  75. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/python/mq-bridge-py/uv.lock +0 -0
  76. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/analysis/benches/metadata_bench.rs +0 -0
  77. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/analysis/debug_ibm_mq_tls.rs +0 -0
  78. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/analysis/http/analyze_xctrace_time_profile.py +0 -0
  79. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/analysis/http/http_flamegraph.py +0 -0
  80. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/analysis/http/mq_bridge_http_profile.rs +0 -0
  81. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/analysis/http/run_http_ladder.sh +0 -0
  82. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/ci/format_bench_output.sh +0 -0
  83. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/httparena/README.md +0 -0
  84. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/httparena/frameworks/mq-bridge-py/Dockerfile +0 -0
  85. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/httparena/frameworks/mq-bridge-py/meta.json +0 -0
  86. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/httparena/frameworks/mq-bridge-py/server.py +0 -0
  87. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/techempower/Python/mq-bridge-py/README.md +0 -0
  88. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/techempower/Python/mq-bridge-py/benchmark_config.json +0 -0
  89. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/techempower/Python/mq-bridge-py/mq-bridge-py.dockerfile +0 -0
  90. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/techempower/Python/mq-bridge-py/server.py +0 -0
  91. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/techempower/README.md +0 -0
  92. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/techempower/postgres.yml +0 -0
  93. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/techempower/seed.sql +0 -0
  94. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/techempower/verify.sh +0 -0
  95. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/the-benchmarker/README.md +0 -0
  96. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/the-benchmarker/python/mq-bridge-py/config.yaml +0 -0
  97. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/the-benchmarker/python/mq-bridge-py/pyproject.toml +0 -0
  98. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/scripts/the-benchmarker/python/mq-bridge-py/server.py +0 -0
  99. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/canonical_message.rs +0 -0
  100. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/checkpoint.rs +0 -0
  101. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/command_handler.rs +0 -0
  102. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/amqp.rs +0 -0
  103. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/aws.rs +0 -0
  104. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/clickhouse.rs +0 -0
  105. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/file/mod.rs +0 -0
  106. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/file/tests.rs +0 -0
  107. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/grpc.proto +0 -0
  108. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/grpc.rs +0 -0
  109. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/http/mod.rs +0 -0
  110. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/http/publisher.rs +0 -0
  111. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/http/stream.rs +0 -0
  112. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/http/tests.rs +0 -0
  113. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/ibm_mq.rs +0 -0
  114. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/kafka.rs +0 -0
  115. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/memory/endpoint.rs +0 -0
  116. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/memory/framed.rs +0 -0
  117. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/memory/ipc_unix.rs +0 -0
  118. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/memory/ipc_windows.rs +0 -0
  119. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/memory/memory_transport.rs +0 -0
  120. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/memory/mod.rs +0 -0
  121. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/memory/transport.rs +0 -0
  122. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/mod.rs +0 -0
  123. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/mongodb/consumer.rs +0 -0
  124. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/mongodb/dedup.rs +0 -0
  125. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/mongodb/mod.rs +0 -0
  126. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/mongodb/publisher.rs +0 -0
  127. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/mongodb/readers.rs +0 -0
  128. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/mongodb/tests.rs +0 -0
  129. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/mqtt.rs +0 -0
  130. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/nats.rs +0 -0
  131. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/object_store.rs +0 -0
  132. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/poll.rs +0 -0
  133. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/postgres/VENDORED.md +0 -0
  134. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/postgres/mod.rs +0 -0
  135. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/postgres/pgoutput/decoder.rs +0 -0
  136. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/postgres/pgoutput/messages.rs +0 -0
  137. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/postgres/pgoutput/mod.rs +0 -0
  138. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/postgres/pgoutput/registry.rs +0 -0
  139. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/postgres/pgoutput/values.rs +0 -0
  140. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/postgres/replication.rs +0 -0
  141. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/postgres/state.rs +0 -0
  142. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/redis_streams.rs +0 -0
  143. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/sled.rs +0 -0
  144. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/sqlx/dedup.rs +0 -0
  145. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/sqlx/mod.rs +0 -0
  146. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/sqlx/tests.rs +0 -0
  147. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/structural/fanout.rs +0 -0
  148. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/structural/mod.rs +0 -0
  149. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/structural/null.rs +0 -0
  150. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/structural/reader.rs +0 -0
  151. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/structural/request.rs +0 -0
  152. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/structural/response.rs +0 -0
  153. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/structural/static_endpoint.rs +0 -0
  154. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/structural/stream_buffer.rs +0 -0
  155. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/structural/switch.rs +0 -0
  156. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/websocket.rs +0 -0
  157. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/zeromq/codec.rs +0 -0
  158. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/zeromq/mod.rs +0 -0
  159. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/zeromq/omq.rs +0 -0
  160. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/endpoints/zeromq/zmq.rs +0 -0
  161. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/errors.rs +0 -0
  162. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/event_handler.rs +0 -0
  163. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/event_store.rs +0 -0
  164. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/extensions.rs +0 -0
  165. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/lib.rs +0 -0
  166. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/buffer.rs +0 -0
  167. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/compression.rs +0 -0
  168. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/cookie_jar.rs +0 -0
  169. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/deduplication.rs +0 -0
  170. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/delay.rs +0 -0
  171. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/dlq.rs +0 -0
  172. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/encryption.rs +0 -0
  173. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/id.rs +0 -0
  174. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/limiter.rs +0 -0
  175. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/metrics.rs +0 -0
  176. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/mod.rs +0 -0
  177. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/random_panic.rs +0 -0
  178. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/retry.rs +0 -0
  179. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/transform/coerce.rs +0 -0
  180. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/transform/compiled.rs +0 -0
  181. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/transform/error.rs +0 -0
  182. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/transform/mod.rs +0 -0
  183. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/transform/path.rs +0 -0
  184. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/transform/schema.rs +0 -0
  185. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/transform/tests.rs +0 -0
  186. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/middleware/weak_join.rs +0 -0
  187. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/models/builders.rs +0 -0
  188. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/models/defaults.rs +0 -0
  189. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/models/secrets.rs +0 -0
  190. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/models/serde_support.rs +0 -0
  191. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/models/tests.rs +0 -0
  192. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/models.rs +0 -0
  193. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/outcomes.rs +0 -0
  194. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/plugin/conformance.rs +0 -0
  195. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/plugin/endpoint.rs +0 -0
  196. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/plugin/message.rs +0 -0
  197. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/plugin/middleware.rs +0 -0
  198. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/plugin/mod.rs +0 -0
  199. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/plugin/sdk.rs +0 -0
  200. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/plugin/test_support.rs +0 -0
  201. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/publisher.rs +0 -0
  202. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/response.rs +0 -0
  203. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/support/base64_engine.rs +0 -0
  204. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/support/compression.rs +0 -0
  205. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/support/connection_registry.rs +0 -0
  206. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/support/crypto.rs +0 -0
  207. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/support/crypto_envelope.rs +0 -0
  208. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/support/interpolation.rs +0 -0
  209. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/support/mod.rs +0 -0
  210. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/support/plugin_abi.rs +0 -0
  211. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/support/source_ranges.rs +0 -0
  212. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/test_utils.rs +0 -0
  213. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/traits.rs +0 -0
  214. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/src/type_handler.rs +0 -0
  215. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/README.md +0 -0
  216. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/armature_integration.rs +0 -0
  217. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/amqp.rs +0 -0
  218. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/aws.rs +0 -0
  219. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/clickhouse.rs +0 -0
  220. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/config.toml +0 -0
  221. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/amqp.yml +0 -0
  222. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/aws.yml +0 -0
  223. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/clickhouse.yml +0 -0
  224. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/ibm-mq-certs/client.crl +0 -0
  225. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/ibm-mq-certs/client.kdb +0 -0
  226. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/ibm-mq-certs/client.p12 +0 -0
  227. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/ibm-mq-certs/client.rdb +0 -0
  228. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/ibm-mq-certs/client.sth +0 -0
  229. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/ibm_mq.yml +0 -0
  230. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/ibm_mq_tls.yml +0 -0
  231. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/kafka-tls.yml +0 -0
  232. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/kafka.yml +0 -0
  233. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/mariadb.yml +0 -0
  234. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/mongodb-replica.yml +0 -0
  235. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/mongodb-tls.yml +0 -0
  236. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/mongodb.yml +0 -0
  237. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/mosquitto.conf +0 -0
  238. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/mosquitto_performance.conf +0 -0
  239. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/mosquitto_persistence.conf +0 -0
  240. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/mq_init.mqsc +0 -0
  241. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/mq_init_tls.mqsc +0 -0
  242. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/mqtt.yml +0 -0
  243. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/mqtt_performance.yml +0 -0
  244. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/mysql.yml +0 -0
  245. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/nats.yml +0 -0
  246. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/object_store.yml +0 -0
  247. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/postgres.yml +0 -0
  248. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/postgres_cdc.yml +0 -0
  249. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/docker-compose/redis.yml +0 -0
  250. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/file.rs +0 -0
  251. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/grpc.rs +0 -0
  252. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/grpc_tls.rs +0 -0
  253. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/http.rs +0 -0
  254. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/http_tls.rs +0 -0
  255. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/ibm_mq.rs +0 -0
  256. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/ibm_mq_tls.rs +0 -0
  257. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/ipc.rs +0 -0
  258. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/kafka.rs +0 -0
  259. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/kafka_tls.rs +0 -0
  260. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/logic_test.rs +0 -0
  261. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/mariadb.rs +0 -0
  262. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/memory.rs +0 -0
  263. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/mod.rs +0 -0
  264. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/mongodb.rs +0 -0
  265. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/mongodb_raw.rs +0 -0
  266. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/mongodb_tls.rs +0 -0
  267. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/mqtt.rs +0 -0
  268. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/mysql.rs +0 -0
  269. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/nats.rs +0 -0
  270. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/object_store.rs +0 -0
  271. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/performance_static.rs +0 -0
  272. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/postgres.rs +0 -0
  273. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/postgres_cdc.rs +0 -0
  274. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/redis_streams.rs +0 -0
  275. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/route.rs +0 -0
  276. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/scripts/gen_certs.sh +0 -0
  277. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/sqlite.rs +0 -0
  278. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/tls_helpers.rs +0 -0
  279. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/websocket.rs +0 -0
  280. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration/zeromq.rs +0 -0
  281. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/integration_test.rs +0 -0
  282. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/memory_leak_test.rs +0 -0
  283. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/ref_test.rs +0 -0
  284. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/reference_docs_test.rs +0 -0
  285. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/sqlite_test.rs +0 -0
  286. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/tls_example.rs +0 -0
  287. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/unit_tests.md +0 -0
  288. {mq_bridge_py_basic-0.4.0 → mq_bridge_py_basic-0.4.1}/tests/websocket_test.rs +0 -0
@@ -3348,7 +3348,7 @@ dependencies = [
3348
3348
 
3349
3349
  [[package]]
3350
3350
  name = "mq-bridge"
3351
- version = "0.4.0"
3351
+ version = "0.4.1"
3352
3352
  dependencies = [
3353
3353
  "aes-gcm",
3354
3354
  "anyhow",
@@ -3431,7 +3431,7 @@ dependencies = [
3431
3431
 
3432
3432
  [[package]]
3433
3433
  name = "mq-bridge-bindings-common"
3434
- version = "0.4.0"
3434
+ version = "0.4.1"
3435
3435
  dependencies = [
3436
3436
  "anyhow",
3437
3437
  "fast-uuid-v7",
@@ -3445,7 +3445,7 @@ dependencies = [
3445
3445
 
3446
3446
  [[package]]
3447
3447
  name = "mq-bridge-node"
3448
- version = "0.4.0"
3448
+ version = "0.4.1"
3449
3449
  dependencies = [
3450
3450
  "anyhow",
3451
3451
  "async-trait",
@@ -3487,7 +3487,7 @@ dependencies = [
3487
3487
 
3488
3488
  [[package]]
3489
3489
  name = "mq-bridge-py"
3490
- version = "0.4.0"
3490
+ version = "0.4.1"
3491
3491
  dependencies = [
3492
3492
  "anyhow",
3493
3493
  "async-trait",
@@ -3529,13 +3529,14 @@ checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084"
3529
3529
 
3530
3530
  [[package]]
3531
3531
  name = "napi"
3532
- version = "3.12.0"
3532
+ version = "3.12.1"
3533
3533
  source = "registry+https://github.com/rust-lang/crates.io-index"
3534
- checksum = "6f71d6bc097c4a6eb853c3f24991ab8c9f50f57d1f719e305175541482217e36"
3534
+ checksum = "459197f1592f4c3dbbf9c1b13f5a4599a343e4ef66b96bc340e2a518b36a6662"
3535
3535
  dependencies = [
3536
3536
  "bitflags 2.13.1",
3537
3537
  "ctor",
3538
3538
  "futures",
3539
+ "libc",
3539
3540
  "napi-build",
3540
3541
  "napi-sys",
3541
3542
  "nohash-hasher",
@@ -3547,15 +3548,15 @@ dependencies = [
3547
3548
 
3548
3549
  [[package]]
3549
3550
  name = "napi-build"
3550
- version = "2.4.0"
3551
+ version = "2.4.1"
3551
3552
  source = "registry+https://github.com/rust-lang/crates.io-index"
3552
- checksum = "5282704fbe8d49b0cf8b08e3f33233416a528658f205c7e5ace63b582de0b11c"
3553
+ checksum = "60fdf9b392c50e7c4170fa633bd909490ed7835cea4c046776d1a4dd8d2ae0ab"
3553
3554
 
3554
3555
  [[package]]
3555
3556
  name = "napi-derive"
3556
- version = "3.6.2"
3557
+ version = "3.6.3"
3557
3558
  source = "registry+https://github.com/rust-lang/crates.io-index"
3558
- checksum = "6d9002b2940f0184444754546e0fcd15182f56948e6f381968b019d549387c42"
3559
+ checksum = "0fa55ea69990c90b888e9e77044410e304ce7f35de599dc6d0b5c1923d2e59af"
3559
3560
  dependencies = [
3560
3561
  "convert_case 0.11.0",
3561
3562
  "ctor",
@@ -3567,9 +3568,9 @@ dependencies = [
3567
3568
 
3568
3569
  [[package]]
3569
3570
  name = "napi-derive-backend"
3570
- version = "6.1.1"
3571
+ version = "6.1.2"
3571
3572
  source = "registry+https://github.com/rust-lang/crates.io-index"
3572
- checksum = "d60b5d773ad46c698c8cc2cd9fde0b283d39cbb7f71c04bee633c7bdba4423bd"
3573
+ checksum = "df4056ac7c18e4438ccf0edaed4340ca0d269278c8ec19284f7b23cb039fd0ae"
3573
3574
  dependencies = [
3574
3575
  "convert_case 0.11.0",
3575
3576
  "proc-macro2",
@@ -4791,9 +4792,9 @@ dependencies = [
4791
4792
 
4792
4793
  [[package]]
4793
4794
  name = "rcgen"
4794
- version = "0.14.8"
4795
+ version = "0.14.9"
4795
4796
  source = "registry+https://github.com/rust-lang/crates.io-index"
4796
- checksum = "57f6d249aad744e274e682777a50283a225a32705394ee6d5fcc01efa25e4055"
4797
+ checksum = "091e7a8e7d86e6feb87a27ce8e2cba29d49eff9507afeebefab7eeb2ca667fb4"
4797
4798
  dependencies = [
4798
4799
  "pem",
4799
4800
  "ring",
@@ -16,7 +16,7 @@ members = ["bindings-common", "python/mq-bridge-py"]
16
16
  resolver = "2"
17
17
 
18
18
  [workspace.package]
19
- version = "0.4.0"
19
+ version = "0.4.1"
20
20
 
21
21
  [workspace.dependencies]
22
22
  anyhow = "1.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mq-bridge-py-basic
3
- Version: 0.4.0
3
+ Version: 0.4.1
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: License :: OSI Approved :: MIT License
6
6
  Classifier: Programming Language :: Python :: 3
@@ -16,6 +16,7 @@ use mq_bridge::test_utils::{
16
16
  };
17
17
 
18
18
  const PERF_TEST_MESSAGE_COUNT: usize = 1000;
19
+ const GRPC_SERVER_MESSAGE_COUNT: usize = 25_600;
19
20
 
20
21
  #[allow(unused)]
21
22
  #[cfg(feature = "rustls")]
@@ -1244,6 +1245,7 @@ fn performance_benchmarks(c: &mut Criterion) {
1244
1245
  // report it as both write and read.
1245
1246
  #[cfg(feature = "grpc")]
1246
1247
  if mq_bridge::test_utils::should_run_benchmark("grpc_server") {
1248
+ group.throughput(Throughput::Elements(GRPC_SERVER_MESSAGE_COUNT as u64));
1247
1249
  group.bench_function("grpc_server_batch", |b| {
1248
1250
  b.to_async(&rt).iter_custom(|iters| async move {
1249
1251
  let (publisher, drain) = grpc_server_helper::setup_coupled().await;
@@ -1253,14 +1255,14 @@ fn performance_benchmarks(c: &mut Criterion) {
1253
1255
  total += mq_bridge::test_utils::measure_write_performance(
1254
1256
  "grpc_server_batch",
1255
1257
  std::sync::Arc::clone(&publisher),
1256
- PERF_TEST_MESSAGE_COUNT,
1258
+ GRPC_SERVER_MESSAGE_COUNT,
1257
1259
  PERF_TEST_CONCURRENCY,
1258
1260
  )
1259
1261
  .await;
1260
1262
  }
1261
1263
  grpc_server_helper::finish_drain(drain).await;
1262
1264
  let msgs_per_sec =
1263
- (iters as f64 * PERF_TEST_MESSAGE_COUNT as f64) / total.as_secs_f64();
1265
+ (iters as f64 * GRPC_SERVER_MESSAGE_COUNT as f64) / total.as_secs_f64();
1264
1266
  let mut results = BENCH_RESULTS.lock().await;
1265
1267
  let stats = results.entry("grpc_server".to_string()).or_default();
1266
1268
  stats.write_performance = msgs_per_sec;
@@ -1281,14 +1283,14 @@ fn performance_benchmarks(c: &mut Criterion) {
1281
1283
  total += mq_bridge::test_utils::measure_single_write_performance(
1282
1284
  "grpc_server_single",
1283
1285
  std::sync::Arc::clone(&publisher),
1284
- PERF_TEST_MESSAGE_COUNT,
1286
+ GRPC_SERVER_MESSAGE_COUNT,
1285
1287
  PERF_TEST_CONCURRENCY,
1286
1288
  )
1287
1289
  .await;
1288
1290
  }
1289
1291
  grpc_server_helper::finish_drain(drain).await;
1290
1292
  let msgs_per_sec =
1291
- (iters as f64 * PERF_TEST_MESSAGE_COUNT as f64) / total.as_secs_f64();
1293
+ (iters as f64 * GRPC_SERVER_MESSAGE_COUNT as f64) / total.as_secs_f64();
1292
1294
  let mut results = BENCH_RESULTS.lock().await;
1293
1295
  let stats = results.entry("grpc_server".to_string()).or_default();
1294
1296
  stats.single_write_performance = msgs_per_sec;
@@ -58,9 +58,23 @@ pub enum RouteOutcome {
58
58
  struct OutcomeGuard {
59
59
  outcome: Arc<RwLock<Option<RouteOutcome>>>,
60
60
  status: Arc<RwLock<EndpointStatus>>,
61
+ drops: Arc<RwLock<DropReport>>,
61
62
  resolved: Option<RouteOutcome>,
62
63
  }
63
64
 
65
+ /// Messages the route discarded because the sink rejected them permanently and
66
+ /// no DLQ was configured.
67
+ ///
68
+ /// Accumulated by the route task and published by [`OutcomeGuard`] as the route
69
+ /// ends, rather than written to the status directly: the reconnect loop clears
70
+ /// `EndpointStatus::error` when a pass reports ready, so a drop recorded inline
71
+ /// races that reset and is usually erased before anyone can read it.
72
+ #[derive(Default)]
73
+ pub(crate) struct DropReport {
74
+ count: u64,
75
+ last_cause: Option<String>,
76
+ }
77
+
64
78
  impl OutcomeGuard {
65
79
  fn set(&mut self, outcome: RouteOutcome) {
66
80
  self.resolved = Some(outcome);
@@ -77,6 +91,22 @@ impl Drop for OutcomeGuard {
77
91
  s.error = Some("route task panicked or was aborted".to_string());
78
92
  RouteOutcome::Failed
79
93
  });
94
+ // A route that discarded data did not run clean, whatever its outcome.
95
+ // Never overwrite a recorded failure cause: that one explains why the
96
+ // route stopped, which is the more urgent of the two.
97
+ {
98
+ let drops = recover_read_lock(&self.drops, "route_drop_report");
99
+ if drops.count > 0 {
100
+ let mut s = recover_write_lock(&self.status, "route_handle_status");
101
+ if s.error.is_none() {
102
+ s.error = Some(format!(
103
+ "dropped {} message(s): sink rejected them permanently and no dlq middleware is configured: {}",
104
+ drops.count,
105
+ drops.last_cause.as_deref().unwrap_or("unknown cause")
106
+ ));
107
+ }
108
+ }
109
+ }
80
110
  *recover_write_lock(&self.outcome, "route_handle_outcome") = Some(outcome);
81
111
  }
82
112
  }
@@ -350,6 +380,24 @@ fn report_route_error(err_tx: &Sender<anyhow::Error>, err: anyhow::Error, contex
350
380
  }
351
381
  }
352
382
 
383
+ /// Records a batch the route discarded after a permanent sink rejection.
384
+ ///
385
+ /// Dropping is deliberate — it is what stops a poison message from wedging the
386
+ /// route — but `err_tx` only carries route-*stopping* errors, so without this a
387
+ /// drop is invisible: the route resolves to [`RouteOutcome::Completed`] with
388
+ /// `error: None` and the caller cannot tell a clean run from one that threw data
389
+ /// away. [`OutcomeGuard`] publishes the tally when the route ends.
390
+ fn record_dropped_messages(
391
+ drops: Option<&Arc<RwLock<DropReport>>>,
392
+ dropped: usize,
393
+ cause: &PublisherError,
394
+ ) {
395
+ let Some(drops) = drops else { return };
396
+ let mut report = recover_write_lock(drops, "route_drop_report");
397
+ report.count += dropped as u64;
398
+ report.last_cause = Some(cause.to_string());
399
+ }
400
+
353
401
  struct BatchScratch {
354
402
  message_ids: Vec<u128>,
355
403
  request_ids: HashSet<u128>,
@@ -388,6 +436,7 @@ async fn send_batch_and_commit(
388
436
  commit_semaphore: Option<&Arc<tokio::sync::Semaphore>>,
389
437
  commit_tasks: &mut JoinSet<()>,
390
438
  scratch: &mut BatchScratch,
439
+ drops: Option<&Arc<RwLock<DropReport>>>,
391
440
  ) -> anyhow::Result<()> {
392
441
  let batch_len = messages.len();
393
442
  scratch.fill_from(&messages);
@@ -447,6 +496,25 @@ async fn send_batch_and_commit(
447
496
  failed.len(),
448
497
  first_err
449
498
  );
499
+ // Non-retryable entries in a mixed batch are Ack'ed (dropped) below,
500
+ // so account for them here before the transient path returns.
501
+ if !has_dlq_middleware {
502
+ let mut dropped = 0usize;
503
+ let mut cause = None;
504
+ for (msg, e) in &failed {
505
+ if matches!(e, PublisherError::NonRetryable(_)) {
506
+ error!(
507
+ "Dropping message (ID: {:032x}) due to non-retryable error: {}",
508
+ msg.message_id, e
509
+ );
510
+ dropped += 1;
511
+ cause.get_or_insert(e);
512
+ }
513
+ }
514
+ if let Some(cause) = cause {
515
+ record_dropped_messages(drops, dropped, cause);
516
+ }
517
+ }
450
518
  let dispositions = map_responses_to_dispositions(
451
519
  &scratch.message_ids,
452
520
  responses,
@@ -473,6 +541,11 @@ async fn send_batch_and_commit(
473
541
  msg.message_id, e
474
542
  );
475
543
  }
544
+ if !has_dlq_middleware {
545
+ if let Some((_, first)) = failed.first() {
546
+ record_dropped_messages(drops, failed.len(), first);
547
+ }
548
+ }
476
549
  let err_tx = err_tx.clone();
477
550
  let dispositions = map_responses_to_dispositions(
478
551
  &scratch.message_ids,
@@ -504,6 +577,17 @@ async fn send_batch_and_commit(
504
577
  debug!("Failure commit result: {:?}", commit_result);
505
578
  if non_retryable && !has_dlq_middleware {
506
579
  commit_result?;
580
+ // Acking a permanently-rejected batch keeps the route from
581
+ // re-reading the same poison messages forever, but the data is
582
+ // gone. Record it: a drop that leaves no trace is how a route
583
+ // reports a clean success while having discarded messages.
584
+ for id in scratch.message_ids.iter() {
585
+ error!(
586
+ "Dropping message (ID: {:032x}) due to non-retryable error: {}",
587
+ id, e
588
+ );
589
+ }
590
+ record_dropped_messages(drops, batch_len, &e);
507
591
  Ok(())
508
592
  } else {
509
593
  Err(e.into())
@@ -798,9 +882,12 @@ impl Route {
798
882
  let status_loop = Arc::clone(&status);
799
883
  // Terminal outcome cell, published by `OutcomeGuard` as the task exits.
800
884
  let outcome = Arc::new(RwLock::new(None::<RouteOutcome>));
885
+ // Tally of discarded messages, published alongside the terminal outcome.
886
+ let drops = Arc::new(RwLock::new(DropReport::default()));
801
887
  let mut outcome_guard = OutcomeGuard {
802
888
  outcome: Arc::clone(&outcome),
803
889
  status: Arc::clone(&status),
890
+ drops: Arc::clone(&drops),
804
891
  resolved: None,
805
892
  };
806
893
 
@@ -826,9 +913,15 @@ impl Route {
826
913
  let (iter_ready_tx, iter_ready_rx) = bounded(1);
827
914
 
828
915
  // The actual route logic is in `run_until_err`.
916
+ let drops_run = Arc::clone(&drops);
829
917
  let mut run_task = tokio::spawn(async move {
830
918
  route_arc
831
- .run_until_err(&name_arc, Some(internal_shutdown_rx), Some(iter_ready_tx))
919
+ .run_until_err_reporting_to(
920
+ &name_arc,
921
+ Some(internal_shutdown_rx),
922
+ Some(iter_ready_tx),
923
+ Some(&drops_run),
924
+ )
832
925
  .await
833
926
  });
834
927
 
@@ -1007,6 +1100,21 @@ impl Route {
1007
1100
  name: &str,
1008
1101
  shutdown_rx: Option<async_channel::Receiver<()>>,
1009
1102
  ready_tx: Option<Sender<()>>,
1103
+ ) -> anyhow::Result<bool> {
1104
+ self.run_until_err_reporting_to(name, shutdown_rx, ready_tx, None)
1105
+ .await
1106
+ }
1107
+
1108
+ /// [`run_until_err`](Self::run_until_err) with somewhere to report dropped
1109
+ /// messages. A deployed route passes its status cell so that a permanent
1110
+ /// sink rejection is still visible after the route completes; a caller that
1111
+ /// drives a `Route` directly has no such cell and passes `None`.
1112
+ pub(crate) async fn run_until_err_reporting_to(
1113
+ &self,
1114
+ name: &str,
1115
+ shutdown_rx: Option<async_channel::Receiver<()>>,
1116
+ ready_tx: Option<Sender<()>>,
1117
+ drops: Option<&Arc<RwLock<DropReport>>>,
1010
1118
  ) -> anyhow::Result<bool> {
1011
1119
  let (_internal_shutdown_tx, internal_shutdown_rx) = bounded(1);
1012
1120
  let shutdown_rx = shutdown_rx.unwrap_or(internal_shutdown_rx);
@@ -1021,9 +1129,11 @@ impl Route {
1021
1129
  return result;
1022
1130
  }
1023
1131
  if self.options.concurrency == 1 {
1024
- self.run_sequentially(name, shutdown_rx, ready_tx).await
1132
+ self.run_sequentially(name, shutdown_rx, ready_tx, drops)
1133
+ .await
1025
1134
  } else {
1026
- self.run_concurrently(name, shutdown_rx, ready_tx).await
1135
+ self.run_concurrently(name, shutdown_rx, ready_tx, drops)
1136
+ .await
1027
1137
  }
1028
1138
  }
1029
1139
 
@@ -1033,6 +1143,7 @@ impl Route {
1033
1143
  name: &str,
1034
1144
  shutdown_rx: async_channel::Receiver<()>,
1035
1145
  ready_tx: Option<Sender<()>>,
1146
+ drops: Option<&Arc<RwLock<DropReport>>>,
1036
1147
  ) -> anyhow::Result<bool> {
1037
1148
  let source_metadata_required = output_requires_source_metadata(name, &self.output)?;
1038
1149
  let publisher = create_publisher_from_route(name, &self.output).await?;
@@ -1129,6 +1240,7 @@ impl Route {
1129
1240
  commit_semaphore.as_ref(),
1130
1241
  &mut commit_tasks,
1131
1242
  &mut batch_scratch,
1243
+ drops,
1132
1244
  )
1133
1245
  .await
1134
1246
  {
@@ -1174,6 +1286,7 @@ impl Route {
1174
1286
  name: &str,
1175
1287
  shutdown_rx: async_channel::Receiver<()>,
1176
1288
  ready_tx: Option<Sender<()>>,
1289
+ drops: Option<&Arc<RwLock<DropReport>>>,
1177
1290
  ) -> anyhow::Result<bool> {
1178
1291
  let source_metadata_required = output_requires_source_metadata(name, &self.output)?;
1179
1292
  let publisher = create_publisher_from_route(name, &self.output).await?;
@@ -1224,6 +1337,8 @@ impl Route {
1224
1337
  let has_retry_middleware = self.output.has_retry_middleware();
1225
1338
  let has_dlq_middleware = self.output.has_dlq_middleware();
1226
1339
  let batch_size = self.options.batch_size;
1340
+ // Owned per worker: the borrow cannot outlive this loop iteration.
1341
+ let drops = drops.cloned();
1227
1342
  join_set.spawn(async move {
1228
1343
  debug!("Starting worker {}", i);
1229
1344
  let mut batch_scratch = BatchScratch::with_capacity(batch_size);
@@ -1240,6 +1355,7 @@ impl Route {
1240
1355
  commit_semaphore.as_ref(),
1241
1356
  &mut commit_tasks,
1242
1357
  &mut batch_scratch,
1358
+ drops.as_ref(),
1243
1359
  )
1244
1360
  .await
1245
1361
  {
@@ -3953,6 +4069,61 @@ mod tests {
3953
4069
  assert_eq!(attempts.values().filter(|&&c| c == 1).count(), 2);
3954
4070
  }
3955
4071
 
4072
+ /// A sink that rejects permanently with no DLQ configured drops the batch so
4073
+ /// the route is not wedged re-reading a poison message — but the drop must
4074
+ /// not be silent. The route still completes; it just carries the cause, so a
4075
+ /// caller polling only `outcome` cannot mistake a discarded batch for a
4076
+ /// clean delivery.
4077
+ #[tokio::test(flavor = "multi_thread")]
4078
+ async fn test_dropped_poison_batch_is_recorded_on_the_route_status() {
4079
+ let unique_id = fast_uuid_v7::gen_id().to_string();
4080
+ let in_topic = format!("drop_in_{}", unique_id);
4081
+ let out_topic = format!("drop_out_{}", unique_id);
4082
+ let input = Endpoint::new_memory(&in_topic, 10);
4083
+
4084
+ let mut output = Endpoint::new_memory(&out_topic, 10);
4085
+ output.middlewares = vec![Middleware::RandomPanic(RandomPanicMiddleware {
4086
+ mode: FaultMode::JsonFormatError,
4087
+ trigger_on_message: None,
4088
+ enabled: true,
4089
+ ..Default::default()
4090
+ })];
4091
+
4092
+ let input_ch = input.channel().unwrap();
4093
+ input_ch.send_message("poison".into()).await.unwrap();
4094
+
4095
+ let route = Route::new(input, output)
4096
+ .with_fault_injection(true)
4097
+ .with_exit_on_empty(true);
4098
+ let handle = route.run("test_dropped_poison_recorded").await.unwrap();
4099
+
4100
+ let outcome = tokio::time::timeout(Duration::from_secs(10), async {
4101
+ loop {
4102
+ if let Some(outcome) = handle.outcome() {
4103
+ return outcome;
4104
+ }
4105
+ tokio::time::sleep(Duration::from_millis(20)).await;
4106
+ }
4107
+ })
4108
+ .await
4109
+ .expect("the drain finishes rather than retrying the poison batch forever");
4110
+
4111
+ assert_eq!(
4112
+ outcome,
4113
+ RouteOutcome::Completed,
4114
+ "dropping the batch lets the drain finish"
4115
+ );
4116
+ let error = handle.status().error.unwrap_or_default();
4117
+ assert!(
4118
+ error.contains("dropped 1 message"),
4119
+ "the discarded batch is reported, not silently swallowed: {error:?}"
4120
+ );
4121
+ assert!(
4122
+ error.contains("JSON format error"),
4123
+ "the reported cause names the underlying rejection: {error:?}"
4124
+ );
4125
+ }
4126
+
3956
4127
  #[tokio::test(flavor = "multi_thread")]
3957
4128
  async fn test_route_dlq_integration() {
3958
4129
  // Setup: Input -> [Panic(Disconnect) -> Retry -> DLQ] -> Output