mq-bridge-py-basic 0.4.3__tar.gz → 0.4.5__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.3 → mq_bridge_py_basic-0.4.5}/.github/workflows/ci.yml +70 -126
  2. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/.github/workflows/ibm-mq.yml +12 -2
  3. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/.github/workflows/node.yml +6 -0
  4. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/.github/workflows/python.yml +6 -0
  5. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/.github/workflows/test-matrix.yml +6 -0
  6. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/CHANGELOG.md +87 -0
  7. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/Cargo.lock +4 -4
  8. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/Cargo.toml +1 -1
  9. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/PKG-INFO +1 -1
  10. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/README.md +2 -2
  11. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/docs/DELIVERY.md +58 -26
  12. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/mq-bridge.schema.json +47 -10
  13. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/mq_bridge/config.py +2 -0
  14. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/mq_bridge/config.pyi +6 -3
  15. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/file/mod.rs +46 -24
  16. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/file/tests.rs +7 -7
  17. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/mod.rs +245 -43
  18. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/object_store.rs +754 -80
  19. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/models/builders.rs +34 -4
  20. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/models/defaults.rs +0 -19
  21. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/models/tests.rs +1 -1
  22. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/models.rs +63 -12
  23. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/route.rs +170 -18
  24. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/support/source_ranges.rs +47 -0
  25. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  26. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  27. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  28. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/.github/dependabot.yml +0 -0
  29. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/.github/workflows/benchmark.yml +0 -0
  30. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/.github/workflows/publish-node.yml +0 -0
  31. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/.github/workflows/publish-python.yml +0 -0
  32. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/.github/workflows/release.yml +0 -0
  33. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/.gitignore +0 -0
  34. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/CLAUDE.md +0 -0
  35. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/CONTRIBUTING.md +0 -0
  36. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/LICENSE +0 -0
  37. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/LICENSE.python +0 -0
  38. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/SECURITY.md +0 -0
  39. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/benches/ETL_BENCHMARKS.md +0 -0
  40. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/benches/performance_bench.rs +0 -0
  41. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/benches/router_bench.rs +0 -0
  42. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/benches/zeromq_backends.rs +0 -0
  43. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/bindings-common/Cargo.toml +0 -0
  44. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/bindings-common/src/lib.rs +0 -0
  45. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/bindings-common/src/logging.rs +0 -0
  46. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/build.rs +0 -0
  47. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/deny.toml +0 -0
  48. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/docs/ARCHITECTURE.md +0 -0
  49. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/docs/CONFIGURATION.md +0 -0
  50. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/docs/EXTENDING.md +0 -0
  51. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/docs/PLUGINS.md +0 -0
  52. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/docs/REFERENCE.md +0 -0
  53. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/examples/ipc_worker_queue.yaml +0 -0
  54. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/mq_bridge/__init__.py +0 -0
  55. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/mq_bridge/__init__.pyi +0 -0
  56. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/mq_bridge/plugin_packaging.py +0 -0
  57. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/mq_bridge/py.typed +0 -0
  58. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/package-lock.json +0 -0
  59. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/pyproject.toml +0 -0
  60. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/Cargo.toml +0 -0
  61. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/LICENSE.python +0 -0
  62. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/README.md +0 -0
  63. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/analysis/bench_http_native.py +0 -0
  64. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/example.py +0 -0
  65. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/examples/bench_memory.py +0 -0
  66. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/examples/bench_memory.yaml +0 -0
  67. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/examples/consume_pull.py +0 -0
  68. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/examples/dlt_source.py +0 -0
  69. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/examples/json_route.py +0 -0
  70. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/examples/memory.yaml +0 -0
  71. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/examples/raw_route.py +0 -0
  72. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/pyproject-basic.toml +0 -0
  73. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/pyproject-reduced.toml +0 -0
  74. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/scripts/gen_config_types.py +0 -0
  75. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/src/lib.rs +0 -0
  76. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/tests/test_config_types.py +0 -0
  77. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/tests/test_custom_endpoint.py +0 -0
  78. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/tests/test_logging.py +0 -0
  79. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/tests/test_packaging.py +0 -0
  80. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/tests/test_performance_smoke.py +0 -0
  81. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/tests/test_plugin_package.py +0 -0
  82. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/tests/test_public_api.py +0 -0
  83. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/tests/test_routes.py +0 -0
  84. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/python/mq-bridge-py/uv.lock +0 -0
  85. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/analysis/benches/metadata_bench.rs +0 -0
  86. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/analysis/debug_ibm_mq_tls.rs +0 -0
  87. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/analysis/http/analyze_xctrace_time_profile.py +0 -0
  88. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/analysis/http/http_flamegraph.py +0 -0
  89. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/analysis/http/mq_bridge_http_profile.rs +0 -0
  90. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/analysis/http/run_http_ladder.sh +0 -0
  91. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/ci/format_bench_output.sh +0 -0
  92. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/httparena/README.md +0 -0
  93. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/httparena/frameworks/mq-bridge-py/Dockerfile +0 -0
  94. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/httparena/frameworks/mq-bridge-py/meta.json +0 -0
  95. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/httparena/frameworks/mq-bridge-py/server.py +0 -0
  96. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/techempower/Python/mq-bridge-py/README.md +0 -0
  97. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/techempower/Python/mq-bridge-py/benchmark_config.json +0 -0
  98. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/techempower/Python/mq-bridge-py/mq-bridge-py.dockerfile +0 -0
  99. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/techempower/Python/mq-bridge-py/server.py +0 -0
  100. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/techempower/README.md +0 -0
  101. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/techempower/postgres.yml +0 -0
  102. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/techempower/seed.sql +0 -0
  103. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/techempower/verify.sh +0 -0
  104. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/the-benchmarker/README.md +0 -0
  105. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/the-benchmarker/python/mq-bridge-py/config.yaml +0 -0
  106. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/the-benchmarker/python/mq-bridge-py/pyproject.toml +0 -0
  107. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/scripts/the-benchmarker/python/mq-bridge-py/server.py +0 -0
  108. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/canonical_message.rs +0 -0
  109. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/checkpoint.rs +0 -0
  110. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/command_handler.rs +0 -0
  111. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/amqp.rs +0 -0
  112. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/aws.rs +0 -0
  113. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/clickhouse.rs +0 -0
  114. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/grpc.proto +0 -0
  115. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/grpc.rs +0 -0
  116. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/http/mod.rs +0 -0
  117. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/http/publisher.rs +0 -0
  118. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/http/stream.rs +0 -0
  119. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/http/tests.rs +0 -0
  120. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/ibm_mq.rs +0 -0
  121. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/kafka.rs +0 -0
  122. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/memory/endpoint.rs +0 -0
  123. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/memory/framed.rs +0 -0
  124. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/memory/ipc_unix.rs +0 -0
  125. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/memory/ipc_windows.rs +0 -0
  126. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/memory/memory_transport.rs +0 -0
  127. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/memory/mod.rs +0 -0
  128. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/memory/transport.rs +0 -0
  129. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/mongodb/consumer.rs +0 -0
  130. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/mongodb/dedup.rs +0 -0
  131. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/mongodb/mod.rs +0 -0
  132. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/mongodb/publisher.rs +0 -0
  133. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/mongodb/readers.rs +0 -0
  134. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/mongodb/tests.rs +0 -0
  135. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/mqtt.rs +0 -0
  136. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/nats.rs +0 -0
  137. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/poll.rs +0 -0
  138. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/postgres/VENDORED.md +0 -0
  139. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/postgres/mod.rs +0 -0
  140. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/postgres/pgoutput/decoder.rs +0 -0
  141. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/postgres/pgoutput/messages.rs +0 -0
  142. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/postgres/pgoutput/mod.rs +0 -0
  143. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/postgres/pgoutput/registry.rs +0 -0
  144. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/postgres/pgoutput/values.rs +0 -0
  145. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/postgres/replication.rs +0 -0
  146. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/postgres/state.rs +0 -0
  147. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/redis_streams.rs +0 -0
  148. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/sled.rs +0 -0
  149. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/sqlx/dedup.rs +0 -0
  150. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/sqlx/mod.rs +0 -0
  151. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/sqlx/tests.rs +0 -0
  152. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/structural/fanout.rs +0 -0
  153. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/structural/mod.rs +0 -0
  154. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/structural/null.rs +0 -0
  155. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/structural/reader.rs +0 -0
  156. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/structural/request.rs +0 -0
  157. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/structural/response.rs +0 -0
  158. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/structural/static_endpoint.rs +0 -0
  159. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/structural/stream_buffer.rs +0 -0
  160. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/structural/switch.rs +0 -0
  161. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/websocket.rs +0 -0
  162. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/zeromq/codec.rs +0 -0
  163. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/zeromq/mod.rs +0 -0
  164. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/zeromq/omq.rs +0 -0
  165. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/endpoints/zeromq/zmq.rs +0 -0
  166. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/errors.rs +0 -0
  167. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/event_handler.rs +0 -0
  168. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/event_store.rs +0 -0
  169. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/extensions.rs +0 -0
  170. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/lib.rs +0 -0
  171. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/buffer.rs +0 -0
  172. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/compression.rs +0 -0
  173. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/cookie_jar.rs +0 -0
  174. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/deduplication.rs +0 -0
  175. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/delay.rs +0 -0
  176. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/dlq.rs +0 -0
  177. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/encryption.rs +0 -0
  178. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/id.rs +0 -0
  179. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/limiter.rs +0 -0
  180. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/metrics.rs +0 -0
  181. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/mod.rs +0 -0
  182. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/random_panic.rs +0 -0
  183. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/retry.rs +0 -0
  184. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/transform/coerce.rs +0 -0
  185. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/transform/compiled.rs +0 -0
  186. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/transform/error.rs +0 -0
  187. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/transform/mod.rs +0 -0
  188. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/transform/path.rs +0 -0
  189. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/transform/schema.rs +0 -0
  190. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/transform/tests.rs +0 -0
  191. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/middleware/weak_join.rs +0 -0
  192. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/models/secrets.rs +0 -0
  193. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/models/serde_support.rs +0 -0
  194. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/outcomes.rs +0 -0
  195. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/plugin/conformance.rs +0 -0
  196. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/plugin/endpoint.rs +0 -0
  197. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/plugin/message.rs +0 -0
  198. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/plugin/middleware.rs +0 -0
  199. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/plugin/mod.rs +0 -0
  200. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/plugin/sdk.rs +0 -0
  201. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/plugin/test_support.rs +0 -0
  202. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/publisher.rs +0 -0
  203. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/response.rs +0 -0
  204. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/support/base64_engine.rs +0 -0
  205. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/support/compression.rs +0 -0
  206. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/support/connection_registry.rs +0 -0
  207. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/support/crypto.rs +0 -0
  208. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/support/crypto_envelope.rs +0 -0
  209. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/support/interpolation.rs +0 -0
  210. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/support/mod.rs +0 -0
  211. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/support/plugin_abi.rs +0 -0
  212. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/test_utils.rs +0 -0
  213. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/traits.rs +0 -0
  214. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/src/type_handler.rs +0 -0
  215. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/README.md +0 -0
  216. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/armature_integration.rs +0 -0
  217. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/amqp.rs +0 -0
  218. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/aws.rs +0 -0
  219. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/clickhouse.rs +0 -0
  220. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/config.toml +0 -0
  221. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/amqp.yml +0 -0
  222. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/aws.yml +0 -0
  223. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/clickhouse.yml +0 -0
  224. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/ibm-mq-certs/client.crl +0 -0
  225. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/ibm-mq-certs/client.kdb +0 -0
  226. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/ibm-mq-certs/client.p12 +0 -0
  227. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/ibm-mq-certs/client.rdb +0 -0
  228. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/ibm-mq-certs/client.sth +0 -0
  229. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/ibm_mq.yml +0 -0
  230. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/ibm_mq_tls.yml +0 -0
  231. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/kafka-tls.yml +0 -0
  232. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/kafka.yml +0 -0
  233. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/mariadb.yml +0 -0
  234. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/mongodb-replica.yml +0 -0
  235. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/mongodb-tls.yml +0 -0
  236. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/mongodb.yml +0 -0
  237. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/mosquitto.conf +0 -0
  238. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/mosquitto_performance.conf +0 -0
  239. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/mosquitto_persistence.conf +0 -0
  240. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/mq_init.mqsc +0 -0
  241. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/mq_init_tls.mqsc +0 -0
  242. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/mqtt.yml +0 -0
  243. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/mqtt_performance.yml +0 -0
  244. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/mysql.yml +0 -0
  245. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/nats.yml +0 -0
  246. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/object_store.yml +0 -0
  247. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/postgres.yml +0 -0
  248. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/postgres_cdc.yml +0 -0
  249. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/docker-compose/redis.yml +0 -0
  250. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/file.rs +0 -0
  251. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/grpc.rs +0 -0
  252. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/grpc_tls.rs +0 -0
  253. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/http.rs +0 -0
  254. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/http_tls.rs +0 -0
  255. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/ibm_mq.rs +0 -0
  256. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/ibm_mq_tls.rs +0 -0
  257. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/ipc.rs +0 -0
  258. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/kafka.rs +0 -0
  259. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/kafka_tls.rs +0 -0
  260. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/logic_test.rs +0 -0
  261. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/mariadb.rs +0 -0
  262. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/memory.rs +0 -0
  263. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/mod.rs +0 -0
  264. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/mongodb.rs +0 -0
  265. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/mongodb_raw.rs +0 -0
  266. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/mongodb_tls.rs +0 -0
  267. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/mqtt.rs +0 -0
  268. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/mysql.rs +0 -0
  269. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/nats.rs +0 -0
  270. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/object_store.rs +0 -0
  271. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/performance_static.rs +0 -0
  272. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/postgres.rs +0 -0
  273. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/postgres_cdc.rs +0 -0
  274. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/redis_streams.rs +0 -0
  275. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/route.rs +0 -0
  276. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/scripts/gen_certs.sh +0 -0
  277. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/sqlite.rs +0 -0
  278. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/tls_helpers.rs +0 -0
  279. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/websocket.rs +0 -0
  280. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration/zeromq.rs +0 -0
  281. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/integration_test.rs +0 -0
  282. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/memory_leak_test.rs +0 -0
  283. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/ref_test.rs +0 -0
  284. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/reference_docs_test.rs +0 -0
  285. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/sqlite_test.rs +0 -0
  286. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/tls_example.rs +0 -0
  287. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/unit_tests.md +0 -0
  288. {mq_bridge_py_basic-0.4.3 → mq_bridge_py_basic-0.4.5}/tests/websocket_test.rs +0 -0
@@ -1,10 +1,20 @@
1
1
  name: CI
2
2
 
3
3
  on:
4
- push:
5
- branches: [main]
6
4
  pull_request:
7
5
  branches: [main, dev]
6
+ workflow_dispatch:
7
+
8
+ # Only the tip of a PR branch is worth testing; superseded runs are cancelled so
9
+ # they stop holding runner slots the integration jobs are waiting for.
10
+ concurrency:
11
+ group: ${{ github.workflow }}-${{ github.ref }}
12
+ cancel-in-progress: true
13
+
14
+ # Nothing in CI writes back to the repository; artifacts move through the Actions
15
+ # runtime token, not this one.
16
+ permissions:
17
+ contents: read
8
18
 
9
19
  env:
10
20
  CARGO_TERM_COLOR: always
@@ -25,11 +35,6 @@ jobs:
25
35
 
26
36
  - name: Cache cargo build
27
37
  uses: Swatinem/rust-cache@v2
28
- with:
29
- # Differentiates the matrix `check` job per feature set; evaluates to an
30
- # empty string (no-op) in non-matrix jobs. rust-cache already keys on the
31
- # job id, OS, rustc version, and lockfiles automatically.
32
- key: ${{ matrix.features }}
33
38
 
34
39
  - name: Check formatting
35
40
  run: cargo fmt --all -- --check
@@ -37,44 +42,37 @@ jobs:
37
42
  - name: Run clippy
38
43
  run: cargo clippy --all-targets --all-features -- -D warnings
39
44
 
40
- # Build with all features
45
+ # Every feature subset still gets its own `cargo check`, but sequentially in one
46
+ # job: the matrix cost 8 runner slots at the moment integration-build's dependents
47
+ # were starving, and none of this is on the critical path.
41
48
  build:
42
- name: Build
49
+ name: Build (feature subsets)
43
50
  runs-on: ubuntu-latest
44
- strategy:
45
- matrix:
46
- features:
47
- - ""
48
- - "full"
49
- - "kafka"
50
- # "amqp" # no recent changes, already included in full
51
- - "nats"
52
- - "grpc"
53
- - "mqtt"
54
- - "mongodb"
55
- - "http"
56
- # - "aws" # needs too long, already included in full
57
- # - "zeromq" # no recent changes, already included in full
58
51
  steps:
59
52
  - uses: actions/checkout@v4
60
-
53
+
61
54
  - name: Install Rust toolchain
62
55
  uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
63
-
56
+
64
57
  - name: Cache cargo build
65
58
  uses: Swatinem/rust-cache@v2
66
- with:
67
- # Differentiates the matrix `check` job per feature set; evaluates to an
68
- # empty string (no-op) in non-matrix jobs. rust-cache already keys on the
69
- # job id, OS, rustc version, and lockfiles automatically.
70
- key: ${{ matrix.features }}
71
-
72
- - name: Check
59
+
60
+ # amqp/aws/zeromq are omitted: unchanged for a while and covered by `full`.
61
+ - name: Check each feature subset
73
62
  run: |
74
- if [ -z "${{ matrix.features }}" ]; then
75
- cargo check --all-targets
76
- else
77
- cargo check --all-targets --features "${{ matrix.features }}"
63
+ failed=""
64
+ for f in "" full kafka nats grpc mqtt mongodb http; do
65
+ echo "::group::cargo check --features ${f:-<default>}"
66
+ if [ -z "$f" ]; then
67
+ cargo check --all-targets || failed="$failed <default>"
68
+ else
69
+ cargo check --all-targets --features "$f" || failed="$failed $f"
70
+ fi
71
+ echo "::endgroup::"
72
+ done
73
+ if [ -n "$failed" ]; then
74
+ echo "::error::feature subsets failed:$failed"
75
+ exit 1
78
76
  fi
79
77
 
80
78
  # Unit tests
@@ -89,11 +87,6 @@ jobs:
89
87
 
90
88
  - name: Cache cargo build
91
89
  uses: Swatinem/rust-cache@v2
92
- with:
93
- # Differentiates the matrix `check` job per feature set; evaluates to an
94
- # empty string (no-op) in non-matrix jobs. rust-cache already keys on the
95
- # job id, OS, rustc version, and lockfiles automatically.
96
- key: ${{ matrix.features }}
97
90
 
98
91
  - name: Run unit tests
99
92
  run: cargo test --lib --features=full
@@ -145,12 +138,32 @@ jobs:
145
138
  path: nextest-archive.tar.zst
146
139
  retention-days: 1
147
140
 
148
- # Integration tests (requires Docker) split into parallel jobs. Each runs the
149
- # prebuilt nextest archive from integration-build — no recompilation.
150
- integration-others:
151
- name: Integration — Others
141
+ # Integration tests (requires Docker), split across runners by measured runtime
142
+ # so no single job dominates the critical path. Each runs the prebuilt nextest
143
+ # archive from integration-build — no recompilation. `--no-capture` implies
144
+ # `--test-threads=1`, and tests tear their compose stacks down with `down -v`,
145
+ # so parallelism has to come from separate runners rather than from nextest.
146
+ integration:
147
+ name: Integration — ${{ matrix.name }}
152
148
  runs-on: ubuntu-latest
153
149
  needs: integration-build
150
+ timeout-minutes: 30
151
+ strategy:
152
+ fail-fast: false
153
+ matrix:
154
+ include:
155
+ - name: Status
156
+ filter: 'binary(integration_test) & test(=test_all_status)'
157
+ - name: Chaos
158
+ filter: 'binary(integration_test) & test(=test_all_chaos)'
159
+ - name: Logic
160
+ filter: 'binary(integration_test) & (test(=test_all_request_reply) | test(=test_all_subscriber_logic))'
161
+ - name: Endpoints
162
+ filter: 'binary(integration_test) & not test(=test_all_status) & not test(=test_all_chaos) & not test(=test_all_request_reply) & not test(=test_all_subscriber_logic) & not test(=test_all_performance_pipeline) & not test(=test_all_performance_direct)'
163
+ - name: Performance Pipeline
164
+ filter: 'binary(integration_test) & test(=test_all_performance_pipeline)'
165
+ - name: Performance Direct
166
+ filter: 'binary(integration_test) & test(=test_all_performance_direct)'
154
167
  services:
155
168
  docker:
156
169
  image: docker:dind
@@ -171,58 +184,17 @@ jobs:
171
184
  - name: Pre-pull docker images
172
185
  run: |
173
186
  find tests/integration/docker-compose -name "*.yml" | xargs -P 5 -I {} docker compose -f {} pull -q
174
- - name: Install JRE (for keytool)
175
- run: |
176
- sudo apt-get update
177
- sudo apt-get install -y default-jre-headless
178
-
179
- - name: Generate TLS certs for integration services
180
- run: |
181
- chmod +x tests/integration/scripts/gen_certs.sh
182
- ./tests/integration/scripts/gen_certs.sh mongodb
183
- ./tests/integration/scripts/gen_certs.sh kafka
184
- ./tests/integration/scripts/gen_certs.sh ibm-mq
185
-
186
- - name: Run chaos/stability tests
187
- run: |
188
- cargo nextest run --archive-file nextest-archive.tar.zst \
189
- --run-ignored all --no-capture \
190
- -E 'binary(integration_test) & test(=test_all_chaos)'
191
-
192
- - name: Run remaining integration tests (excluding chaos & performance)
193
- run: |
194
- cargo nextest run --archive-file nextest-archive.tar.zst \
195
- --run-ignored all --no-capture \
196
- -E 'binary(integration_test) & not test(=test_all_chaos) & not test(=test_all_performance_pipeline) & not test(=test_all_performance_direct)'
197
-
198
- integration-performance:
199
- name: Integration — Performance
200
- runs-on: ubuntu-latest
201
- needs: integration-build
202
- services:
203
- docker:
204
- image: docker:dind
205
- options: --privileged
206
- steps:
207
- - uses: actions/checkout@v4
208
-
209
- - name: Install cargo-nextest
210
- uses: taiki-e/install-action@v2
211
- with:
212
- tool: nextest
213
187
 
214
- - name: Download nextest archive
215
- uses: actions/download-artifact@v4
216
- with:
217
- name: integration-nextest-archive
218
-
219
- - name: Pre-pull docker images
220
- run: |
221
- find tests/integration/docker-compose -name "*.yml" | xargs -P 5 -I {} docker compose -f {} pull -q
222
188
  - name: Install JRE (for keytool)
189
+ timeout-minutes: 5
223
190
  run: |
224
- sudo apt-get update
225
- sudo apt-get install -y default-jre-headless
191
+ # Runner images ship a JDK; only pay the 46 MB download if they didn't.
192
+ # A degraded apt mirror used to stall this step for hours.
193
+ if command -v keytool >/dev/null 2>&1; then exit 0; fi
194
+ sudo apt-get update -qq
195
+ sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y \
196
+ -o Acquire::Retries=3 -o Acquire::http::Timeout=20 \
197
+ default-jre-headless
226
198
 
227
199
  - name: Generate TLS certs for integration services
228
200
  run: |
@@ -231,26 +203,18 @@ jobs:
231
203
  ./tests/integration/scripts/gen_certs.sh kafka
232
204
  ./tests/integration/scripts/gen_certs.sh ibm-mq
233
205
 
234
- - name: Run pipeline performance tests
235
- run: |
236
- cargo nextest run --archive-file nextest-archive.tar.zst \
237
- --run-ignored all --no-capture \
238
- -E 'binary(integration_test) & test(=test_all_performance_pipeline)'
239
-
240
- - name: Run other performance tests
206
+ - name: Run ${{ matrix.name }} integration tests
241
207
  run: |
242
208
  cargo nextest run --archive-file nextest-archive.tar.zst \
243
209
  --run-ignored all --no-capture \
244
- -E 'binary(integration_test) & test(=test_all_performance_direct)'
210
+ -E '${{ matrix.filter }}'
245
211
 
212
+ # Armature clones an external repo and runs its test suite: no docker stacks, no
213
+ # TLS certs, no keytool. It used to pay ~1.3m of setup for 1.7m of tests.
246
214
  integration-armature:
247
215
  name: Integration — Armature
248
216
  runs-on: ubuntu-latest
249
217
  needs: integration-build
250
- services:
251
- docker:
252
- image: docker:dind
253
- options: --privileged
254
218
  steps:
255
219
  - uses: actions/checkout@v4
256
220
 
@@ -264,21 +228,6 @@ jobs:
264
228
  with:
265
229
  name: integration-nextest-archive
266
230
 
267
- - name: Pre-pull docker images
268
- run: |
269
- find tests/integration/docker-compose -name "*.yml" | xargs -P 5 -I {} docker compose -f {} pull -q
270
- - name: Install JRE (for keytool)
271
- run: |
272
- sudo apt-get update
273
- sudo apt-get install -y default-jre-headless
274
-
275
- - name: Generate TLS certs for integration services
276
- run: |
277
- chmod +x tests/integration/scripts/gen_certs.sh
278
- ./tests/integration/scripts/gen_certs.sh mongodb
279
- ./tests/integration/scripts/gen_certs.sh kafka
280
- ./tests/integration/scripts/gen_certs.sh ibm-mq
281
-
282
231
  - name: Run armature integration tests
283
232
  run: |
284
233
  cargo nextest run --archive-file nextest-archive.tar.zst \
@@ -297,11 +246,6 @@ jobs:
297
246
 
298
247
  - name: Cache cargo build
299
248
  uses: Swatinem/rust-cache@v2
300
- with:
301
- # Differentiates the matrix `check` job per feature set; evaluates to an
302
- # empty string (no-op) in non-matrix jobs. rust-cache already keys on the
303
- # job id, OS, rustc version, and lockfiles automatically.
304
- key: ${{ matrix.features }}
305
249
 
306
250
  - name: Build documentation (deny warnings)
307
251
  run: RUSTDOCFLAGS="-D warnings" cargo doc --all-features --no-deps
@@ -21,6 +21,12 @@ on:
21
21
  - '.github/workflows/ibm-mq.yml'
22
22
  workflow_dispatch:
23
23
 
24
+ # Superseded PR runs are cancelled; push runs always finish so every pre-merge
25
+ # commit keeps its own verdict.
26
+ concurrency:
27
+ group: ${{ github.workflow }}-${{ github.ref }}
28
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
29
+
24
30
  env:
25
31
  CARGO_TERM_COLOR: always
26
32
  RUST_BACKTRACE: 1
@@ -144,9 +150,13 @@ jobs:
144
150
 
145
151
  - name: Install JDK (for keytool - TLS tests)
146
152
  if: steps.mqclient.outputs.available == 'true'
153
+ timeout-minutes: 5
147
154
  run: |
148
- sudo apt-get update
149
- sudo apt-get install -y default-jdk
155
+ if command -v keytool >/dev/null 2>&1; then exit 0; fi
156
+ sudo apt-get update -qq
157
+ sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y \
158
+ -o Acquire::Retries=3 -o Acquire::http::Timeout=20 \
159
+ default-jdk
150
160
 
151
161
  - name: Generate TLS certificates
152
162
  if: steps.mqclient.outputs.available == 'true'
@@ -19,6 +19,12 @@ on:
19
19
  - "src/**"
20
20
  workflow_dispatch:
21
21
 
22
+ # Superseded PR runs are cancelled; push runs always finish so every pre-merge
23
+ # commit keeps its own verdict.
24
+ concurrency:
25
+ group: ${{ github.workflow }}-${{ github.ref }}
26
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
27
+
22
28
  env:
23
29
  CARGO_TERM_COLOR: always
24
30
 
@@ -19,6 +19,12 @@ on:
19
19
  - "src/**"
20
20
  workflow_dispatch:
21
21
 
22
+ # Superseded PR runs are cancelled; push runs always finish so every pre-merge
23
+ # commit keeps its own verdict.
24
+ concurrency:
25
+ group: ${{ github.workflow }}-${{ github.ref }}
26
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
27
+
22
28
  env:
23
29
  CARGO_TERM_COLOR: always
24
30
 
@@ -6,6 +6,12 @@ on:
6
6
  pull_request:
7
7
  branches: [main, dev]
8
8
 
9
+ # Superseded PR runs are cancelled; push runs always finish so every pre-merge
10
+ # commit keeps its own verdict.
11
+ concurrency:
12
+ group: ${{ github.workflow }}-${{ github.ref }}
13
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
14
+
9
15
  env:
10
16
  CARGO_TERM_COLOR: always
11
17
 
@@ -2,6 +2,93 @@
2
2
 
3
3
  All notable changes to `mq-bridge`. Newest first.
4
4
 
5
+ ## 0.4.4
6
+
7
+ ### Breaking
8
+
9
+ - **`idempotency` on the `file` and `object_store` sinks is replaced by `name_by`.** The old
10
+ field described a consequence rather than the thing it set. What it actually chooses is how
11
+ written objects and parts are *named*, and everything else — sortability, replay dedup,
12
+ whether `date_partition` applies, how errors are reported — follows from that name:
13
+
14
+ | `name_by` | Name | Consequence |
15
+ | --- | --- | --- |
16
+ | `write_time` | `<uuidv7>.<ext>`, optionally under `YYYY/MM/DD/` | unique per write, sorts by write order |
17
+ | `source_position` | `part-<topic>-<partition>-<start>-<end>.<ext>`, zero-padded, flat | repeats exactly on a replay, sorts by source order |
18
+ | `auto` (new default) | `source_position` where the input carries a replay position, else `write_time` | see below |
19
+
20
+ `idempotency: true|false` is still read and still means
21
+ `name_by: source_position|write_time`, so v0.4.x configs keep loading. An explicit `name_by`
22
+ wins over it.
23
+
24
+ - **An `object_store` sink now defaults to `source_position` naming over a replayable input**
25
+ (Kafka, Postgres CDC, a SQL cursor, a MongoDB change stream, or a file). Key order is the
26
+ only order a bucket has, so this is what makes `mqb copy orders.csv s3://…` come back in
27
+ source order at any `concurrency` without configuring anything — and it is what removed the
28
+ `concurrency > 1` warning from that route. Three consequences to know about:
29
+ - **A re-run into the same prefix writes nothing — where the source repeats its
30
+ positions.** The names repeat, and a repeat is a no-op. That covers a re-read of the same
31
+ file, Kafka offsets, a SQL cursor and a CDC stream. A file source in `subscribe` or
32
+ `group_subscribe` mode is the exception: it stamps a per-run epoch, so its names stay
33
+ distinct across runs and a re-run writes a second copy. Where the no-op does apply it is a
34
+ change of behaviour — the same command used to append a second copy under fresh uuid
35
+ names. Use a fresh prefix, or `name_by: write_time`, if you want the old behaviour. The
36
+ no-op also needs the prefix listing to succeed: a replay whose batches fall on different
37
+ boundaries names different objects, so where the listing is denied the sink can only catch
38
+ a repeat that lands on the exact same name and the rest is written twice.
39
+ - **`date_partition` does not apply** under `source_position`; parts are written flat.
40
+ - **Do not mix the two families in one prefix.** uuid names and `part-…` names do not sort
41
+ correctly against each other. A prefix written by an older version keeps working on its
42
+ own; point the upgraded route at a new prefix if a reader depends on listing order.
43
+
44
+ - **The `file` sink stays on `write_time` under `auto`** and must be told
45
+ `name_by: source_position` explicitly. There, positional naming turns `path` from a file
46
+ into a *directory* of part files — a change of structure, not of name, and not something to
47
+ derive on the operator's behalf.
48
+
49
+ - `object_store` `date_partition` is now `Option<bool>` (unset = on, and only for
50
+ `write_time`). Side effect: the "`date_partition` is a publisher-only option" warning used
51
+ to fire for *every* `object_store` consumer, because the field defaulted to `true` and the
52
+ check could not tell that from an explicit setting. It now fires only when the field was
53
+ actually set.
54
+
55
+ ### Changed
56
+
57
+ - **The `object_store` sink lists its prefix only on the `source_position` write path**, and
58
+ only once per publisher, immediately before its first write rather than when it opens. A
59
+ `write_time` sink never lists at all; a `source_position` restart into a populated prefix
60
+ pays for exactly one `LIST` and then skips the rest of the replay without re-encoding or
61
+ re-uploading. The listing cannot be deferred any further than this: `PutMode::Create` only
62
+ catches a repeat that lands on the same object name, so a replay whose batches fall on
63
+ different boundaries collides with nothing and would otherwise write every record a second
64
+ time under overlapping names. A listing that fails is retried on the next batch, unless it
65
+ failed for a reason retrying cannot clear (a denied `ListObjects`), in which case the sink
66
+ warns once and falls back to same-name-only deduplication.
67
+ - **The `concurrency > 1` warning now fires only for a `write_time` name**, which is the only
68
+ case where write order is not source order — under `auto` over a replayable input that is
69
+ now nobody. It names `name_by: source_position` where the input carries a replay position
70
+ and `concurrency: 1` otherwise, rather than pointing at a setting that would fail on an
71
+ input with no position.
72
+ - The `source_position` write path reports `SentBatch::Partial` like the ordinary path does.
73
+ A record that cannot be encoded splits the run instead of failing the whole batch: the
74
+ offsets around it are written under names covering exactly what went in, and the bad record
75
+ goes to the DLQ. (Encode failures are unreachable in practice today; this removes an
76
+ asymmetry rather than fixing an observed bug.)
77
+
78
+ ### Fixed
79
+
80
+ - A failed prefix listing no longer fails an `object_store` batch. The error was propagated as
81
+ non-retryable, which dropped a replay's batch on a bucket that denies `ListObjects`, or on a
82
+ transient listing hiccup. It is now logged and the sink degrades to same-name-only
83
+ deduplication: a transient failure is retried on the next batch, while a denied `ListObjects`
84
+ is latched after one warning and not retried.
85
+
86
+ - A route rejected for `name_by: source_position` over an input that carries no replay position
87
+ no longer leaves a directory behind at a `file` sink's `path`. The publisher opens before the
88
+ consumer, and the part-file sink creates its directory as it opens, so the rejected route used
89
+ to turn the operator's output *file* into an empty directory — after which a corrected run
90
+ failed on the leftover. The requirement is now checked before any sink opens.
91
+
5
92
  ## 0.4.0
6
93
 
7
94
  ### Breaking
@@ -3348,7 +3348,7 @@ dependencies = [
3348
3348
 
3349
3349
  [[package]]
3350
3350
  name = "mq-bridge"
3351
- version = "0.4.3"
3351
+ version = "0.4.5"
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.3"
3434
+ version = "0.4.5"
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.3"
3448
+ version = "0.4.5"
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.3"
3490
+ version = "0.4.5"
3491
3491
  dependencies = [
3492
3492
  "anyhow",
3493
3493
  "async-trait",
@@ -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.3"
19
+ version = "0.4.5"
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.3
3
+ Version: 0.4.5
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: License :: OSI Approved :: MIT License
6
6
  Classifier: Programming Language :: Python :: 3
@@ -268,7 +268,7 @@ deduplicate on, and what a handler in the route changes about all of this, is co
268
268
 
269
269
  > **[docs/DELIVERY.md](docs/DELIVERY.md) — delivery guarantees.** Per-source identity and
270
270
  > per-sink idempotency tables, the `deduplication` middleware, Mongo `id_field` and `report_outcome`,
271
- > SQL `ON CONFLICT`, ClickHouse `ReplacingMergeTree`, file/object-store `idempotency: true`, what
271
+ > SQL `ON CONFLICT`, ClickHouse `ReplacingMergeTree`, file/object-store `name_by: source_position`, what
272
272
  > handlers change, and what `mq-bridge` deliberately does not provide.
273
273
 
274
274
  The short form: point the sink at a deterministic business key (`id_field` for MongoDB, an
@@ -279,7 +279,7 @@ across every writer, so no extra state store is needed. Add the `deduplication`
279
279
  ### Cloud Object Storage (S3 / GCS / Azure)
280
280
  The `object_store` endpoint (alias `s3`) reads and writes cloud object stores — Amazon S3, Google Cloud Storage, Azure Blob, Cloudflare R2, and anything else the [`object_store`](https://crates.io/crates/object_store) crate speaks — behind the same `receive_batch` / `send_batch` API. Enable it with the `object-store` feature. Credentials and backend options are read from the process environment (`AWS_ACCESS_KEY_ID`, `AWS_ENDPOINT`, `AWS_REGION`, `GOOGLE_SERVICE_ACCOUNT`, `AZURE_STORAGE_ACCOUNT`, ...); the URL scheme picks the backend (`s3://`, `gs://`, `az://`).
281
281
 
282
- * **As a sink**, each flushed batch is encoded with the same file endpoint formats (`normal` JSONL, `json`, `text`, `raw`) and written as **one immutable object** at `<prefix>/[YYYY/MM/DD/]<uuidv7>.<ext>`. Objects are write-once — nothing is appended or mutated. The uuidv7 name already sorts by write time; the optional `date_partition` prefix (on by default, derived from that same id's timestamp) is a readability / lifecycle-rule convenience. This naming applies only while `idempotency` is off — with `idempotency: true` the parts are instead named for the source range they cover and written flat under the prefix, and `date_partition` is ignored (see [Files & object storage — `idempotency`](docs/DELIVERY.md#files--object-storage--idempotency)).
282
+ * **As a sink**, batches are encoded with the same file endpoint formats (`normal` JSONL, `json`, `text`, `raw`) and written as whole immutable objects — write-once, nothing appended or mutated. Under `name_by: write_time` each flushed batch becomes **one object** at `<prefix>/[YYYY/MM/DD/]<uuidv7>.<ext>`; the uuidv7 name already sorts by write time, and the optional `date_partition` prefix (on by default, derived from that same id's timestamp) is a readability / lifecycle-rule convenience. Under `name_by: source_position` a batch becomes **one object per contiguous run of source positions** it covers — usually one, more when the batch spans partitions or skips offsets a replay already wrote — each named for the range it covers and written flat under the prefix, where `date_partition` does not apply. The default `name_by: auto` picks `source_position` whenever the route's input carries a replay position — Kafka, Postgres CDC, a SQL cursor, a MongoDB change stream or a file — so key order equals source order at any `concurrency` without configuring anything (see [Files & object storage — `name_by`](docs/DELIVERY.md#files--object-storage--name_by)).
283
283
  * **As a source**, objects under the prefix are listed in key order, fetched whole, split on the delimiter, and emitted. Progress is a durable cursor holding the last fully-acked object key: set `cursor_id` and an external `checkpoint_store` (`file://`, `s3://`, `postgres://`, `mongodb://`) so a restart resumes without re-emitting. Objects are **never deleted or rewritten** — resume is non-destructive and at-least-once at object granularity (a nacked batch is redelivered; the cursor only advances once an object is fully acked). `csv` is supported on the source only.
284
284
 
285
285
  ```yaml