mq-bridge-basic 0.4.18__tar.gz → 0.4.19__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 (382) hide show
  1. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/CHANGELOG.md +137 -0
  2. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/Cargo.lock +4 -4
  3. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/Cargo.toml +1 -1
  4. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/PKG-INFO +1 -1
  5. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/README.md +5 -8
  6. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/docs/REFERENCE.md +130 -12
  7. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/mq-bridge.schema.json +165 -11
  8. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/mq_bridge/config.py +10 -0
  9. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/mq_bridge/config.pyi +22 -0
  10. mq_bridge_basic-0.4.19/src/endpoints/file/csv_dialect.rs +322 -0
  11. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/file/mod.rs +547 -165
  12. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/file/tests.rs +452 -35
  13. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/grpc/publisher.rs +5 -1
  14. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/grpc/server.rs +8 -10
  15. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/http/tests.rs +45 -0
  16. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/memory/endpoint.rs +35 -46
  17. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/mod.rs +66 -1
  18. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/mqtt.rs +1 -1
  19. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/nats.rs +10 -13
  20. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/object_store.rs +222 -28
  21. mq_bridge_basic-0.4.19/src/endpoints/sqlx/columns.rs +597 -0
  22. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/sqlx/mod.rs +186 -53
  23. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/sqlx/tests.rs +286 -0
  24. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/aggregate/mod.rs +511 -130
  25. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/aggregate/tests.rs +298 -4
  26. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/filter.rs +55 -2
  27. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/models/builders.rs +1 -0
  28. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/models/serde_support.rs +1 -0
  29. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/models/tests.rs +22 -0
  30. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/models.rs +127 -11
  31. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/route.rs +165 -30
  32. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/postgres.rs +45 -0
  33. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration_test.rs +9 -0
  34. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.cargo/config.toml +0 -0
  35. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.coderabbit.yaml +0 -0
  36. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.dockerignore +0 -0
  37. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  38. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  39. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  40. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.github/dependabot.yml +0 -0
  41. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.github/workflows/app.yml +0 -0
  42. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.github/workflows/benchmark.yml +0 -0
  43. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.github/workflows/build-node.yml +0 -0
  44. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.github/workflows/ci.yml +0 -0
  45. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.github/workflows/conda.yml +0 -0
  46. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.github/workflows/docs.yml +0 -0
  47. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.github/workflows/ibm-mq.yml +0 -0
  48. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.github/workflows/node.yml +0 -0
  49. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.github/workflows/publish-node.yml +0 -0
  50. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.github/workflows/publish-python.yml +0 -0
  51. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.github/workflows/python.yml +0 -0
  52. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.github/workflows/release.yml +0 -0
  53. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.github/workflows/test-matrix.yml +0 -0
  54. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.gitignore +0 -0
  55. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/.justfile +0 -0
  56. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/AGENTS.md +0 -0
  57. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/CLAUDE.md +0 -0
  58. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/CONTRIBUTING.md +0 -0
  59. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/LICENSE +0 -0
  60. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/LICENSE-APACHE +0 -0
  61. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/LICENSE-APACHE.python +0 -0
  62. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/LICENSE-MIT +0 -0
  63. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/LICENSE-MIT.python +0 -0
  64. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/LICENSE.python +0 -0
  65. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/SECURITY.md +0 -0
  66. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/THIRD_PARTY_LICENSES.txt +0 -0
  67. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/benches/ETL_BENCHMARKS.md +0 -0
  68. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/benches/csv_to_json_bench.rs +0 -0
  69. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/benches/middleware_expr_bench.rs +0 -0
  70. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/benches/pack_bench.rs +0 -0
  71. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/benches/performance_bench.rs +0 -0
  72. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/benches/router_bench.rs +0 -0
  73. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/benches/zeromq_backends.rs +0 -0
  74. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/bindings-common/Cargo.toml +0 -0
  75. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/bindings-common/src/lib.rs +0 -0
  76. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/bindings-common/src/logging.rs +0 -0
  77. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/build.rs +0 -0
  78. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/deny.toml +0 -0
  79. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/docs/ARCHITECTURE.md +0 -0
  80. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/docs/CONFIGURATION.md +0 -0
  81. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/docs/DELIVERY.md +0 -0
  82. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/docs/EXTENDING.md +0 -0
  83. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/docs/GRPC.md +0 -0
  84. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/docs/PLUGINS.md +0 -0
  85. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/docs/THIRD_PARTY_LICENSES.md +0 -0
  86. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/docs/assets/copy-demo.png +0 -0
  87. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/examples/c-plugin/CMakeLists.txt +0 -0
  88. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/examples/c-plugin/README.md +0 -0
  89. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/examples/c-plugin/legacy_ledger.c +0 -0
  90. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/examples/c-plugin/legacy_ledger.h +0 -0
  91. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/examples/c-plugin/legacy_parser.c +0 -0
  92. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/examples/c-plugin/legacy_parser.h +0 -0
  93. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/examples/c-plugin/minimal.c +0 -0
  94. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/examples/c-plugin/plugin.c +0 -0
  95. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/examples/ipc_worker_queue.yaml +0 -0
  96. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/include/cbindgen.toml +0 -0
  97. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/include/mq_bridge_plugin.h +0 -0
  98. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/include/mq_bridge_plugin_helpers.h +0 -0
  99. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/llms.txt +0 -0
  100. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/mq_bridge/__init__.py +0 -0
  101. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/mq_bridge/__init__.pyi +0 -0
  102. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/mq_bridge/plugin_packaging.py +0 -0
  103. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/mq_bridge/py.typed +0 -0
  104. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/package-lock.json +0 -0
  105. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/pyproject.toml +0 -0
  106. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/Cargo.toml +0 -0
  107. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/LICENSE-APACHE.python +0 -0
  108. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/LICENSE-MIT.python +0 -0
  109. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/LICENSE.python +0 -0
  110. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/README.md +0 -0
  111. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/THIRD_PARTY_LICENSES.txt +0 -0
  112. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/analysis/bench_http_native.py +0 -0
  113. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/example.py +0 -0
  114. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/examples/IBM_MQ.md +0 -0
  115. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/examples/bench_memory.py +0 -0
  116. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/examples/bench_memory.yaml +0 -0
  117. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/examples/consume_pull.py +0 -0
  118. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/examples/dlt_source.py +0 -0
  119. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/examples/ibm-mq-input.py +0 -0
  120. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/examples/json_route.py +0 -0
  121. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/examples/memory.yaml +0 -0
  122. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/examples/raw_route.py +0 -0
  123. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/pyproject-basic.toml +0 -0
  124. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/pyproject-reduced.toml +0 -0
  125. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/scripts/gen_config_types.py +0 -0
  126. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/src/lib.rs +0 -0
  127. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/tests/test_config_types.py +0 -0
  128. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/tests/test_custom_endpoint.py +0 -0
  129. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/tests/test_logging.py +0 -0
  130. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/tests/test_packaging.py +0 -0
  131. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/tests/test_performance_smoke.py +0 -0
  132. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/tests/test_plugin_package.py +0 -0
  133. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/tests/test_public_api.py +0 -0
  134. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/tests/test_routes.py +0 -0
  135. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/tests/test_shutdown.py +0 -0
  136. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/python/mq-bridge-py/uv.lock +0 -0
  137. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/analysis/benches/metadata_bench.rs +0 -0
  138. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/analysis/debug_ibm_mq_tls.rs +0 -0
  139. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/analysis/http/analyze_xctrace_time_profile.py +0 -0
  140. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/analysis/http/http_flamegraph.py +0 -0
  141. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/analysis/http/mq_bridge_http_profile.rs +0 -0
  142. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/analysis/http/run_http_ladder.sh +0 -0
  143. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/ci/format_bench_output.sh +0 -0
  144. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/httparena/README.md +0 -0
  145. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/httparena/frameworks/mq-bridge-py/Dockerfile +0 -0
  146. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/httparena/frameworks/mq-bridge-py/meta.json +0 -0
  147. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/httparena/frameworks/mq-bridge-py/server.py +0 -0
  148. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/httparena/frameworks/mq-bridge-py/templates/fortunes.html +0 -0
  149. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/mqb-agent.py +0 -0
  150. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/sync-version.mjs +0 -0
  151. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/techempower/Python/mq-bridge-py/README.md +0 -0
  152. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/techempower/Python/mq-bridge-py/benchmark_config.json +0 -0
  153. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/techempower/Python/mq-bridge-py/mq-bridge-py.dockerfile +0 -0
  154. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/techempower/Python/mq-bridge-py/server.py +0 -0
  155. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/techempower/README.md +0 -0
  156. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/techempower/postgres.yml +0 -0
  157. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/techempower/seed.sql +0 -0
  158. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/techempower/verify.sh +0 -0
  159. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/the-benchmarker/README.md +0 -0
  160. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/the-benchmarker/python/mq-bridge-py/config.yaml +0 -0
  161. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/the-benchmarker/python/mq-bridge-py/pyproject.toml +0 -0
  162. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/scripts/the-benchmarker/python/mq-bridge-py/server.py +0 -0
  163. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/canonical_message.rs +0 -0
  164. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/checkpoint.rs +0 -0
  165. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/command_handler.rs +0 -0
  166. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/config_file.rs +0 -0
  167. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/amqp.rs +0 -0
  168. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/aws.rs +0 -0
  169. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/clickhouse.rs +0 -0
  170. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/dir_spool/mod.rs +0 -0
  171. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/dir_spool/tests.rs +0 -0
  172. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/grpc/consumer.rs +0 -0
  173. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/grpc/dynamic.rs +0 -0
  174. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/grpc/mod.rs +0 -0
  175. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/grpc/proto/mqbridge/bridge.proto +0 -0
  176. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/grpc/tests.rs +0 -0
  177. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/http/mod.rs +0 -0
  178. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/http/publisher.rs +0 -0
  179. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/http/stream.rs +0 -0
  180. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/http_bulk/auth.rs +0 -0
  181. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/http_bulk/consumer.rs +0 -0
  182. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/http_bulk/mod.rs +0 -0
  183. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/http_bulk/presets.rs +0 -0
  184. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/http_bulk/publisher.rs +0 -0
  185. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/http_bulk/query.rs +0 -0
  186. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/ibm_mq.rs +0 -0
  187. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/kafka.rs +0 -0
  188. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/memory/framed.rs +0 -0
  189. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/memory/ipc_unix.rs +0 -0
  190. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/memory/ipc_windows.rs +0 -0
  191. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/memory/memory_transport.rs +0 -0
  192. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/memory/mod.rs +0 -0
  193. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/memory/transport.rs +0 -0
  194. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/mongodb/aggregate.rs +0 -0
  195. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/mongodb/consumer.rs +0 -0
  196. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/mongodb/dedup.rs +0 -0
  197. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/mongodb/mod.rs +0 -0
  198. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/mongodb/publisher.rs +0 -0
  199. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/mongodb/readers.rs +0 -0
  200. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/mongodb/tests.rs +0 -0
  201. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/poll.rs +0 -0
  202. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/postgres/VENDORED.md +0 -0
  203. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/postgres/mod.rs +0 -0
  204. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/postgres/pgoutput/decoder.rs +0 -0
  205. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/postgres/pgoutput/messages.rs +0 -0
  206. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/postgres/pgoutput/mod.rs +0 -0
  207. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/postgres/pgoutput/registry.rs +0 -0
  208. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/postgres/pgoutput/values.rs +0 -0
  209. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/postgres/replication.rs +0 -0
  210. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/postgres/state.rs +0 -0
  211. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/redis_streams.rs +0 -0
  212. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/sled.rs +0 -0
  213. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/sqlx/aggregate.rs +0 -0
  214. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/sqlx/dedup.rs +0 -0
  215. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/structural/fanout.rs +0 -0
  216. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/structural/mod.rs +0 -0
  217. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/structural/null.rs +0 -0
  218. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/structural/reader.rs +0 -0
  219. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/structural/request.rs +0 -0
  220. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/structural/response.rs +0 -0
  221. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/structural/sequence.rs +0 -0
  222. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/structural/static_endpoint.rs +0 -0
  223. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/structural/stream_buffer.rs +0 -0
  224. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/structural/switch.rs +0 -0
  225. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/websocket.rs +0 -0
  226. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/zeromq/codec.rs +0 -0
  227. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/zeromq/mod.rs +0 -0
  228. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/zeromq/omq.rs +0 -0
  229. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/endpoints/zeromq/zmq.rs +0 -0
  230. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/errors.rs +0 -0
  231. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/event_handler.rs +0 -0
  232. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/event_store.rs +0 -0
  233. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/extensions.rs +0 -0
  234. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/lib.rs +0 -0
  235. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/aggregate/states.rs +0 -0
  236. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/aggregate/store.rs +0 -0
  237. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/aggregate/writer.rs +0 -0
  238. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/buffer.rs +0 -0
  239. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/compression.rs +0 -0
  240. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/cookie_jar.rs +0 -0
  241. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/deduplication/memory.rs +0 -0
  242. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/deduplication.rs +0 -0
  243. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/deferred_commit.rs +0 -0
  244. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/delay.rs +0 -0
  245. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/dlq.rs +0 -0
  246. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/encryption.rs +0 -0
  247. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/id.rs +0 -0
  248. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/limiter.rs +0 -0
  249. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/lookup.rs +0 -0
  250. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/metrics.rs +0 -0
  251. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/mod.rs +0 -0
  252. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/otel.rs +0 -0
  253. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/pack.rs +0 -0
  254. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/random_panic.rs +0 -0
  255. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/raw_json.rs +0 -0
  256. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/retry.rs +0 -0
  257. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/timeout.rs +0 -0
  258. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/transform/coerce.rs +0 -0
  259. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/transform/compiled.rs +0 -0
  260. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/transform/error.rs +0 -0
  261. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/transform/mod.rs +0 -0
  262. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/transform/path.rs +0 -0
  263. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/transform/schema.rs +0 -0
  264. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/transform/tests.rs +0 -0
  265. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/middleware/weak_join.rs +0 -0
  266. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/models/defaults.rs +0 -0
  267. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/models/secrets.rs +0 -0
  268. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/outcomes.rs +0 -0
  269. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/plugin/completion.rs +0 -0
  270. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/plugin/conformance.rs +0 -0
  271. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/plugin/crash.rs +0 -0
  272. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/plugin/discovery.rs +0 -0
  273. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/plugin/endpoint.rs +0 -0
  274. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/plugin/forward.rs +0 -0
  275. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/plugin/host.rs +0 -0
  276. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/plugin/message.rs +0 -0
  277. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/plugin/middleware.rs +0 -0
  278. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/plugin/mod.rs +0 -0
  279. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/plugin/sdk.rs +0 -0
  280. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/plugin/test_support.rs +0 -0
  281. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/publisher.rs +0 -0
  282. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/response.rs +0 -0
  283. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/shutdown.rs +0 -0
  284. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/base64_engine.rs +0 -0
  285. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/change_op.rs +0 -0
  286. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/compression.rs +0 -0
  287. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/compression_pool.rs +0 -0
  288. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/config_schema.rs +0 -0
  289. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/connection_registry.rs +0 -0
  290. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/crypto.rs +0 -0
  291. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/crypto_envelope.rs +0 -0
  292. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/http_status.rs +0 -0
  293. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/interpolation.rs +0 -0
  294. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/lookup_batch.rs +0 -0
  295. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/mod.rs +0 -0
  296. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/ndjson.rs +0 -0
  297. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/pack.rs +0 -0
  298. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/parallel.rs +0 -0
  299. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/parquet.rs +0 -0
  300. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/plugin_abi.rs +0 -0
  301. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/poll_job.rs +0 -0
  302. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/source_ranges.rs +0 -0
  303. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/support/stream_batch.rs +0 -0
  304. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/test_utils.rs +0 -0
  305. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/traits.rs +0 -0
  306. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/src/type_handler.rs +0 -0
  307. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/README.md +0 -0
  308. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/armature_integration.rs +0 -0
  309. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/compat/python/bridge_client.py +0 -0
  310. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/dedup_store_bench.rs +0 -0
  311. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/delivery_guarantee_test.rs +0 -0
  312. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/amqp.rs +0 -0
  313. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/aws.rs +0 -0
  314. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/clickhouse.rs +0 -0
  315. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/config.toml +0 -0
  316. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/amqp.yml +0 -0
  317. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/aws.yml +0 -0
  318. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/clickhouse.yml +0 -0
  319. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/ibm-mq-certs/client.crl +0 -0
  320. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/ibm-mq-certs/client.kdb +0 -0
  321. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/ibm-mq-certs/client.p12 +0 -0
  322. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/ibm-mq-certs/client.rdb +0 -0
  323. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/ibm-mq-certs/client.sth +0 -0
  324. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/ibm_mq.yml +0 -0
  325. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/ibm_mq_tls.yml +0 -0
  326. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/kafka-tls.yml +0 -0
  327. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/kafka.yml +0 -0
  328. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/mariadb.yml +0 -0
  329. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/mongodb-replica.yml +0 -0
  330. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/mongodb-tls.yml +0 -0
  331. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/mongodb.yml +0 -0
  332. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/mosquitto.conf +0 -0
  333. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/mosquitto_performance.conf +0 -0
  334. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/mosquitto_persistence.conf +0 -0
  335. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/mq_init.mqsc +0 -0
  336. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/mq_init_tls.mqsc +0 -0
  337. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/mqtt.yml +0 -0
  338. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/mqtt_performance.yml +0 -0
  339. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/mysql.yml +0 -0
  340. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/nats.yml +0 -0
  341. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/object_store.yml +0 -0
  342. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/postgres.yml +0 -0
  343. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/postgres_cdc.yml +0 -0
  344. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/docker-compose/redis.yml +0 -0
  345. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/file.rs +0 -0
  346. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/grpc.rs +0 -0
  347. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/grpc_tls.rs +0 -0
  348. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/http.rs +0 -0
  349. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/http_tls.rs +0 -0
  350. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/ibm_mq.rs +0 -0
  351. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/ibm_mq_tls.rs +0 -0
  352. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/ipc.rs +0 -0
  353. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/kafka.rs +0 -0
  354. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/kafka_tls.rs +0 -0
  355. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/logic_test.rs +0 -0
  356. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/mariadb.rs +0 -0
  357. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/memory.rs +0 -0
  358. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/mod.rs +0 -0
  359. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/mongodb.rs +0 -0
  360. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/mongodb_raw.rs +0 -0
  361. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/mongodb_tls.rs +0 -0
  362. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/mqtt.rs +0 -0
  363. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/mysql.rs +0 -0
  364. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/nats.rs +0 -0
  365. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/object_store.rs +0 -0
  366. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/performance_static.rs +0 -0
  367. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/postgres_cdc.rs +0 -0
  368. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/redis_streams.rs +0 -0
  369. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/route.rs +0 -0
  370. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/scripts/gen_certs.sh +0 -0
  371. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/sqlite.rs +0 -0
  372. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/tls_helpers.rs +0 -0
  373. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/websocket.rs +0 -0
  374. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/integration/zeromq.rs +0 -0
  375. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/memory_leak_test.rs +0 -0
  376. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/otel_test.rs +0 -0
  377. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/ref_test.rs +0 -0
  378. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/reference_docs_test.rs +0 -0
  379. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/sqlite_test.rs +0 -0
  380. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/tls_example.rs +0 -0
  381. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/unit_tests.md +0 -0
  382. {mq_bridge_basic-0.4.18 → mq_bridge_basic-0.4.19}/tests/websocket_test.rs +0 -0
@@ -2,6 +2,143 @@
2
2
 
3
3
  All notable changes to `mq-bridge`. Newest first.
4
4
 
5
+ ## 0.4.19
6
+
7
+ CSV in more shapes: the reader takes other separators and quoting, and a CSV sink no longer
8
+ mixes JSON into its cells. The second is a behaviour change, listed below.
9
+
10
+ ### Added
11
+
12
+ - **CSV dialects.** `format: csv` took only comma-separated, `"`-quoted files with a header. A
13
+ `csv` block on the `file` endpoint and on an `object_store` source now sets `separator` (one
14
+ character, `tab`, `space`, hex, or `auto`), `quote` (a character or `none`), `header` and
15
+ `columns`. `separator: auto` is for sources and takes whichever of `,` `;` tab `|` occurs
16
+ most often outside quotes in the first record. That covers Excel's semicolon exports, TSV
17
+ from `mongoexport` and `psql`, and headerless dumps; the book's file page lists the setting
18
+ per tool. On the command line it is one parameter, `csv={"separator":"auto"}`.
19
+ `FileConfig` and `ObjectStoreConfig` gain the field `csv`, and `models` the types
20
+ `CsvConfig` and `CsvNested`; code that builds either struct without `..Default::default()`
21
+ needs the new field.
22
+ - **CSV to object storage.** An `object_store` sink rejected `format: csv`. It now writes each
23
+ batch as a CSV file with its own header, taken from that batch's first row, in the dialect
24
+ the `csv` block sets. Set `csv.columns` when every object must have the same columns.
25
+ - **A warning for short CSV rows.** A row with fewer fields than the header was read with the
26
+ missing ones empty and nothing said, which is what a wrong `separator` looks like. It is now
27
+ warned about once per process, as a row with too many fields already was.
28
+
29
+ - **`aggregate`: `on_error`, time-based averages, late-message detection, `read_only`.**
30
+ - `on_error: drop | fail | skip` says what happens to a message that cannot be folded.
31
+ `drop` is the default and what happened before: an input logs, acks and drops it, so an
32
+ HTTP caller gets `202`. `fail` nacks it instead (HTTP `500`). `skip` leaves out only the
33
+ entries that cannot be computed, runs the others, passes the message on and names the
34
+ skipped entries in the metadata `mqb.aggregate.skipped`. Before, one missing field in one
35
+ entry discarded the message for all entries.
36
+ - `ema`, `ema_stddev` and `ema_variance` take a half-life in place of `alpha`
37
+ (`ema(reading, 5m)`): a value counts half after that time, however many messages came.
38
+ The new `time` names the payload field with the event time (epoch seconds or
39
+ milliseconds, or RFC 3339); without it the clock is used.
40
+ - With `time`, a message older than the newest one its state has seen is folded without
41
+ decay and marked with the metadata `mqb.aggregate.late`. It is detected, not reordered.
42
+ - `read_only: true` reads the states from the `store` and never changes them, for a dry run
43
+ or a second route that only reads.
44
+ - The error for a missing field now says `is missing or not a number`.
45
+ - `AggregateMiddleware` gains the fields `time`, `on_error` and `read_only`, and `models`
46
+ the enum `AggregateOnError`; code that builds the struct without `..Default::default()`
47
+ needs the new fields.
48
+ - **Descriptive names for the file formats.** `format: raw` writes only the payload, which
49
+ for JSON payloads is plain JSON lines, while `format: json` writes the whole message
50
+ envelope; the names suggested the opposite. `payload`, `envelope_json`, `envelope_text`
51
+ and `envelope` are now accepted for `raw`, `json`, `text` and `normal`, on `file`,
52
+ `object_store` and `mongodb`. The old names keep working and are what is written back.
53
+ - **`mqb copy`: pipes, `--limit`, progress, compression by file name.**
54
+ - `-` is stdin as the source and stdout as the target (`-?format=csv` takes parameters). A
55
+ `file` source on a pipe, FIFO or terminal is read once without seeking, and its end ends
56
+ the copy, with or without `--drain`. Before, `file:///dev/stdin` failed with `Illegal seek`.
57
+ With stdout as the target the `copied …` summary goes to stderr.
58
+ - `--limit N` stops after `N` rows reached the destination; with `--filter`, `N` matching rows.
59
+ - On a terminal, a running row count is shown on stderr every two seconds.
60
+ - A `file://` path ending in `.gz`, `.zst` or `.lz4` sets `compression`; `compression=none`
61
+ overrides. A sink named `out.jsonl.gz` used to be written uncompressed.
62
+ - A copy without `--drain` now exits when its route ends by itself, on a permanent error or
63
+ the end of a stream. It used to wait for Ctrl-C.
64
+ - **SQL sink: `columns: auto` and `key`.** A SQL sink could write a record's fields into columns
65
+ only through a hand-written `insert_query`, percent-encoded on the command line, and an upsert
66
+ needed its own `ON CONFLICT` clause. With `columns: auto` each top-level JSON field goes into
67
+ the table column of the same name, and `key: id` turns the insert into an upsert, so
68
+ `mqb copy --from 'postgres://…?table=orders&cursor_column=id' --to 'postgres://…?table=orders&columns=auto&key=id'`
69
+ copies a table and can be rerun.
70
+ - The table must exist. A column a record does not name keeps its default (insert) or its
71
+ value (update). A field without a column is not written and is logged once; with
72
+ `extra_column: <name>` those fields go into that column as one JSON object.
73
+ - PostgreSQL casts each value to the column type, so `numeric`, `timestamptz`, `uuid`,
74
+ `jsonb`, enum and array columns take the text a SQL or CSV source delivers.
75
+ - `bulk_copy` works with `columns: auto`, not with `key`. `columns` cannot be combined with
76
+ `insert_query` or `auto_create_table`.
77
+ - `SqlxConfig` gains the fields `columns`, `key` and `extra_column`, and `models` the type `SqlColumns`.
78
+ - **SQL source: `timestamps: rfc3339`.** A Postgres `timestamptz` column is read in Postgres's
79
+ text form, `2026-10-04 09:15:23.923277+00`, which few other systems parse. With
80
+ `timestamps: rfc3339` a `cursor_column` source renders it in UTC as
81
+ `2026-10-04T09:15:23.923277Z`; a `timestamp` without zone gets the `T` and no offset. The
82
+ default is unchanged. `SqlxConfig` gains the field `timestamps` and `models` the type
83
+ `SqlTimestamps`.
84
+
85
+ ### Behaviour changes
86
+
87
+ - **`aggregate`: states in memory only are opt-in.** An `aggregate` without
88
+ a `store` kept its states in the process, lost on restart and wrong with two instances, and
89
+ that was the default. It now needs `consistency: single_writer` next to it; with neither a
90
+ `store` nor that, the route fails to start with an error naming both. Add
91
+ `consistency: single_writer` to a config from 0.4.17 or 0.4.18 that has no `store` to keep
92
+ what it did.
93
+ - **A CSV sink flattens nested objects.** A nested object used to be written as JSON text in
94
+ one cell, so the output of `aggregate` (`{"stats":{"n":3,"avg":2.5}}`) came out as a mix of
95
+ CSV and JSON. It now becomes one column per leaf, named by its path: `stats.n`, `stats.avg`.
96
+ **A new file gets different columns than before; a file that already has a header keeps
97
+ it.** Set `csv.nested: json` for the previous output. Arrays are still written as JSON text.
98
+ - **A drain does not wait for an endpoint.** With `exit_on_empty` (`mqb copy --drain`) a route
99
+ that failed reconnected up to ten times, 5 s apart, before it gave up: about 50 s against a
100
+ closed port, a WebSocket path that answers 404, a NATS subject outside every stream or a gRPC
101
+ topic nobody serves. It now ends on the first failure when nothing has been delivered yet,
102
+ with the endpoint's error. A drain that has delivered something keeps the ten reconnects, so
103
+ a short outage in the middle of a long copy does not end it. Routes without `exit_on_empty`
104
+ reconnect without limit, as before. Add a `retry` middleware to a drain that should wait for
105
+ its sink.
106
+ - **A CSV file that ends inside a quoted field fails a drain.** The reader took everything
107
+ after the open quote as one field and reported success. A drain now writes the records before
108
+ it and fails, naming the byte offset of the open record; a tailing route waits for the writer
109
+ to finish the record.
110
+ - **Blank lines in a line-based file are skipped.** `raw`, `json`, `text` and `normal` sources
111
+ emitted an empty line as a message with an empty payload, which a SQL or Parquet sink then
112
+ rejected. The CSV reader already skipped them. Row counts change for files with blank lines.
113
+ - **A `file` route whose source and sink are the same path is refused.** It doubled the file
114
+ under a drain and would grow it without end otherwise.
115
+ - **SQLite `has no column named` is not retried.** A sink writing to a table without the
116
+ expected columns retried for ever; it is now a non-retryable error like the same case on
117
+ Postgres and MySQL.
118
+ - **An `object_store` source on a local path that does not exist fails a drain.** It reported
119
+ `copied 0 rows`. An empty directory or cloud prefix still does. A drain of a local path also
120
+ ends after one listing instead of waiting out the idle interval.
121
+ - **NATS: a missing `subject` or `stream` stops the route.** It was retried as a connection
122
+ error until the start timeout.
123
+ - **Clearer errors and quieter logs.** A queue read on a plain SQL table names
124
+ `cursor_column`; Postgres errors no longer end in `at line N` (a line of the server's source);
125
+ a closed database port reports `Connection refused` at once; a `filter` that does not compile
126
+ lists the operators, and one with a single `=` says so; a gRPC server names the topic it has
127
+ no consumer for; the drop summary counts messages per cause; an unknown `aggregate` field
128
+ lists the built-ins; `csv` settings without `format: csv` and an `insert_query` token that
129
+ binds NULL each warn once. The WebSocket "falling back to routed mode" line is now DEBUG and
130
+ the MQTT note on restart loss INFO.
131
+
132
+ ### Fixed
133
+
134
+ - **`mqb copy --wait` reports a failed route at once.** A route that failed before it delivered
135
+ anything was retried until the wait ran out, and a later empty attempt could then report
136
+ success. `--wait` now retries only a drain that ended cleanly with nothing to copy.
137
+ - **`aggregate` with a shared `store` no longer keeps the state of a message it rejects.** A
138
+ message whose result had no place in the payload (`into: a.b` where `a` is not an object) was
139
+ counted in the store and then failed, so under `on_error: fail` every redelivery counted it
140
+ again. It now fails before any state changes, as it already did without a shared store.
141
+
5
142
  ## 0.4.18
6
143
 
7
144
  A new generic output for search engines, plus documentation and packaging work. This release
@@ -3689,7 +3689,7 @@ dependencies = [
3689
3689
 
3690
3690
  [[package]]
3691
3691
  name = "mq-bridge"
3692
- version = "0.4.18"
3692
+ version = "0.4.19"
3693
3693
  dependencies = [
3694
3694
  "aes-gcm",
3695
3695
  "anyhow",
@@ -3792,7 +3792,7 @@ dependencies = [
3792
3792
 
3793
3793
  [[package]]
3794
3794
  name = "mq-bridge-bindings-common"
3795
- version = "0.4.18"
3795
+ version = "0.4.19"
3796
3796
  dependencies = [
3797
3797
  "anyhow",
3798
3798
  "fast-uuid-v7",
@@ -3806,7 +3806,7 @@ dependencies = [
3806
3806
 
3807
3807
  [[package]]
3808
3808
  name = "mq-bridge-node"
3809
- version = "0.4.18"
3809
+ version = "0.4.19"
3810
3810
  dependencies = [
3811
3811
  "anyhow",
3812
3812
  "async-trait",
@@ -3861,7 +3861,7 @@ dependencies = [
3861
3861
 
3862
3862
  [[package]]
3863
3863
  name = "mq-bridge-py"
3864
- version = "0.4.18"
3864
+ version = "0.4.19"
3865
3865
  dependencies = [
3866
3866
  "anyhow",
3867
3867
  "async-trait",
@@ -40,7 +40,7 @@ dbg_macro = "warn"
40
40
  exit = "warn"
41
41
 
42
42
  [workspace.package]
43
- version = "0.4.18"
43
+ version = "0.4.19"
44
44
 
45
45
  [workspace.dependencies]
46
46
  anyhow = "1.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mq-bridge-basic
3
- Version: 0.4.18
3
+ Version: 0.4.19
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: Topic :: Database
@@ -93,7 +93,7 @@ Every row works from the Rust crate, the Python and Node.js packages, and the ze
93
93
  | **MongoDB** as source or sink | `mongodb` endpoint · `mongodb` | [MongoDB](https://marcomq.github.io/mq-bridge/connectors/mongodb.html) |
94
94
  | **ClickHouse** bulk insert and resumable reads | `clickhouse` endpoint · `clickhouse` | [ClickHouse](https://marcomq.github.io/mq-bridge/connectors/clickhouse.html) |
95
95
  | **Search engines** and other bulk document APIs (Meilisearch, Typesense, Elasticsearch, Qdrant, PostgREST / Supabase) | `http_bulk` endpoint · `http-bulk` | [HTTP bulk](https://marcomq.github.io/mq-bridge/connectors/http-bulk.html) |
96
- | **Object storage**: S3 (and S3-compatible, e.g. R2), GCS, Azure Blob, or a local directory, as **Parquet** or **JSONL**; **CSV** as input | `object_store` endpoint with `format: parquet \| raw \| json \| csv` · `object-store`, `parquet` | [Object storage](https://marcomq.github.io/mq-bridge/connectors/object-store.html) |
96
+ | **Object storage**: S3 (and S3-compatible, e.g. R2), GCS, Azure Blob, or a local directory, as **Parquet**, **JSONL** or **CSV** | `object_store` endpoint with `format: parquet \| raw \| json \| csv` · `object-store`, `parquet` | [Object storage](https://marcomq.github.io/mq-bridge/connectors/object-store.html) |
97
97
  | **Files**: CSV and JSONL, read and write | `file` endpoint · built in | [File](https://marcomq.github.io/mq-bridge/connectors/file.html) |
98
98
  | **Analytics / warehouses**: Snowflake, BigQuery, Databricks / Spark, Athena / Trino, DuckDB **via Parquet on S3/GCS/Azure**. These are not native connectors: mq-bridge writes the Parquet files, the warehouse loads or queries them | `object_store` with `format: parquet` · `parquet` | [Snowflake](https://marcomq.github.io/mq-bridge/cookbook/snowflake.html) · [BigQuery](https://marcomq.github.io/mq-bridge/cookbook/bigquery.html) · [Databricks / Spark](https://marcomq.github.io/mq-bridge/cookbook/databricks.html) · [Athena / Trino](https://marcomq.github.io/mq-bridge/cookbook/athena.html) · [DuckDB](https://marcomq.github.io/mq-bridge/cookbook/duckdb.html) |
99
99
  | **HTTP, gRPC, WebSocket** as server or client, including request/reply | `http`, `grpc`, `websocket` endpoints · `http`, `grpc`, `websocket` | [HTTP](https://marcomq.github.io/mq-bridge/connectors/http.html) · [gRPC](https://marcomq.github.io/mq-bridge/connectors/grpc.html) · [Request / reply](https://marcomq.github.io/mq-bridge/tutorials/request-reply.html) |
@@ -116,6 +116,8 @@ Throughput is tracked continuously on the public [benchmark dashboard](https://m
116
116
  | CSV → JSONL, 1M mixed-type rows (~116 MiB) | **2,824,858 rows/s**, ~28 MiB RAM | Meltano (`tap-csv` → `target-jsonl`): ~19,500 rows/s, ~444 MiB RAM — **~145x slower**<br>DuckDB, all cores: 2,036,659 rows/s — mq-bridge **~1.4x faster**, ~17x less memory |
117
117
  | Kafka → file, 1M rows, no transform | **~65% faster** than Sea Streamer | Sea Streamer, both on mimalloc (~80% faster vs. its default-allocator build) |
118
118
 
119
+ The CSV row reuses an existing, independently published 1M-row CSV → JSONL workload, on a byte-identical fixture: 7 mixed-type columns, seed 42, 121,981,421 bytes, SHA-256 `a84894e0…0c45b221` ([full definition](apps/mq-bridge-app/benches/etl/README.md#6--csv--jsonl-vs-meltano)). Whole-process wall-clock, no transformation, Meltano run on the same machine and file.
120
+
119
121
  CSV figures: mq-bridge 0.4.12. DuckDB is a throughput ceiling for the conversion itself, not an ETL tool. Methodology and reporting rules are in [`benches/ETL_BENCHMARKS.md`](benches/ETL_BENCHMARKS.md); the raw numbers, baselines and reproducible helpers are in the [ETL benchmark harness](apps/mq-bridge-app/benches/etl/README.md).
120
122
 
121
123
 
@@ -170,17 +172,12 @@ tuning use the same settings in both.
170
172
 
171
173
  ## Status
172
174
 
173
- `mq-bridge` is young (created in 2025), but its reliability behavior is exercised by an automated integration and performance suite across **every** supported endpoint, in each of the queue and subscriber modes that endpoint supports:
175
+ `mq-bridge` was created in 2025. Its reliability behavior is exercised by an automated integration and performance suite across supported endpoints, in each of the queue and subscriber modes that endpoint supports:
174
176
 
175
177
  * All endpoints showed **no data loss during in-flight broker restarts**; MQTT publish confirmation was hardened until a chaos test drove in-flight loss to **zero**.
176
178
  * Postgres CDC has a **restart-safety test**: an un-acked, in-flight batch is redelivered after a database restart with no loss and no gap.
177
179
 
178
- Known rough edges:
179
-
180
- - old or very new broker-server versions, or unusual broker settings
181
- - subscribe/event and response patterns where the backend has no native equivalent (emulated); MongoDB request/reply is only covered by automated tests so far
182
- - NATS without JetStream (integration tests run with JetStream only)
183
- - **TLS**: one `TlsConfig` shape is shared by all transports and covered by automated tests, but per-backend certificate matrices are still being expanded, so verify non-trivial TLS setups yourself
180
+ It is used as rust library in [armature](https://github.com/quinnjr/armature) and as python lib in [omniload](https://github.com/panodata/omniload).
184
181
 
185
182
  ## Running Tests
186
183
  The project includes integration and performance tests. Most backend tests require Docker.
@@ -700,7 +700,43 @@ stream. File compression/encryption supports only the default `consume` mode. `c
700
700
  too: the header row is written into the first member, so the decoded stream is a normal CSV
701
701
  file.
702
702
 
703
- A `csv` sink takes its columns from the first row it writes, in that row's field order.
703
+ A `csv` sink takes its columns from the first row it writes, in that row's field order. An
704
+ `object_store` sink writes each batch as a CSV file of its own, with its own header taken from
705
+ that batch's first row; set `columns` when every object must have the same ones.
706
+
707
+ `csv` on its own means comma-separated, `"`-quoted, with a header record. The `csv` block
708
+ describes any other dialect, for the `file` and `object_store` endpoints:
709
+
710
+ ```yaml endpoint
711
+ input:
712
+ file:
713
+ path: "export.csv"
714
+ format: csv
715
+ csv:
716
+ separator: ";" # one character, `tab`, `space`, hex (`0x1f`), or `auto`
717
+ quote: "'" # one character, or `none`; default `"`
718
+ header: false # first record is data; a source then needs `columns`
719
+ columns: [id, name] # replaces the header's names; a sink writes exactly these
720
+ ```
721
+
722
+ | Field | Default | Meaning |
723
+ | --- | --- | --- |
724
+ | `separator` | `,` | Field separator. `auto` (sources only) picks whichever of `,` `;` tab `\|` occurs most often outside quotes in the first record, and `,` on a tie. |
725
+ | `quote` | `"` | Quote character; a doubled one inside a quoted field is a literal. `none` reads every byte as data and makes a sink fail a value it would have to quote. |
726
+ | `header` | `true` | Whether the first record names the columns. A sink with `false` writes rows only. |
727
+ | `columns` | — | Source: the keys to use, instead of the header's. Sink: the columns to write, in this order; other keys are dropped. |
728
+ | `nested` | `flatten` | Sink only. `flatten` writes a nested object as one `parent.child` column per leaf; `json` writes its JSON text into one cell. Arrays are always JSON text. |
729
+
730
+ `delimiter` stays the *record* separator and is independent of all this; it only must not
731
+ contain the separator or the quote character. Common exports: Excel "CSV UTF-8" in a
732
+ semicolon locale is `separator: ";"` (the byte-order mark and CRLF are handled already),
733
+ `mongoexport --type=tsv` and `psql -A -F $'\t'` are `separator: tab`, and `psql --csv` and
734
+ `COPY … WITH (FORMAT csv)` are the default. PostgreSQL's `COPY` *text* format (backslash
735
+ escapes, `\N`) and UTF-16 files are not CSV dialects and are not read.
736
+
737
+ A row with more fields than the header drops the extras, and one with fewer reads the missing
738
+ ones as empty. Each is warned about once per process; a short row is the usual sign of a wrong
739
+ `separator`.
704
740
 
705
741
  A file **source** must declare the same `compression`/`encryption` the data was written with.
706
742
  A mismatch (wrong key, wrong codec, or a missing field) is a permanent decode failure: the
@@ -1151,12 +1187,16 @@ to keep a counter: the arithmetic runs here, so no request is made per message.
1151
1187
  | `output` | expression | the state itself; shapes what is written to the message |
1152
1188
  | `emit` | `updated` \| `previous` | `updated` |
1153
1189
  | `entries` | list of `{key, expression, fields, into, output, emit}` | `[]`; further aggregates |
1154
- | `store` | URL | – (states live in memory); `postgres://…/db[/table]`, `sqlite://…`, `mongodb://host/db[/collection]` |
1155
- | `consistency` | `shared` \| `single_writer` | `shared`; only used with `store` |
1190
+ | `store` | URL | –; `postgres://…/db[/table]`, `sqlite://…`, `mongodb://host/db[/collection]`. Without it `consistency: single_writer` is required |
1191
+ | `consistency` | `shared` \| `single_writer` | `shared`, which needs a `store`; `single_writer` without a `store` keeps the states in memory only |
1156
1192
  | `max_keys` | integer | `1000000`; states kept in memory per entry, `0` is unlimited |
1193
+ | `time` | dotted payload path | – (the clock); the message's event time, for `fields` entries |
1194
+ | `on_error` | `drop` \| `fail` \| `skip` | `drop`; what happens to a message that cannot be folded |
1195
+ | `read_only` | bool | `false`; reads the states of the `store` and never changes them |
1157
1196
 
1158
1197
  ```yaml middleware
1159
1198
  - aggregate:
1199
+ consistency: single_writer
1160
1200
  key: "${payload:sensor_id}"
1161
1201
  into: sensor
1162
1202
  expression: "{ total: (state.total ?? 0) + reading, count: (state.count ?? 0) + 1 }"
@@ -1166,6 +1206,11 @@ to keep a counter: the arithmetic runs here, so no request is made per message.
1166
1206
  `{"sensor_id": 7, "reading": 20, "sensor": {"total": 20, "count": 1}}`; the next message for sensor 7
1167
1207
  continues from that state.
1168
1208
 
1209
+ **States in memory only are opt-in.** Without a `store` the states are lost on restart and
1210
+ not shared between instances, so that has to be asked for with `consistency: single_writer`,
1211
+ as above. An `aggregate` with neither a `store` nor `consistency: single_writer` is a startup
1212
+ error.
1213
+
1169
1214
  **Expressions** are the ones [`filter`](#filter) and [`transform`](#transform) use. They read
1170
1215
  payload fields by name and metadata as `meta.<key>`, plus `state`: the value `expression`
1171
1216
  returned for the previous message with the same key. For a key seen for the first time
@@ -1184,6 +1229,7 @@ to forget it. Keep the weighted sum and the weight instead and divide when writi
1184
1229
 
1185
1230
  ```yaml middleware
1186
1231
  - aggregate:
1232
+ consistency: single_writer
1187
1233
  key: "${payload:sensor_id}"
1188
1234
  into: sensor.avg_reading
1189
1235
  expression: "{ s: (state.s ?? 0) * 0.99 + reading, w: (state.w ?? 0) * 0.99 + 1 }"
@@ -1197,6 +1243,7 @@ the usual form still reads 216.
1197
1243
 
1198
1244
  ```yaml middleware
1199
1245
  - aggregate:
1246
+ consistency: single_writer
1200
1247
  entries:
1201
1248
  - key: "${payload:sensor_id}"
1202
1249
  into: features.sensor
@@ -1212,6 +1259,7 @@ times faster, because no expression runs and the payload is not parsed into a tr
1212
1259
 
1213
1260
  ```yaml middleware
1214
1261
  - aggregate:
1262
+ consistency: single_writer
1215
1263
  key: "${payload:sensor_id}"
1216
1264
  into: sensor
1217
1265
  fields:
@@ -1228,14 +1276,84 @@ times faster, because no expression runs and the payload is not parsed into a tr
1228
1276
  | `mean(path)` | arithmetic mean |
1229
1277
  | `stddev(path)`, `variance(path)` | sample standard deviation and variance (divided by n − 1) of all values; `null` for the first message |
1230
1278
  | `ema(path, alpha)` | moving average weighting each new value with `alpha` (0 < alpha ≤ 1), without a start bias: the first message reads its own value |
1231
- | `ema_stddev(path, alpha)`, `ema_variance(path, alpha)` | the same over values weighted like `ema`, so old values fade; `null` for the first message |
1279
+ | `ema(path, half_life)` | the same, weighted by time: a value counts half after `half_life`, e.g. `ema(reading, 5m)`. Units: `ms`, `s`, `m`, `h`, `d` |
1280
+ | `ema_stddev(path, alpha)`, `ema_variance(path, alpha)` | the same over values weighted like `ema`, so old values fade; `null` for the first message. Both take a half-life in place of `alpha` too |
1232
1281
 
1233
1282
  `path` is a dotted payload path such as `reading` or `device.reading`. Its value must be a
1234
- number or a numeric string (what a CSV source delivers); a message without one fails like a
1235
- message with a failing expression. The result is an object with the field names in
1283
+ number or a numeric string (what a CSV source delivers); a message without one cannot be
1284
+ folded, see [`on_error`](#aggregate-on-error). The result is an object with the field names in
1236
1285
  alphabetical order, e.g. `{"avg": 20.0, "high": 20.0, "n": 1, "total": 20.0}`. An entry takes
1237
1286
  either `expression` or `fields`; entries of both kinds can be mixed. `fields` takes no `output`.
1238
1287
 
1288
+ **Time.** `ema(path, alpha)` counts messages: ten messages in one second fade a value as
1289
+ much as ten messages in one day. With a half-life the weight follows the time between two
1290
+ messages of a key instead. `time` names the payload field holding the message's time: epoch
1291
+ seconds, epoch milliseconds (any number above 1e11), or an RFC 3339 text such as
1292
+ `2026-10-03T12:00:00Z`; a text without a zone is read as UTC. Without `time` the clock of
1293
+ this process is used, which makes a replay compute different values.
1294
+
1295
+ ```yaml middleware
1296
+ - aggregate:
1297
+ consistency: single_writer
1298
+ key: "${payload:sensor_id}"
1299
+ into: sensor
1300
+ time: measured_at
1301
+ fields:
1302
+ n: count
1303
+ avg: ema(reading, 5m)
1304
+ spread: ema_stddev(reading, 1h)
1305
+ ```
1306
+
1307
+ **Late messages are detected, not corrected.** With `time` set, every `fields` state
1308
+ remembers the newest time it has seen. A message with an older time is folded as if it had
1309
+ arrived at that newest time (nothing decays for it), and it carries the metadata
1310
+ `mqb.aggregate.late` naming the entries concerned by their `into`, comma-separated. A
1311
+ [`filter`](#filter) or a `switch` can act on it as `meta["mqb.aggregate.late"]`. The first
1312
+ occurrence is logged as a warning. `time` adds one slot to each `fields` state; states stored
1313
+ before it was set are read and extended. Expression entries do not use `time`.
1314
+
1315
+ <a id="aggregate-on-error"></a>
1316
+ **A message that cannot be folded.** Its payload is not a JSON object, a `key` has no value,
1317
+ a field read by `fields` or `time` is missing or not a number, or an expression fails. One
1318
+ entry that cannot be computed is enough. `on_error` decides what follows; no state changes
1319
+ for an entry that was not computed.
1320
+
1321
+ | `on_error` | On an input | On an output |
1322
+ |---|---|---|
1323
+ | `drop` (default) | logged, acked and dropped. **The source sees a success**: an HTTP caller gets `202` | only that message fails, as non-retryable |
1324
+ | `fail` | logged and nacked, so the source sees the failure: an HTTP caller gets `500`. A source that redelivers nacked messages (a broker) delivers it again | as `drop` |
1325
+ | `skip` | the entries that cannot be computed are left out, the others run, and the message goes on. A message no entry can fold goes on unchanged | the same |
1326
+
1327
+ A message that left entries out under `skip` carries the metadata `mqb.aggregate.skipped`
1328
+ with their `into` paths, comma-separated, and the first occurrence is logged as a warning;
1329
+ the reason for each is logged at debug level.
1330
+
1331
+ ```yaml middleware
1332
+ - aggregate:
1333
+ consistency: single_writer
1334
+ on_error: skip
1335
+ entries:
1336
+ - { key: "${payload:sensor_id}", into: sensor, fields: { avg: "ema(reading, 0.01)" } }
1337
+ - { key: "${payload:site_id}", into: site, fields: { high: max(reading) } }
1338
+ ```
1339
+
1340
+ **Reading without writing.** `read_only: true` computes and writes into the message as
1341
+ usual but stores nothing, so a dry run or a second route can use the states another route
1342
+ maintains. `emit: updated` shows what the state would become with this message,
1343
+ `emit: previous` the stored state as it is. It needs a `store`; states are loaded per batch
1344
+ whatever `consistency` says, and each message of a batch sees the stored state, not the
1345
+ messages before it.
1346
+
1347
+ ```yaml middleware
1348
+ - aggregate:
1349
+ store: "postgres://localhost/telemetry/sensor_states"
1350
+ read_only: true
1351
+ emit: previous
1352
+ key: "${payload:sensor_id}"
1353
+ into: sensor
1354
+ fields: { n: count, avg: "ema(reading, 0.01)" }
1355
+ ```
1356
+
1239
1357
  **Keeping the states in a store.** With `store` the states survive a restart. The table or
1240
1358
  collection defaults to `mqb_aggregate_<route>` and is created on start; PostgreSQL, SQLite
1241
1359
  and MongoDB are supported.
@@ -1283,7 +1401,7 @@ and MongoDB are supported.
1283
1401
  **What to expect.**
1284
1402
 
1285
1403
  - **Without `store`, state lives in memory only.** It is lost on restart and it is not shared
1286
- between instances.
1404
+ between instances, which is why it needs `consistency: single_writer`.
1287
1405
  - **Memory is bounded by `max_keys`.** An entry keeps at most that many states in memory,
1288
1406
  one million unless set. When it is full, the half that was used least recently is dropped.
1289
1407
  Without a `store` those states are forgotten: their key starts again from an empty state,
@@ -1295,13 +1413,13 @@ and MongoDB are supported.
1295
1413
  first: on an input, list it *after* `aggregate` (see [Ordering](#ordering--read-this-before-combining-middleware)).
1296
1414
  - **Order matters for order-dependent states** such as a moving average. Within a batch
1297
1415
  messages are folded in order; with a route `concurrency` above 1 the order across batches
1298
- is not guaranteed.
1299
- - **A message that cannot be folded fails alone** and changes no state: its payload is not a
1300
- JSON object, its `key` has no value, or an expression fails. On an input it is logged,
1301
- acked and dropped; on an output only that message fails, as non-retryable.
1416
+ is not guaranteed. With `time`, a message older than its state is marked, not reordered.
1417
+ - **A message that cannot be folded fails alone** and changes no state. By default an input
1418
+ drops it and still acks it, so an HTTP caller gets `202`; see
1419
+ [`on_error`](#aggregate-on-error) for `fail` and `skip`.
1302
1420
  - **No windows and no expiry by time.** There is no "last hour" and no time to live: a state
1303
1421
  covers every message of its key, and a row in the store is never removed. `ema` and
1304
- `ema_stddev` stand in for a sliding window. For fixed windows put the window into the key,
1422
+ `ema_stddev` stand in for a sliding window, by message count or with a half-life by time. For fixed windows put the window into the key,
1305
1423
  e.g. `key: "${payload:sensor_id}:${payload:hour}"`, and use a `store` with `shared`, which
1306
1424
  keeps no state in memory; the rows of past windows stay until you delete them.
1307
1425
  - **No exactly-once and no key ownership.** A stream processor commits state and input