mq-bridge-py-basic 0.2.19__tar.gz → 0.2.20__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 (198) hide show
  1. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/.github/workflows/release.yml +15 -4
  2. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/Cargo.lock +30 -32
  3. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/Cargo.toml +4 -3
  4. mq_bridge_py_basic-0.2.20/PKG-INFO +191 -0
  5. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/README.md +6 -0
  6. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/benches/performance_bench.rs +1 -1
  7. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/mq-bridge.schema.json +102 -7
  8. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/mq_bridge/__init__.py +4 -0
  9. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/mq_bridge/__init__.pyi +40 -2
  10. mq_bridge_py_basic-0.2.20/mq_bridge/config.py +98 -0
  11. mq_bridge_py_basic-0.2.20/mq_bridge/config.pyi +394 -0
  12. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/pyproject.toml +5 -3
  13. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/python/mq-bridge-py/Cargo.toml +2 -1
  14. mq_bridge_py_basic-0.2.20/python/mq-bridge-py/README.md +167 -0
  15. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/python/mq-bridge-py/example.py +14 -13
  16. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/python/mq-bridge-py/examples/raw_route.py +0 -1
  17. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/python/mq-bridge-py/pyproject-basic.toml +5 -3
  18. mq_bridge_py_basic-0.2.20/python/mq-bridge-py/scripts/gen_config_types.py +248 -0
  19. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/python/mq-bridge-py/src/lib.rs +216 -41
  20. mq_bridge_py_basic-0.2.20/python/mq-bridge-py/tests/test_config_types.py +45 -0
  21. mq_bridge_py_basic-0.2.20/python/mq-bridge-py/tests/test_packaging.py +49 -0
  22. mq_bridge_py_basic-0.2.20/python/mq-bridge-py/tests/test_routes.py +143 -0
  23. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/python/mq-bridge-py/uv.lock +100 -1369
  24. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/httparena/frameworks/mq-bridge-py/Dockerfile +1 -1
  25. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/httparena/frameworks/mq-bridge-py/meta.json +7 -2
  26. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/httparena/frameworks/mq-bridge-py/server.py +191 -32
  27. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/grpc.rs +103 -32
  28. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/http.rs +3 -1
  29. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/mod.rs +113 -0
  30. mq_bridge_py_basic-0.2.20/src/endpoints/websocket.rs +783 -0
  31. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/middleware/buffer.rs +296 -2
  32. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/middleware/mod.rs +2 -5
  33. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/models.rs +77 -3
  34. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/test_utils.rs +45 -11
  35. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/websocket.rs +1 -1
  36. mq_bridge_py_basic-0.2.20/tests/websocket_test.rs +356 -0
  37. mq_bridge_py_basic-0.2.19/PKG-INFO +0 -110
  38. mq_bridge_py_basic-0.2.19/python/mq-bridge-py/README.md +0 -86
  39. mq_bridge_py_basic-0.2.19/src/endpoints/websocket.rs +0 -459
  40. mq_bridge_py_basic-0.2.19/tests/websocket_test.rs +0 -118
  41. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  42. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  43. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  44. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/.github/workflows/benchmark.yml +0 -0
  45. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/.github/workflows/ci.yml +0 -0
  46. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/.github/workflows/ibm-mq.yml +0 -0
  47. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/.github/workflows/publish-python.yml +0 -0
  48. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/.github/workflows/python.yml +0 -0
  49. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/.github/workflows/test-matrix.yml +0 -0
  50. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/.gitignore +0 -0
  51. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/ARCHITECTURE.md +0 -0
  52. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/CONFIGURATION.md +0 -0
  53. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/CONTRIBUTING.md +0 -0
  54. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/LICENSE +0 -0
  55. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/LICENSE.python +0 -0
  56. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/benches/router_bench.rs +0 -0
  57. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/build.rs +0 -0
  58. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/claude.md +0 -0
  59. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/examples/ipc_worker_queue.yaml +0 -0
  60. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/mq_bridge/py.typed +0 -0
  61. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/python/mq-bridge-py/LICENSE.python +0 -0
  62. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/python/mq-bridge-py/analysis/bench_http_native.py +0 -0
  63. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/python/mq-bridge-py/examples/bench_memory.py +0 -0
  64. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/python/mq-bridge-py/examples/bench_memory.yaml +0 -0
  65. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/python/mq-bridge-py/examples/json_route.py +0 -0
  66. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/python/mq-bridge-py/examples/memory.yaml +0 -0
  67. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/python/mq-bridge-py/tests/test_performance_smoke.py +0 -0
  68. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/python/mq-bridge-py/tests/test_public_api.py +0 -0
  69. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/analysis/HTTP_STREAM_ENDPOINT_PLAN.md +0 -0
  70. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/analysis/benches/metadata_bench.rs +0 -0
  71. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/analysis/debug_ibm_mq_tls.rs +0 -0
  72. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/analysis/http/analyze_xctrace_time_profile.py +0 -0
  73. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/analysis/http/http_flamegraph.py +0 -0
  74. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/analysis/http/mq_bridge_http_profile.rs +0 -0
  75. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/analysis/http/run_http_ladder.sh +0 -0
  76. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/httparena/README.md +0 -0
  77. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/techempower/Python/mq-bridge-py/README.md +0 -0
  78. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/techempower/Python/mq-bridge-py/benchmark_config.json +0 -0
  79. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/techempower/Python/mq-bridge-py/mq-bridge-py.dockerfile +0 -0
  80. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/techempower/Python/mq-bridge-py/server.py +0 -0
  81. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/techempower/README.md +0 -0
  82. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/techempower/postgres.yml +0 -0
  83. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/techempower/seed.sql +0 -0
  84. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/techempower/verify.sh +0 -0
  85. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/the-benchmarker/README.md +0 -0
  86. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/the-benchmarker/python/mq-bridge-py/config.yaml +0 -0
  87. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/the-benchmarker/python/mq-bridge-py/pyproject.toml +0 -0
  88. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/scripts/the-benchmarker/python/mq-bridge-py/server.py +0 -0
  89. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/canonical_message.rs +0 -0
  90. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/command_handler.rs +0 -0
  91. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/amqp.rs +0 -0
  92. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/aws.rs +0 -0
  93. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/fanout.rs +0 -0
  94. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/file.rs +0 -0
  95. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/grpc.proto +0 -0
  96. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/http_stream.rs +0 -0
  97. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/ibm_mq.rs +0 -0
  98. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/kafka.rs +0 -0
  99. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/memory/endpoint.rs +0 -0
  100. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/memory/ipc_unix.rs +0 -0
  101. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/memory/ipc_windows.rs +0 -0
  102. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/memory/memory_transport.rs +0 -0
  103. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/memory/mod.rs +0 -0
  104. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/memory/transport.rs +0 -0
  105. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/mongodb.rs +0 -0
  106. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/mqtt.rs +0 -0
  107. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/nats.rs +0 -0
  108. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/null.rs +0 -0
  109. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/reader.rs +0 -0
  110. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/response.rs +0 -0
  111. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/sled.rs +0 -0
  112. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/sqlx.rs +0 -0
  113. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/static_endpoint.rs +0 -0
  114. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/stream_buffer.rs +0 -0
  115. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/switch.rs +0 -0
  116. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/endpoints/zeromq.rs +0 -0
  117. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/errors.rs +0 -0
  118. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/event_handler.rs +0 -0
  119. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/event_store.rs +0 -0
  120. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/extensions.rs +0 -0
  121. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/lib.rs +0 -0
  122. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/middleware/cookie_jar.rs +0 -0
  123. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/middleware/deduplication.rs +0 -0
  124. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/middleware/delay.rs +0 -0
  125. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/middleware/dlq.rs +0 -0
  126. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/middleware/limiter.rs +0 -0
  127. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/middleware/metrics.rs +0 -0
  128. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/middleware/random_panic.rs +0 -0
  129. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/middleware/retry.rs +0 -0
  130. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/middleware/weak_join.rs +0 -0
  131. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/outcomes.rs +0 -0
  132. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/publisher.rs +0 -0
  133. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/response.rs +0 -0
  134. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/route.rs +0 -0
  135. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/traits.rs +0 -0
  136. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/src/type_handler.rs +0 -0
  137. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/README.md +0 -0
  138. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/armature_integration.rs +0 -0
  139. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/amqp.rs +0 -0
  140. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/aws.rs +0 -0
  141. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/config.toml +0 -0
  142. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/amqp.yml +0 -0
  143. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/aws.yml +0 -0
  144. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/ibm-mq-certs/client.crl +0 -0
  145. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/ibm-mq-certs/client.kdb +0 -0
  146. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/ibm-mq-certs/client.p12 +0 -0
  147. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/ibm-mq-certs/client.rdb +0 -0
  148. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/ibm-mq-certs/client.sth +0 -0
  149. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/ibm_mq.yml +0 -0
  150. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/ibm_mq_tls.yml +0 -0
  151. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/kafka-tls.yml +0 -0
  152. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/kafka.yml +0 -0
  153. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/mariadb.yml +0 -0
  154. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/mongodb-replica.yml +0 -0
  155. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/mongodb-tls.yml +0 -0
  156. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/mongodb.yml +0 -0
  157. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/mosquitto.conf +0 -0
  158. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/mosquitto_performance.conf +0 -0
  159. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/mosquitto_persistence.conf +0 -0
  160. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/mq_init.mqsc +0 -0
  161. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/mq_init_tls.mqsc +0 -0
  162. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/mqtt.yml +0 -0
  163. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/mqtt_performance.yml +0 -0
  164. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/mysql.yml +0 -0
  165. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/nats.yml +0 -0
  166. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/docker-compose/postgres.yml +0 -0
  167. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/file.rs +0 -0
  168. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/grpc.rs +0 -0
  169. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/grpc_tls.rs +0 -0
  170. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/http.rs +0 -0
  171. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/http_tls.rs +0 -0
  172. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/ibm_mq.rs +0 -0
  173. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/ibm_mq_tls.rs +0 -0
  174. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/ipc.rs +0 -0
  175. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/kafka.rs +0 -0
  176. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/kafka_tls.rs +0 -0
  177. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/logic_test.rs +0 -0
  178. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/mariadb.rs +0 -0
  179. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/memory.rs +0 -0
  180. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/mod.rs +0 -0
  181. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/mongodb.rs +0 -0
  182. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/mongodb_raw.rs +0 -0
  183. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/mongodb_tls.rs +0 -0
  184. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/mqtt.rs +0 -0
  185. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/mysql.rs +0 -0
  186. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/nats.rs +0 -0
  187. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/performance_static.rs +0 -0
  188. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/postgres.rs +0 -0
  189. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/route.rs +0 -0
  190. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/scripts/gen_certs.sh +0 -0
  191. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/sqlite.rs +0 -0
  192. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/tls_helpers.rs +0 -0
  193. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration/zeromq.rs +0 -0
  194. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/integration_test.rs +0 -0
  195. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/ref_test.rs +0 -0
  196. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/sqlite_test.rs +0 -0
  197. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/tls_example.rs +0 -0
  198. {mq_bridge_py_basic-0.2.19 → mq_bridge_py_basic-0.2.20}/tests/unit_tests.md +0 -0
@@ -50,13 +50,24 @@ jobs:
50
50
  runs-on: ubuntu-latest
51
51
  needs: release
52
52
  environment: release
53
+ permissions:
54
+ # Required for crates.io Trusted Publishing (OIDC).
55
+ contents: read
56
+ id-token: write
53
57
  steps:
54
- - uses: actions/checkout@v4
55
-
58
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
59
+ with:
60
+ persist-credentials: false
61
+
56
62
  - name: Install Rust toolchain
57
63
  uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
58
-
64
+
65
+ # Exchange the GitHub OIDC token for a short-lived crates.io token.
66
+ - name: Authenticate to crates.io (Trusted Publishing)
67
+ uses: rust-lang/crates-io-auth-action@c6f97d42243bad5fab37ca0427f495c86d5b1a18 # v1.0.5
68
+ id: auth
69
+
59
70
  - name: Publish to crates.io
60
71
  run: cargo publish
61
72
  env:
62
- CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}
73
+ CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
@@ -299,7 +299,7 @@ dependencies = [
299
299
  "tokio-rustls 0.26.4",
300
300
  "tokio-stream",
301
301
  "tokio-util",
302
- "tokio-websockets",
302
+ "tokio-websockets 0.10.1",
303
303
  "tracing",
304
304
  "tryhard",
305
305
  "url",
@@ -3057,7 +3057,7 @@ dependencies = [
3057
3057
 
3058
3058
  [[package]]
3059
3059
  name = "mq-bridge"
3060
- version = "0.2.19"
3060
+ version = "0.2.20"
3061
3061
  dependencies = [
3062
3062
  "anyhow",
3063
3063
  "arc-swap",
@@ -3109,7 +3109,7 @@ dependencies = [
3109
3109
  "tokio",
3110
3110
  "tokio-rustls 0.26.4",
3111
3111
  "tokio-stream",
3112
- "tokio-tungstenite",
3112
+ "tokio-websockets 0.13.2",
3113
3113
  "tonic",
3114
3114
  "tonic-prost",
3115
3115
  "tonic-prost-build",
@@ -3124,7 +3124,7 @@ dependencies = [
3124
3124
 
3125
3125
  [[package]]
3126
3126
  name = "mq-bridge-py"
3127
- version = "0.2.19"
3127
+ version = "0.2.20"
3128
3128
  dependencies = [
3129
3129
  "anyhow",
3130
3130
  "async-trait",
@@ -3132,6 +3132,7 @@ dependencies = [
3132
3132
  "fast-uuid-v7",
3133
3133
  "mq-bridge",
3134
3134
  "pyo3",
3135
+ "schemars",
3135
3136
  "serde",
3136
3137
  "serde_json",
3137
3138
  "serde_yaml_ng",
@@ -4884,6 +4885,12 @@ dependencies = [
4884
4885
  "digest 0.11.3",
4885
4886
  ]
4886
4887
 
4888
+ [[package]]
4889
+ name = "sha1_smol"
4890
+ version = "1.0.1"
4891
+ source = "registry+https://github.com/rust-lang/crates.io-index"
4892
+ checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d"
4893
+
4887
4894
  [[package]]
4888
4895
  name = "sha2"
4889
4896
  version = "0.10.9"
@@ -5550,18 +5557,6 @@ dependencies = [
5550
5557
  "tokio",
5551
5558
  ]
5552
5559
 
5553
- [[package]]
5554
- name = "tokio-tungstenite"
5555
- version = "0.29.0"
5556
- source = "registry+https://github.com/rust-lang/crates.io-index"
5557
- checksum = "8f72a05e828585856dacd553fba484c242c46e391fb0e58917c942ee9202915c"
5558
- dependencies = [
5559
- "futures-util",
5560
- "log",
5561
- "tokio",
5562
- "tungstenite",
5563
- ]
5564
-
5565
5560
  [[package]]
5566
5561
  name = "tokio-util"
5567
5562
  version = "0.7.18"
@@ -5598,6 +5593,25 @@ dependencies = [
5598
5593
  "webpki-roots 0.26.11",
5599
5594
  ]
5600
5595
 
5596
+ [[package]]
5597
+ name = "tokio-websockets"
5598
+ version = "0.13.2"
5599
+ source = "registry+https://github.com/rust-lang/crates.io-index"
5600
+ checksum = "dad543404f98bfc969aeb71994105c592acfc6c43323fddcd016bb208d1c65cb"
5601
+ dependencies = [
5602
+ "base64",
5603
+ "bytes",
5604
+ "fastrand",
5605
+ "futures-core",
5606
+ "futures-sink",
5607
+ "http 1.4.2",
5608
+ "httparse",
5609
+ "sha1_smol",
5610
+ "simdutf8",
5611
+ "tokio",
5612
+ "tokio-util",
5613
+ ]
5614
+
5601
5615
  [[package]]
5602
5616
  name = "toml"
5603
5617
  version = "1.1.2+spec-1.1.0"
@@ -5863,22 +5877,6 @@ dependencies = [
5863
5877
  "tokio",
5864
5878
  ]
5865
5879
 
5866
- [[package]]
5867
- name = "tungstenite"
5868
- version = "0.29.0"
5869
- source = "registry+https://github.com/rust-lang/crates.io-index"
5870
- checksum = "6c01152af293afb9c7c2a57e4b559c5620b421f6d133261c60dd2d0cdb38e6b8"
5871
- dependencies = [
5872
- "bytes",
5873
- "data-encoding",
5874
- "http 1.4.2",
5875
- "httparse",
5876
- "log",
5877
- "rand 0.9.4",
5878
- "sha1 0.10.6",
5879
- "thiserror 2.0.18",
5880
- ]
5881
-
5882
5880
  [[package]]
5883
5881
  name = "typed-builder"
5884
5882
  version = "0.22.0"
@@ -16,7 +16,7 @@ members = ["python/mq-bridge-py"]
16
16
  resolver = "2"
17
17
 
18
18
  [workspace.package]
19
- version = "0.2.19"
19
+ version = "0.2.20"
20
20
 
21
21
  [workspace.dependencies]
22
22
  anyhow = "1.0"
@@ -46,6 +46,7 @@ tokio = { workspace = true, features = ["rt-multi-thread", "macros", "sync", "ti
46
46
  # Note on MSRV for optional features:
47
47
  # The base crate keeps MSRV 1.75 with default = [].
48
48
  # - "amqp" (lapin 4.10) requires Rust 1.88+; "http" (hyper-rustls 0.27) requires Rust 1.85+.
49
+ # - "websocket" (tokio-websockets 0.13) requires Rust 1.89+.
49
50
  # - "aws" (aws-sdk-*) may require a newer stable toolchain than the base MSRV.
50
51
  # Use `rustup override set stable` or a `rust-toolchain.toml` file when enabling these features.
51
52
  async-trait.workspace = true
@@ -118,7 +119,7 @@ http-body = { version = "1.0", optional = true }
118
119
  h2 = { version = "0.4", optional = true }
119
120
  flate2 = { version = "1.0", optional = true }
120
121
  base64 = { version = "0.22", optional = true }
121
- tokio-tungstenite = { version = "0.29", optional = true }
122
+ tokio-websockets = { version = "0.13", optional = true, default-features = false, features = ["client", "server", "sha1_smol", "fastrand"] }
122
123
 
123
124
  # AWS
124
125
  aws-config = { version = "1.8", optional = true, default-features = false, features = ["behavior-version-latest", "rt-tokio", "rustls"] }
@@ -180,7 +181,7 @@ nats = ["async-nats", "rustls", "rustls-pemfile"]
180
181
  mongodb = ["dep:mongodb"]
181
182
  mqtt = ["rumqttc", "rustls", "tokio-rustls", "rustls-pemfile", "url"]
182
183
  http = ["dep:arc-swap", "hyper", "hyper-util", "hyper-rustls", "http-body-util", "dep:http-body", "rustls", "tokio-rustls", "rustls-pemfile", "webpki-roots", "h2", "dep:flate2", "dep:base64"]
183
- websocket = ["dep:tokio-tungstenite"]
184
+ websocket = ["dep:tokio-websockets"]
184
185
  aws = ["aws-config", "aws-sdk-sqs", "aws-sdk-sns", "dep:base64"]
185
186
  ibm-mq = ["mqi"]
186
187
  zeromq = ["dep:zeromq"]
@@ -0,0 +1,191 @@
1
+ Metadata-Version: 2.4
2
+ Name: mq-bridge-py-basic
3
+ Version: 0.2.20
4
+ Classifier: Development Status :: 3 - Alpha
5
+ Classifier: License :: OSI Approved :: MIT License
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: Programming Language :: Python :: 3.9
8
+ Classifier: Programming Language :: Python :: 3.10
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Rust
13
+ Requires-Dist: typing-extensions>=4.0
14
+ License-File: LICENSE.python
15
+ Summary: Python bindings for mq-bridge (basic: all-platform messaging set)
16
+ Keywords: messaging,tokio,pyo3,maturin,mq-bridge
17
+ License: MIT
18
+ Requires-Python: >=3.9
19
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
20
+ Project-URL: Homepage, https://github.com/marcomq/mq-bridge
21
+ Project-URL: Issues, https://github.com/marcomq/mq-bridge/issues
22
+ Project-URL: Repository, https://github.com/marcomq/mq-bridge
23
+
24
+ # mq-bridge Python bindings
25
+
26
+ Thin Python bindings for the Rust `mq-bridge` core.
27
+
28
+ ## Install
29
+
30
+ Pick exactly one distribution. Both install the same import path: `mq_bridge`.
31
+
32
+ | Package | Install | Includes |
33
+ | :--- | :--- | :--- |
34
+ | Full | `pip install mq-bridge-py` | Basic set plus Kafka, AWS, gRPC, MongoDB, SQLx |
35
+ | Basic | `pip install mq-bridge-py-basic` | HTTP, NATS, MQTT, AMQP, WebSocket, ZeroMQ, middleware |
36
+
37
+ Memory and file endpoints are always present in both packages. Use `mq-bridge-py-basic` when you want the lean all-platform wheel set. Use `mq-bridge-py` when you need Kafka or the heavier non-messaging backends.
38
+
39
+ The public API stays close to mq-bridge itself:
40
+
41
+ - `Route.from_yaml(path, name)` loads one named route from a YAML file
42
+ - `Route.from_yaml_str(text, name)` / `Route.from_config(mapping, name)` build a route from an in-memory YAML string or a Python `dict`, no file required
43
+ - `Route.with_handler(...)` attaches a raw `Message` handler, with lazy `json()`/`text()` readers and `with_json()`/`with_payload()` response helpers
44
+ - `Route.add_handler(kind, ...)` uses mq-bridge's `kind` dispatch and delivers decoded JSON
45
+ - `RetryableError` and `NonRetryableError` let Python handlers signal retry intent
46
+ - `Publisher.from_yaml(path, name)` (plus `from_yaml_str` / `from_config`) loads one named publisher
47
+ - `Publisher.send_json(...)` and `Publisher.request_json(...)` serialize Python JSON values in Rust
48
+
49
+ The Python surface is synchronous and blocking. Tokio, broker I/O, routing, and batching all stay in Rust.
50
+
51
+ ## Config types and schema
52
+
53
+ `mq-bridge-app` can create and test route and endpoint JSON/YAML through its UI.
54
+ It does not replace your Python code or handlers, but it is useful when you want
55
+ a known-good connection and route shape before pasting the configuration into
56
+ Python. Load the generated config with `Route.from_config`, `Route.from_yaml`,
57
+ `Publisher.from_config`, or `Publisher.from_yaml`.
58
+
59
+ For the `from_config` / `from_yaml_str` mappings, `mq_bridge.config` ships
60
+ `TypedDict` definitions so editors autocomplete the config keys (`input`,
61
+ `output`, `batch_size`, every transport config, middleware, …):
62
+
63
+ ```python
64
+ from mq_bridge import Route
65
+ from mq_bridge.config import ConfigDocument
66
+
67
+ config: ConfigDocument = {
68
+ "routes": {
69
+ "orders": {
70
+ "input": {"memory": {"topic": "orders.in", "capacity": 1600}},
71
+ "output": {"response": {}},
72
+ "batch_size": 128,
73
+ }
74
+ }
75
+ }
76
+ route = Route.from_config(config, "orders")
77
+ ```
78
+
79
+ These types are generated from the JSON Schema, which the extension produces on
80
+ demand from the Rust models — there is no checked-in schema copy to drift:
81
+
82
+ ```python
83
+ from mq_bridge import config_schema
84
+
85
+ schema = config_schema() # the JSON Schema as a dict
86
+ ```
87
+
88
+ `config_schema()` is handy for editor validation of YAML configs too — dump it
89
+ to a file and point your `# yaml-language-server: $schema=` line at it. The types
90
+ are regenerated with `uv run python scripts/gen_config_types.py` (a test fails if
91
+ they drift from the schema).
92
+
93
+ ## Running a route
94
+
95
+ `Route.run()` **blocks the calling thread** until another thread calls `stop()` —
96
+ it deploys the route and then parks. This is convenient for a process whose only
97
+ job is the route, but it is a common trap: nothing after `route.run()` executes
98
+ until the route stops.
99
+
100
+ To keep running Python code after the route is up, use `start()` (non-blocking)
101
+ or the context-manager form:
102
+
103
+ ```python
104
+ route = Route.from_config(config, "orders_route").with_handler(handle)
105
+
106
+ # Non-blocking: deploys, returns, and runs on a background thread.
107
+ route.start()
108
+ publisher.send_json({"order_id": 42}, {"kind": "order.created"})
109
+ route.stop()
110
+ route.join() # optional: wait for a clean shutdown
111
+
112
+ # Or scope it to a block — starts on enter, stops + joins on exit:
113
+ with Route.from_config(config, "orders_route").with_handler(handle):
114
+ publisher.send_json({"order_id": 42}, {"kind": "order.created"})
115
+ ```
116
+
117
+ Configuration/connection errors surface from `start()` itself, not from a
118
+ background thread. `run()` remains available for the blocking single-route case.
119
+
120
+ ## Tuning (environment variables)
121
+
122
+ These knobs are read from the environment at startup:
123
+
124
+ | Variable | Default | Effect |
125
+ | :--- | :--- | :--- |
126
+ | `MQ_BRIDGE_PY_HANDLER_EXECUTOR` | `worker` | `worker` runs handlers on a dedicated interpreter thread that coalesces queued batches under one GIL acquisition (best under load); `direct` calls the handler inline. |
127
+ | `MQ_BRIDGE_PY_HANDLER_CONCURRENCY` | CPU count | Max in-flight handler batches. `0` disables the limit. |
128
+ | `MQ_BRIDGE_PY_GC_MODE` | `default` | `default` leaves CPython's cyclic GC alone; `count` disables it and runs `gc.collect()` every N messages; `off` disables it entirely (pure refcounting). |
129
+ | `MQ_BRIDGE_PY_GC_THRESHOLD` | `100000` | Messages between collections when `MQ_BRIDGE_PY_GC_MODE=count`. |
130
+
131
+ ## Local development
132
+
133
+ `uv` is a good fit here for the Python-side developer workflow, while `maturin` stays the build backend:
134
+
135
+ ```bash
136
+ cd python/mq-bridge-py
137
+ uv sync --group dev --no-install-project
138
+ uv run maturin develop
139
+ uv run pytest -q
140
+ ```
141
+
142
+ Performance smoke tests are skipped by default because they start routes and measure
143
+ local throughput:
144
+
145
+ ```bash
146
+ cd python/mq-bridge-py
147
+ MQ_BRIDGE_RUN_PERF_TESTS=1 uv run pytest -q -m performance
148
+ ```
149
+
150
+ ## Examples
151
+
152
+ Raw message handler:
153
+
154
+ ```bash
155
+ cd python/mq-bridge-py
156
+ uv run python examples/raw_route.py
157
+ ```
158
+
159
+ Kind-based JSON handler:
160
+
161
+ ```bash
162
+ cd python/mq-bridge-py
163
+ uv run python examples/json_route.py
164
+ ```
165
+
166
+ Memory benchmark:
167
+
168
+ ```bash
169
+ cd python/mq-bridge-py
170
+ uv run maturin develop --release
171
+ uv run python examples/bench_memory.py --messages 100000
172
+ ```
173
+
174
+ ## Analysis
175
+
176
+ HTTP comparison benchmark, driven by a native load generator (`wrk`) so the
177
+ client is never the bottleneck. It boots each server itself (mq-bridge in worker
178
+ and direct executor modes, plus FastAPI, Starlette, Sanic, aiohttp, and
179
+ FastStream when installed) and drives each with `wrk`:
180
+
181
+ ```bash
182
+ cd python/mq-bridge-py
183
+ uv run maturin develop --release
184
+ uv sync --group bench # optional Python HTTP peers
185
+ uv run python analysis/bench_http_native.py --connections 1,8,32 --duration 8
186
+ ```
187
+
188
+ Requires `wrk` on `PATH` (`brew install wrk`). The FastStream target compares its
189
+ ASGI custom-route path over Uvicorn; it is not a broker-backed subscriber/publisher
190
+ benchmark. The examples use included sample configs or create temporary configs.
191
+
@@ -157,6 +157,12 @@ The `response` output endpoint sends a reply back to the original requester. Thi
157
157
  There is a separate repository for running mq-bridge as a standalone app, for example as a Docker container configured via YAML or environment variables:
158
158
  https://github.com/marcomq/mq-bridge-app
159
159
 
160
+ ### Configuration-first workflow
161
+
162
+ `mq-bridge-app` can be used to create and test route and endpoint configurations through a UI. The generated JSON/YAML can then be copied into an application and loaded by the Rust library or the Python bindings.
163
+
164
+ This does not replace application code or handlers, but it is useful when you want a known-good connection and route shape before pasting the configuration into code. For Python projects, routes and publishers are commonly loaded from JSON/YAML with `Route.from_config`, `Route.from_yaml`, `Publisher.from_config`, or `Publisher.from_yaml`.
165
+
160
166
  ### Programmatic Handlers
161
167
 
162
168
  For business logic, `mq-bridge` provides a handler layer separate from transport-level middleware. This is where message-specific code usually belongs.
@@ -648,7 +648,7 @@ pub mod websocket_helper {
648
648
  let websocket_config = WebSocketConfig {
649
649
  url: "127.0.0.1:0".to_string(),
650
650
  path: Some("/bench".to_string()),
651
- internal_buffer_size: Some(super::PERF_TEST_MESSAGE_COUNT * 2),
651
+ routed_queue_capacity: Some(super::PERF_TEST_MESSAGE_COUNT * 2),
652
652
  ..Default::default()
653
653
  };
654
654
 
@@ -362,7 +362,7 @@
362
362
  "type": "object",
363
363
  "properties": {
364
364
  "static": {
365
- "type": "string"
365
+ "$ref": "#/$defs/StaticConfig"
366
366
  }
367
367
  },
368
368
  "required": [
@@ -972,6 +972,11 @@
972
972
  "format": "uint64",
973
973
  "minimum": 0
974
974
  },
975
+ "server_protocol": {
976
+ "description": "(Consumer only) Restrict which HTTP protocol versions a server listener accepts.\nDefaults to `auto` (HTTP/1.1 + HTTP/2). On cleartext listeners, `http2_only`\nmeans HTTP/2 prior-knowledge (h2c) only.",
977
+ "$ref": "#/$defs/HttpServerProtocol",
978
+ "default": "auto"
979
+ },
975
980
  "stream_response_to": {
976
981
  "description": "(Publisher only) Optional endpoint that receives streamed HTTP response items as correlated messages.\n\nUse a `stream_buffer` endpoint here when callers need to read streamed\nresponse items later through a normal mq-bridge consumer. Each streamed\nitem is published with `correlation_id`, `http_stream_id`,\n`http_stream_index`, `http_stream_format`, and `http_stream_end`\nmetadata. If the request message has no `correlation_id`, the HTTP\npublisher uses `format!(\"{:032x}\", request.message_id)` so callers can\nderive the consumer correlation id before calling `send`.",
977
982
  "anyOf": [
@@ -1023,6 +1028,26 @@
1023
1028
  "url"
1024
1029
  ]
1025
1030
  },
1031
+ "HttpServerProtocol": {
1032
+ "description": "Supported inbound HTTP protocols for server listeners.",
1033
+ "oneOf": [
1034
+ {
1035
+ "description": "Accept both HTTP/1.1 and HTTP/2, matching the current default behavior.",
1036
+ "type": "string",
1037
+ "const": "auto"
1038
+ },
1039
+ {
1040
+ "description": "Accept only HTTP/1.x connections.",
1041
+ "type": "string",
1042
+ "const": "http1_only"
1043
+ },
1044
+ {
1045
+ "description": "Accept only HTTP/2 connections.",
1046
+ "type": "string",
1047
+ "const": "http2_only"
1048
+ }
1049
+ ]
1050
+ },
1026
1051
  "IbmMqConfig": {
1027
1052
  "description": "Connection settings for the IBM MQ Queue Manager.",
1028
1053
  "type": "object",
@@ -1280,11 +1305,13 @@
1280
1305
  },
1281
1306
  "topic": {
1282
1307
  "description": "The topic name or transport URL. Can be:\n- Simple name: \"my-topic\" (defaults to memory://my-topic)\n- Memory URL: \"memory://my-topic\"\n- IPC URL: \"ipc://my-queue\" or \"ipc:///path/to/socket\"\n- Unix socket: \"unix:///path/to/socket\" (Unix only)\n- Named pipe: \"pipe://my-pipe\" (Windows only)\n\nEither `topic` or `url` can be specified (they are serde aliases).",
1283
- "type": "string"
1308
+ "type": "string",
1309
+ "minLength": 1
1284
1310
  },
1285
1311
  "url": {
1286
1312
  "description": "Alias for `topic`. Use either `topic` or `url`.",
1287
- "type": "string"
1313
+ "type": "string",
1314
+ "minLength": 1
1288
1315
  }
1289
1316
  },
1290
1317
  "additionalProperties": false,
@@ -1614,7 +1641,7 @@
1614
1641
  ]
1615
1642
  },
1616
1643
  "delayed_ack": {
1617
- "description": "(Consumer only) If true, messages are acknowledged immediately upon receipt (auto-ack).\nIf false (default), messages are acknowledged after processing (manual-ack).\nNote: This setting does not currently enable synchronous publishing (waiting for PubAck) for the MQTT publisher.",
1644
+ "description": "(Consumer only) If true, messages are acknowledged immediately upon receipt (auto-ack).\nIf false (default), messages are acknowledged after processing (manual-ack).\nNote: For QoS 1/2 the publisher always waits for end-to-end broker\nconfirmation (PUBACK/PUBCOMP) before reporting success, independent of\nthis setting; QoS 0 remains fire-and-forget.",
1618
1645
  "type": "boolean",
1619
1646
  "default": false
1620
1647
  },
@@ -2157,6 +2184,40 @@
2157
2184
  "table"
2158
2185
  ]
2159
2186
  },
2187
+ "StaticConfig": {
2188
+ "description": "Configuration for the `static` endpoint. Accepts either a bare string (the response body, JSON-encoded for backward compatibility) or a map where only `body` is required and `raw` / `metadata` are optional.",
2189
+ "oneOf": [
2190
+ {
2191
+ "description": "The response body, JSON-encoded as a string.",
2192
+ "type": "string"
2193
+ },
2194
+ {
2195
+ "type": "object",
2196
+ "properties": {
2197
+ "body": {
2198
+ "description": "The static response body.",
2199
+ "type": "string"
2200
+ },
2201
+ "metadata": {
2202
+ "description": "Extra metadata entries attached to the produced message.",
2203
+ "type": "object",
2204
+ "additionalProperties": {
2205
+ "type": "string"
2206
+ }
2207
+ },
2208
+ "raw": {
2209
+ "description": "Send the body verbatim instead of JSON-encoding it as a string.",
2210
+ "type": "boolean",
2211
+ "default": false
2212
+ }
2213
+ },
2214
+ "additionalProperties": false,
2215
+ "required": [
2216
+ "body"
2217
+ ]
2218
+ }
2219
+ ]
2220
+ },
2160
2221
  "StreamBufferConfig": {
2161
2222
  "description": "Configuration for the correlated in-process stream response buffer.",
2162
2223
  "type": "object",
@@ -2297,15 +2358,20 @@
2297
2358
  "description": "WebSocket connection configuration.",
2298
2359
  "type": "object",
2299
2360
  "properties": {
2300
- "internal_buffer_size": {
2301
- "description": "(Consumer only) Internal buffer size for the channel. Defaults to 100.",
2361
+ "backlog": {
2362
+ "description": "(Consumer only) TCP listen backlog (pending-connection queue depth) for the accept socket.\nRaise this if high-concurrency handshake bursts are being dropped/reset before `accept()`\ncan keep up. Defaults to 4096, which is higher than the OS/tokio default of 1024.",
2302
2363
  "type": [
2303
2364
  "integer",
2304
2365
  "null"
2305
2366
  ],
2306
- "format": "uint",
2367
+ "format": "uint32",
2307
2368
  "minimum": 0
2308
2369
  },
2370
+ "execution_mode": {
2371
+ "description": "(Consumer only) Selects whether WebSocket routes run directly or through the routed pipeline.",
2372
+ "$ref": "#/$defs/WebSocketExecutionMode",
2373
+ "default": "auto"
2374
+ },
2309
2375
  "message_id_header": {
2310
2376
  "description": "(Consumer only) Header key to extract the message ID from the WebSocket handshake. Defaults to \"message-id\".",
2311
2377
  "type": [
@@ -2320,6 +2386,15 @@
2320
2386
  "null"
2321
2387
  ]
2322
2388
  },
2389
+ "routed_queue_capacity": {
2390
+ "description": "(Consumer only) Queue capacity for the routed adapter. Direct response routes do not use this queue. Defaults to 100.",
2391
+ "type": [
2392
+ "integer",
2393
+ "null"
2394
+ ],
2395
+ "format": "uint",
2396
+ "minimum": 0
2397
+ },
2323
2398
  "url": {
2324
2399
  "description": "For consumers, the listen address (e.g. \"0.0.0.0:9000\"). For publishers, the target URL.",
2325
2400
  "type": "string",
@@ -2331,6 +2406,26 @@
2331
2406
  "url"
2332
2407
  ]
2333
2408
  },
2409
+ "WebSocketExecutionMode": {
2410
+ "description": "WebSocket route execution strategy.",
2411
+ "oneOf": [
2412
+ {
2413
+ "description": "Use direct per-connection handling for simple `websocket -> response` routes and fall back\nto the routed adapter with a warning when route semantics need the normal pipeline.",
2414
+ "type": "string",
2415
+ "const": "auto"
2416
+ },
2417
+ {
2418
+ "description": "Require direct per-connection handling. Startup fails if the route cannot run directly.",
2419
+ "type": "string",
2420
+ "const": "direct_only"
2421
+ },
2422
+ {
2423
+ "description": "Always use the normal routed consumer/worker/disposition pipeline.",
2424
+ "type": "string",
2425
+ "const": "routed"
2426
+ }
2427
+ ]
2428
+ },
2334
2429
  "ZeroMqConfig": {
2335
2430
  "type": "object",
2336
2431
  "properties": {
@@ -5,6 +5,8 @@ from ._mq_bridge import (
5
5
  Publisher,
6
6
  RetryableError,
7
7
  Route,
8
+ __version__,
9
+ config_schema,
8
10
  )
9
11
 
10
12
  __all__ = [
@@ -14,4 +16,6 @@ __all__ = [
14
16
  "Publisher",
15
17
  "RetryableError",
16
18
  "Route",
19
+ "__version__",
20
+ "config_schema",
17
21
  ]
@@ -1,4 +1,11 @@
1
- from typing import Any, Callable, Dict, List, Mapping, Optional, Union
1
+ from types import TracebackType
2
+ from typing import Any, Callable, Dict, List, Mapping, Optional, Type, Union
3
+
4
+ __version__: str
5
+
6
+ def config_schema() -> Dict[str, Any]:
7
+ """Return the route-config JSON Schema, generated from the Rust models."""
8
+ ...
2
9
 
3
10
  JsonValue = Any
4
11
  HandlerResult = Optional[Union["Message", bytes, str, Dict[str, JsonValue], List[JsonValue], int, float, bool]]
@@ -48,6 +55,12 @@ class Route:
48
55
  @classmethod
49
56
  def from_yaml(cls, path: str, name: str) -> "Route": ...
50
57
 
58
+ @classmethod
59
+ def from_yaml_str(cls, text: str, name: str) -> "Route": ...
60
+
61
+ @classmethod
62
+ def from_config(cls, config: Mapping[str, Any], name: str) -> "Route": ...
63
+
51
64
  def with_handler(self, handler: Callable[[Message], HandlerResult]) -> "Route": ...
52
65
 
53
66
  def add_handler(
@@ -56,10 +69,29 @@ class Route:
56
69
  handler: Callable[[JsonValue], HandlerResult],
57
70
  ) -> "Route": ...
58
71
 
59
- def run(self) -> None: ...
72
+ def run(self) -> None:
73
+ """Deploy and block the calling thread until ``stop()`` is called."""
74
+ ...
75
+
76
+ def start(self) -> None:
77
+ """Deploy on a background thread and return immediately."""
78
+ ...
79
+
80
+ def join(self) -> None:
81
+ """Block until a route started with ``start()`` has stopped."""
82
+ ...
60
83
 
61
84
  def stop(self) -> None: ...
62
85
 
86
+ def __enter__(self) -> "Route": ...
87
+
88
+ def __exit__(
89
+ self,
90
+ exc_type: Optional[Type[BaseException]],
91
+ exc_value: Optional[BaseException],
92
+ traceback: Optional[TracebackType],
93
+ ) -> bool: ...
94
+
63
95
 
64
96
  class MemoryDrainer:
65
97
  @classmethod
@@ -81,6 +113,12 @@ class Publisher:
81
113
  @classmethod
82
114
  def from_yaml(cls, path: str, name: str) -> "Publisher": ...
83
115
 
116
+ @classmethod
117
+ def from_yaml_str(cls, text: str, name: str) -> "Publisher": ...
118
+
119
+ @classmethod
120
+ def from_config(cls, config: Mapping[str, Any], name: str) -> "Publisher": ...
121
+
84
122
  def send(
85
123
  self,
86
124
  message: Union[Message, bytes],