taskito 0.16.1__tar.gz → 0.16.2__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 (330) hide show
  1. {taskito-0.16.1 → taskito-0.16.2}/Cargo.lock +21 -21
  2. {taskito-0.16.1 → taskito-0.16.2}/PKG-INFO +1 -1
  3. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/Cargo.toml +5 -1
  4. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/scheduler/poller.rs +16 -9
  5. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/diesel_common/jobs.rs +25 -0
  6. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/mod.rs +6 -0
  7. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/dead_letter.rs +25 -9
  8. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/jobs/dequeue.rs +57 -12
  9. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/jobs/helpers.rs +104 -34
  10. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/jobs/state.rs +74 -15
  11. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/sqlite/tests.rs +33 -0
  12. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/traits.rs +5 -0
  13. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/tests/rust/storage_tests.rs +220 -0
  14. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/Cargo.toml +1 -1
  15. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-workflows/Cargo.toml +1 -1
  16. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/__init__.py +1 -1
  17. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/handlers/settings.py +6 -2
  18. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/notes.py +14 -1
  19. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/result.py +5 -1
  20. {taskito-0.16.1 → taskito-0.16.2}/pyproject.toml +1 -1
  21. {taskito-0.16.1 → taskito-0.16.2}/Cargo.toml +0 -0
  22. {taskito-0.16.1 → taskito-0.16.2}/LICENSE +0 -0
  23. {taskito-0.16.1 → taskito-0.16.2}/README.md +0 -0
  24. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/error.rs +0 -0
  25. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/job.rs +0 -0
  26. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/lib.rs +0 -0
  27. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/periodic.rs +0 -0
  28. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/resilience/circuit_breaker.rs +0 -0
  29. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/resilience/dlq.rs +0 -0
  30. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/resilience/mod.rs +0 -0
  31. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/resilience/rate_limiter.rs +0 -0
  32. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/resilience/retry.rs +0 -0
  33. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/scheduler/maintenance.rs +0 -0
  34. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/scheduler/mod.rs +0 -0
  35. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/scheduler/result_handler.rs +0 -0
  36. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/scheduler/wake.rs +0 -0
  37. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/diesel_common/archival.rs +0 -0
  38. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/diesel_common/dead_letter.rs +0 -0
  39. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/diesel_common/locks.rs +0 -0
  40. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/diesel_common/logs.rs +0 -0
  41. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/diesel_common/metrics.rs +0 -0
  42. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/diesel_common/migrations.rs +0 -0
  43. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/diesel_common/mod.rs +0 -0
  44. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/diesel_common/workers.rs +0 -0
  45. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/models.rs +0 -0
  46. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/notify.rs +0 -0
  47. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/postgres/archival.rs +0 -0
  48. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/postgres/circuit_breakers.rs +0 -0
  49. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/postgres/dashboard_settings.rs +0 -0
  50. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/postgres/dead_letter.rs +0 -0
  51. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/postgres/jobs.rs +0 -0
  52. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/postgres/listener.rs +0 -0
  53. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/postgres/locks.rs +0 -0
  54. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/postgres/logs.rs +0 -0
  55. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/postgres/metrics.rs +0 -0
  56. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/postgres/mod.rs +0 -0
  57. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/postgres/periodic.rs +0 -0
  58. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/postgres/queue_state.rs +0 -0
  59. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/postgres/rate_limits.rs +0 -0
  60. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/postgres/trait_impl.rs +0 -0
  61. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/postgres/workers.rs +0 -0
  62. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/archival.rs +0 -0
  63. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/circuit_breakers.rs +0 -0
  64. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/dashboard_settings.rs +0 -0
  65. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/jobs/enqueue.rs +0 -0
  66. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/jobs/errors.rs +0 -0
  67. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/jobs/maintenance.rs +0 -0
  68. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/jobs/mod.rs +0 -0
  69. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/jobs/query.rs +0 -0
  70. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/listener.rs +0 -0
  71. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/locks.rs +0 -0
  72. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/logs.rs +0 -0
  73. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/metrics.rs +0 -0
  74. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/mod.rs +0 -0
  75. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/periodic.rs +0 -0
  76. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/queue_state.rs +0 -0
  77. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/rate_limits.rs +0 -0
  78. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/trait_impl.rs +0 -0
  79. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/redis_backend/workers.rs +0 -0
  80. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/schema.rs +0 -0
  81. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/sqlite/archival.rs +0 -0
  82. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/sqlite/circuit_breakers.rs +0 -0
  83. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/sqlite/dashboard_settings.rs +0 -0
  84. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/sqlite/dead_letter.rs +0 -0
  85. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/sqlite/jobs.rs +0 -0
  86. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/sqlite/locks.rs +0 -0
  87. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/sqlite/logs.rs +0 -0
  88. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/sqlite/metrics.rs +0 -0
  89. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/sqlite/mod.rs +0 -0
  90. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/sqlite/periodic.rs +0 -0
  91. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/sqlite/queue_state.rs +0 -0
  92. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/sqlite/rate_limits.rs +0 -0
  93. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/sqlite/trait_impl.rs +0 -0
  94. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/storage/sqlite/workers.rs +0 -0
  95. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/src/worker.rs +0 -0
  96. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-core/tests/rust.rs +0 -0
  97. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/async_worker.rs +0 -0
  98. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/lib.rs +0 -0
  99. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/prefork/child.rs +0 -0
  100. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/prefork/dispatch.rs +0 -0
  101. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/prefork/mod.rs +0 -0
  102. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/prefork/protocol.rs +0 -0
  103. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/prefork/slot.rs +0 -0
  104. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/prefork/watchdog.rs +0 -0
  105. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/py_config.rs +0 -0
  106. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/py_job.rs +0 -0
  107. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/py_queue/inspection.rs +0 -0
  108. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/py_queue/mod.rs +0 -0
  109. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/py_queue/worker.rs +0 -0
  110. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/py_queue/workflow_ops/fan_out.rs +0 -0
  111. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/py_queue/workflow_ops/gates.rs +0 -0
  112. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/py_queue/workflow_ops/lifecycle.rs +0 -0
  113. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/py_queue/workflow_ops/mod.rs +0 -0
  114. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/py_queue/workflow_ops/nodes.rs +0 -0
  115. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/py_queue/workflow_ops/queries.rs +0 -0
  116. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/py_queue/workflow_ops/saga.rs +0 -0
  117. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/py_queue/workflow_ops/test_helpers.rs +0 -0
  118. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/py_worker.rs +0 -0
  119. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-python/src/py_workflow/mod.rs +0 -0
  120. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-workflows/src/common.rs +0 -0
  121. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-workflows/src/definition.rs +0 -0
  122. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-workflows/src/diesel_common.rs +0 -0
  123. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-workflows/src/error.rs +0 -0
  124. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-workflows/src/lib.rs +0 -0
  125. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-workflows/src/node.rs +0 -0
  126. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-workflows/src/postgres_store.rs +0 -0
  127. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-workflows/src/redis_store.rs +0 -0
  128. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-workflows/src/run.rs +0 -0
  129. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-workflows/src/sqlite_store.rs +0 -0
  130. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-workflows/src/state.rs +0 -0
  131. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-workflows/src/storage.rs +0 -0
  132. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-workflows/src/tests.rs +0 -0
  133. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-workflows/src/topology.rs +0 -0
  134. {taskito-0.16.1 → taskito-0.16.2}/crates/taskito-workflows/tests/storage_contract.rs +0 -0
  135. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/_active_context.py +0 -0
  136. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/_taskito.pyi +0 -0
  137. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/app.py +0 -0
  138. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/async_support/__init__.py +0 -0
  139. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/async_support/canvas.py +0 -0
  140. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/async_support/context.py +0 -0
  141. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/async_support/executor.py +0 -0
  142. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/async_support/helpers.py +0 -0
  143. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/async_support/locks.py +0 -0
  144. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/async_support/mixins.py +0 -0
  145. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/async_support/result.py +0 -0
  146. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/autoscale/__init__.py +0 -0
  147. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/autoscale/config.py +0 -0
  148. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/autoscale/controller.py +0 -0
  149. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/autoscale/process_manager.py +0 -0
  150. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/batching/__init__.py +0 -0
  151. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/batching/accumulator.py +0 -0
  152. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/batching/config.py +0 -0
  153. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/batching/item_result.py +0 -0
  154. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/batching/result.py +0 -0
  155. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/canvas.py +0 -0
  156. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/cli.py +0 -0
  157. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/context.py +0 -0
  158. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/contrib/__init__.py +0 -0
  159. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/contrib/django/__init__.py +0 -0
  160. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/contrib/django/admin.py +0 -0
  161. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/contrib/django/apps.py +0 -0
  162. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/contrib/django/management/__init__.py +0 -0
  163. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/contrib/django/management/commands/__init__.py +0 -0
  164. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/contrib/django/management/commands/taskito_dashboard.py +0 -0
  165. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/contrib/django/management/commands/taskito_info.py +0 -0
  166. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/contrib/django/management/commands/taskito_worker.py +0 -0
  167. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/contrib/django/settings.py +0 -0
  168. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/contrib/fastapi.py +0 -0
  169. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/contrib/flask.py +0 -0
  170. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/contrib/otel.py +0 -0
  171. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/contrib/prometheus.py +0 -0
  172. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/contrib/sentry.py +0 -0
  173. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/__init__.py +0 -0
  174. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/_testing.py +0 -0
  175. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/auth.py +0 -0
  176. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/delivery_store.py +0 -0
  177. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/errors.py +0 -0
  178. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/handlers/__init__.py +0 -0
  179. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/handlers/_qs.py +0 -0
  180. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/handlers/auth.py +0 -0
  181. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/handlers/dead_letters.py +0 -0
  182. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/handlers/jobs.py +0 -0
  183. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/handlers/logs.py +0 -0
  184. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/handlers/metrics.py +0 -0
  185. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/handlers/middleware.py +0 -0
  186. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/handlers/oauth.py +0 -0
  187. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/handlers/overrides.py +0 -0
  188. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/handlers/queues.py +0 -0
  189. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/handlers/scaler.py +0 -0
  190. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/handlers/webhook_deliveries.py +0 -0
  191. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/handlers/webhooks.py +0 -0
  192. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/handlers/workflows.py +0 -0
  193. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/middleware_store.py +0 -0
  194. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/oauth/__init__.py +0 -0
  195. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/oauth/config.py +0 -0
  196. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/oauth/flow.py +0 -0
  197. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/oauth/identity.py +0 -0
  198. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/oauth/pkce.py +0 -0
  199. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/oauth/providers.py +0 -0
  200. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/oauth/state_store.py +0 -0
  201. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/overrides_store.py +0 -0
  202. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/request_context.py +0 -0
  203. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/routes.py +0 -0
  204. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/server.py +0 -0
  205. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/static.py +0 -0
  206. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/url_safety.py +0 -0
  207. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/dashboard/webhook_store.py +0 -0
  208. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/events.py +0 -0
  209. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/exceptions.py +0 -0
  210. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/health.py +0 -0
  211. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/inject.py +0 -0
  212. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/interception/__init__.py +0 -0
  213. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/interception/built_in.py +0 -0
  214. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/interception/converters.py +0 -0
  215. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/interception/errors.py +0 -0
  216. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/interception/interceptor.py +0 -0
  217. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/interception/metrics.py +0 -0
  218. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/interception/reconstruct.py +0 -0
  219. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/interception/registry.py +0 -0
  220. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/interception/strategy.py +0 -0
  221. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/interception/walker.py +0 -0
  222. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/locks.py +0 -0
  223. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/log_config.py +0 -0
  224. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/mesh.py +0 -0
  225. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/middleware.py +0 -0
  226. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/mixins/__init__.py +0 -0
  227. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/mixins/_shared.py +0 -0
  228. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/mixins/decorators.py +0 -0
  229. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/mixins/events.py +0 -0
  230. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/mixins/inspection.py +0 -0
  231. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/mixins/lifecycle.py +0 -0
  232. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/mixins/locks.py +0 -0
  233. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/mixins/middleware_admin.py +0 -0
  234. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/mixins/operations.py +0 -0
  235. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/mixins/overrides.py +0 -0
  236. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/mixins/predicates.py +0 -0
  237. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/mixins/resources.py +0 -0
  238. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/mixins/runtime_config.py +0 -0
  239. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/mixins/settings.py +0 -0
  240. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/predicates/__init__.py +0 -0
  241. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/predicates/context.py +0 -0
  242. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/predicates/core.py +0 -0
  243. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/predicates/evaluate.py +0 -0
  244. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/predicates/metrics.py +0 -0
  245. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/predicates/outcomes.py +0 -0
  246. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/predicates/parser.py +0 -0
  247. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/predicates/providers.py +0 -0
  248. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/predicates/recipes/__init__.py +0 -0
  249. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/predicates/recipes/attributes.py +0 -0
  250. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/predicates/recipes/config.py +0 -0
  251. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/predicates/recipes/system.py +0 -0
  252. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/predicates/recipes/time.py +0 -0
  253. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/predicates/registry.py +0 -0
  254. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/prefork/__init__.py +0 -0
  255. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/prefork/__main__.py +0 -0
  256. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/prefork/child.py +0 -0
  257. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/proxies/__init__.py +0 -0
  258. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/proxies/built_in.py +0 -0
  259. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/proxies/handler.py +0 -0
  260. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/proxies/handlers/__init__.py +0 -0
  261. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/proxies/handlers/boto3_client.py +0 -0
  262. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/proxies/handlers/file.py +0 -0
  263. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/proxies/handlers/gcs_client.py +0 -0
  264. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/proxies/handlers/httpx_client.py +0 -0
  265. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/proxies/handlers/logger.py +0 -0
  266. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/proxies/handlers/requests_session.py +0 -0
  267. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/proxies/metrics.py +0 -0
  268. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/proxies/no_proxy.py +0 -0
  269. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/proxies/reconstruct.py +0 -0
  270. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/proxies/registry.py +0 -0
  271. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/proxies/schema.py +0 -0
  272. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/proxies/signing.py +0 -0
  273. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/py.typed +0 -0
  274. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/resources/__init__.py +0 -0
  275. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/resources/definition.py +0 -0
  276. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/resources/frozen.py +0 -0
  277. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/resources/graph.py +0 -0
  278. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/resources/health.py +0 -0
  279. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/resources/pool.py +0 -0
  280. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/resources/runtime.py +0 -0
  281. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/resources/thread_local.py +0 -0
  282. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/resources/toml_config.py +0 -0
  283. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/scaler.py +0 -0
  284. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/serializers.py +0 -0
  285. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  286. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  287. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  288. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  289. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
  290. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
  291. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  292. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  293. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  294. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  295. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  296. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  297. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/ibm-plex-serif-latin-500-normal-C3_OdgN3.woff +0 -0
  298. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/ibm-plex-serif-latin-500-normal-REKAfBVG.woff2 +0 -0
  299. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/ibm-plex-serif-latin-600-normal-D3rpGdkS.woff +0 -0
  300. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/ibm-plex-serif-latin-600-normal-DAxitmSu.woff2 +0 -0
  301. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/index-W-qtINsk.js +0 -0
  302. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/index-XTjpQV4Y.css +0 -0
  303. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/logs.lazy-BRzWGIVq.js +0 -0
  304. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/assets/metrics.lazy-7u0OCPof.js +0 -0
  305. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/static/dashboard/index.html +0 -0
  306. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/task.py +0 -0
  307. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/testing.py +0 -0
  308. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/webhooks.py +0 -0
  309. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/__init__.py +0 -0
  310. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/analysis.py +0 -0
  311. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/builder.py +0 -0
  312. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/context.py +0 -0
  313. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/fan_out.py +0 -0
  314. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/incremental.py +0 -0
  315. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/mixins.py +0 -0
  316. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/run.py +0 -0
  317. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/saga/__init__.py +0 -0
  318. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/saga/context.py +0 -0
  319. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/saga/orchestrator.py +0 -0
  320. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/tracker/__init__.py +0 -0
  321. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/tracker/dag.py +0 -0
  322. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/tracker/event_routing.py +0 -0
  323. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/tracker/fan_out.py +0 -0
  324. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/tracker/finalization.py +0 -0
  325. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/tracker/gates.py +0 -0
  326. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/tracker/sub_workflows.py +0 -0
  327. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/tracker/tracker.py +0 -0
  328. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/tracker/types.py +0 -0
  329. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/types.py +0 -0
  330. {taskito-0.16.1 → taskito-0.16.2}/py_src/taskito/workflows/visualization.py +0 -0
@@ -112,9 +112,9 @@ checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
112
112
 
113
113
  [[package]]
114
114
  name = "cc"
115
- version = "1.2.63"
115
+ version = "1.2.64"
116
116
  source = "registry+https://github.com/rust-lang/crates.io-index"
117
- checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f"
117
+ checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f"
118
118
  dependencies = [
119
119
  "find-msvc-tools",
120
120
  "shlex",
@@ -676,9 +676,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
676
676
 
677
677
  [[package]]
678
678
  name = "js-sys"
679
- version = "0.3.100"
679
+ version = "0.3.102"
680
680
  source = "registry+https://github.com/rust-lang/crates.io-index"
681
- checksum = "f2025f20d7a4fa7785846e7b63d10a76d3f1cee98ee5cb79ea59703f95e42162"
681
+ checksum = "03d04c30968dffe80775bd4d7fb676131cd04a1fb46d2686dbffbaec2d9dfd31"
682
682
  dependencies = [
683
683
  "cfg-if",
684
684
  "futures-util",
@@ -821,9 +821,9 @@ dependencies = [
821
821
 
822
822
  [[package]]
823
823
  name = "openssl-sys"
824
- version = "0.9.116"
824
+ version = "0.9.117"
825
825
  source = "registry+https://github.com/rust-lang/crates.io-index"
826
- checksum = "f28a22dc7140cda5f096e5e7724a6962ca81a7f8bfd2979f9b18c11af56318c4"
826
+ checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695"
827
827
  dependencies = [
828
828
  "cc",
829
829
  "libc",
@@ -1403,7 +1403,7 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
1403
1403
 
1404
1404
  [[package]]
1405
1405
  name = "taskito-async"
1406
- version = "0.16.1"
1406
+ version = "0.16.2"
1407
1407
  dependencies = [
1408
1408
  "async-trait",
1409
1409
  "crossbeam-channel",
@@ -1415,7 +1415,7 @@ dependencies = [
1415
1415
 
1416
1416
  [[package]]
1417
1417
  name = "taskito-core"
1418
- version = "0.16.1"
1418
+ version = "0.16.2"
1419
1419
  dependencies = [
1420
1420
  "async-trait",
1421
1421
  "chrono",
@@ -1439,7 +1439,7 @@ dependencies = [
1439
1439
 
1440
1440
  [[package]]
1441
1441
  name = "taskito-mesh"
1442
- version = "0.16.1"
1442
+ version = "0.16.2"
1443
1443
  dependencies = [
1444
1444
  "base64",
1445
1445
  "bincode",
@@ -1454,7 +1454,7 @@ dependencies = [
1454
1454
 
1455
1455
  [[package]]
1456
1456
  name = "taskito-python"
1457
- version = "0.16.1"
1457
+ version = "0.16.2"
1458
1458
  dependencies = [
1459
1459
  "async-trait",
1460
1460
  "base64",
@@ -1475,7 +1475,7 @@ dependencies = [
1475
1475
 
1476
1476
  [[package]]
1477
1477
  name = "taskito-workflows"
1478
- version = "0.16.1"
1478
+ version = "0.16.2"
1479
1479
  dependencies = [
1480
1480
  "dagron-core",
1481
1481
  "diesel",
@@ -1656,9 +1656,9 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
1656
1656
 
1657
1657
  [[package]]
1658
1658
  name = "wasip2"
1659
- version = "1.0.3+wasi-0.2.9"
1659
+ version = "1.0.4+wasi-0.2.12"
1660
1660
  source = "registry+https://github.com/rust-lang/crates.io-index"
1661
- checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"
1661
+ checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
1662
1662
  dependencies = [
1663
1663
  "wit-bindgen 0.57.1",
1664
1664
  ]
@@ -1674,9 +1674,9 @@ dependencies = [
1674
1674
 
1675
1675
  [[package]]
1676
1676
  name = "wasm-bindgen"
1677
- version = "0.2.123"
1677
+ version = "0.2.125"
1678
1678
  source = "registry+https://github.com/rust-lang/crates.io-index"
1679
- checksum = "a254a4b10c19a76f09a27640e7ffbf9bc30bf67e16a3bf28aaefa4920fe81563"
1679
+ checksum = "8ddb3f79143bced6de84270411622a2699cee572fc0875aeaf1e7867cf9fca1a"
1680
1680
  dependencies = [
1681
1681
  "cfg-if",
1682
1682
  "once_cell",
@@ -1687,9 +1687,9 @@ dependencies = [
1687
1687
 
1688
1688
  [[package]]
1689
1689
  name = "wasm-bindgen-macro"
1690
- version = "0.2.123"
1690
+ version = "0.2.125"
1691
1691
  source = "registry+https://github.com/rust-lang/crates.io-index"
1692
- checksum = "24a40fc75b0ec6f3746ceb10d36f53a93dcd68a93b11b6445983945d79eba0dc"
1692
+ checksum = "4e21a184b13fb19e157296e2c46056aec9092264fab83e4ba59e68c61b323c3d"
1693
1693
  dependencies = [
1694
1694
  "quote",
1695
1695
  "wasm-bindgen-macro-support",
@@ -1697,9 +1697,9 @@ dependencies = [
1697
1697
 
1698
1698
  [[package]]
1699
1699
  name = "wasm-bindgen-macro-support"
1700
- version = "0.2.123"
1700
+ version = "0.2.125"
1701
1701
  source = "registry+https://github.com/rust-lang/crates.io-index"
1702
- checksum = "908f34bd9b9ce3d4caf07b72dfab63d61504d156856c6bd3cd87fa350cf3985b"
1702
+ checksum = "fecefd9c35bd935a20fc3fc344b5f29138961e4f47fb03297d88f2587afb5ebd"
1703
1703
  dependencies = [
1704
1704
  "bumpalo",
1705
1705
  "proc-macro2",
@@ -1710,9 +1710,9 @@ dependencies = [
1710
1710
 
1711
1711
  [[package]]
1712
1712
  name = "wasm-bindgen-shared"
1713
- version = "0.2.123"
1713
+ version = "0.2.125"
1714
1714
  source = "registry+https://github.com/rust-lang/crates.io-index"
1715
- checksum = "7acbf7616c27b194bbb550bf77ed0c2c3e5b7fd1260a93082b95fb7f47959b92"
1715
+ checksum = "23939e44bb9a5d7576fa2b563dc2e136628f1224e88a8deed09e04858b77871f"
1716
1716
  dependencies = [
1717
1717
  "unicode-ident",
1718
1718
  ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: taskito
3
- Version: 0.16.1
3
+ Version: 0.16.2
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "taskito-core"
3
- version = "0.16.1"
3
+ version = "0.16.2"
4
4
  edition = "2021"
5
5
 
6
6
  [features]
@@ -32,3 +32,7 @@ redis = { workspace = true, optional = true }
32
32
 
33
33
  [dev-dependencies]
34
34
  tempfile = "3"
35
+ # Raw connection access in the Redis contract tests, to set up race-window
36
+ # state and assert on internal index keys. Only used by `#[cfg(feature = "redis")]`
37
+ # tests; harmless when the feature is off.
38
+ redis = { workspace = true }
@@ -127,7 +127,7 @@ impl Scheduler {
127
127
  // If we exceed the cap, roll back: clear the claim row and reset
128
128
  // status to `Pending` so the job can be dispatched again later.
129
129
  if !self.check_post_claim_concurrency(&job)? {
130
- self.rollback_claim_and_retry(&job.id, now + CONCURRENCY_RETRY_DELAY_MS)?;
130
+ self.rollback_claim_and_reschedule(&job.id, now + CONCURRENCY_RETRY_DELAY_MS)?;
131
131
  return Ok(false);
132
132
  }
133
133
 
@@ -140,14 +140,20 @@ impl Scheduler {
140
140
  Ok(()) => Ok(true),
141
141
  Err(TrySendError::Full(_)) => {
142
142
  warn!("worker channel full; rescheduling job {job_id} (worker pool is behind)",);
143
- self.rollback_claim_and_retry(&job_id, now + CHANNEL_BACKPRESSURE_RETRY_DELAY_MS)?;
143
+ self.rollback_claim_and_reschedule(
144
+ &job_id,
145
+ now + CHANNEL_BACKPRESSURE_RETRY_DELAY_MS,
146
+ )?;
144
147
  Ok(false)
145
148
  }
146
149
  Err(TrySendError::Closed(_)) => {
147
150
  warn!(
148
151
  "worker channel closed; rescheduling job {job_id} (worker pool shutting down)",
149
152
  );
150
- self.rollback_claim_and_retry(&job_id, now + CHANNEL_BACKPRESSURE_RETRY_DELAY_MS)?;
153
+ self.rollback_claim_and_reschedule(
154
+ &job_id,
155
+ now + CHANNEL_BACKPRESSURE_RETRY_DELAY_MS,
156
+ )?;
151
157
  Ok(false)
152
158
  }
153
159
  }
@@ -193,7 +199,7 @@ impl Scheduler {
193
199
  let key = format!("queue:{}", job.queue);
194
200
  if !self.rate_limiter.try_acquire(&key, rl_config)? {
195
201
  self.storage
196
- .retry(&job.id, now + RATE_LIMIT_RETRY_DELAY_MS)?;
202
+ .reschedule(&job.id, now + RATE_LIMIT_RETRY_DELAY_MS)?;
197
203
  return Ok(false);
198
204
  }
199
205
  }
@@ -202,14 +208,14 @@ impl Scheduler {
202
208
  if let Some(config) = self.task_configs.get(&job.task_name) {
203
209
  if config.circuit_breaker.is_some() && !self.circuit_breaker.allow(&job.task_name)? {
204
210
  self.storage
205
- .retry(&job.id, now + CIRCUIT_BREAKER_RETRY_DELAY_MS)?;
211
+ .reschedule(&job.id, now + CIRCUIT_BREAKER_RETRY_DELAY_MS)?;
206
212
  return Ok(false);
207
213
  }
208
214
 
209
215
  if let Some(ref rl_config) = config.rate_limit {
210
216
  if !self.rate_limiter.try_acquire(&job.task_name, rl_config)? {
211
217
  self.storage
212
- .retry(&job.id, now + RATE_LIMIT_RETRY_DELAY_MS)?;
218
+ .reschedule(&job.id, now + RATE_LIMIT_RETRY_DELAY_MS)?;
213
219
  return Ok(false);
214
220
  }
215
221
  }
@@ -265,11 +271,12 @@ impl Scheduler {
265
271
 
266
272
  /// Reverse a successful `claim_execution` and reschedule the job. Used
267
273
  /// when a post-claim gate rejects the job after the claim row has
268
- /// already been written.
269
- fn rollback_claim_and_retry(&self, job_id: &str, next_at: i64) -> Result<()> {
274
+ /// already been written. Uses `reschedule` (not `retry`) so a job that
275
+ /// never executed does not lose retry budget.
276
+ fn rollback_claim_and_reschedule(&self, job_id: &str, next_at: i64) -> Result<()> {
270
277
  if let Err(e) = self.storage.complete_execution(job_id) {
271
278
  warn!("failed to clear execution claim during rollback for job {job_id}: {e}");
272
279
  }
273
- self.storage.retry(job_id, next_at)
280
+ self.storage.reschedule(job_id, next_at)
274
281
  }
275
282
  }
@@ -705,6 +705,31 @@ macro_rules! impl_diesel_job_ops {
705
705
  Ok(())
706
706
  }
707
707
 
708
+ /// Re-schedule a job back to `Pending` without touching
709
+ /// `retry_count`. Mirrors [`retry`](Self::retry) for soft-gate
710
+ /// reschedules (rate limit, circuit breaker, concurrency cap,
711
+ /// backpressure) where the job never executed, so its retry
712
+ /// budget must be preserved.
713
+ pub fn reschedule(&self, id: &str, next_scheduled_at: i64) -> Result<()> {
714
+ let mut conn = self.conn()?;
715
+
716
+ let affected = diesel::update(jobs::table)
717
+ .filter(jobs::id.eq(id))
718
+ .set((
719
+ jobs::status.eq(JobStatus::Pending as i32),
720
+ jobs::scheduled_at.eq(next_scheduled_at),
721
+ jobs::started_at.eq(None::<i64>),
722
+ jobs::completed_at.eq(None::<i64>),
723
+ jobs::error.eq(None::<String>),
724
+ ))
725
+ .execute(&mut conn)?;
726
+
727
+ if affected == 0 {
728
+ return Err(QueueError::JobNotFound(id.to_string()));
729
+ }
730
+ Ok(())
731
+ }
732
+
708
733
  /// Cancel a pending job and cascade-cancel its dependents. The
709
734
  /// cancelled job moves from `jobs` into `archived_jobs`.
710
735
  pub fn cancel_job(&self, id: &str) -> Result<bool> {
@@ -152,6 +152,9 @@ macro_rules! impl_storage {
152
152
  fn retry(&self, id: &str, next_scheduled_at: i64) -> $crate::error::Result<()> {
153
153
  self.retry(id, next_scheduled_at)
154
154
  }
155
+ fn reschedule(&self, id: &str, next_scheduled_at: i64) -> $crate::error::Result<()> {
156
+ self.reschedule(id, next_scheduled_at)
157
+ }
155
158
  fn cancel_job(&self, id: &str) -> $crate::error::Result<bool> {
156
159
  self.cancel_job(id)
157
160
  }
@@ -679,6 +682,9 @@ impl Storage for StorageBackend {
679
682
  fn retry(&self, id: &str, next_scheduled_at: i64) -> Result<()> {
680
683
  delegate!(self, retry, id, next_scheduled_at)
681
684
  }
685
+ fn reschedule(&self, id: &str, next_scheduled_at: i64) -> Result<()> {
686
+ delegate!(self, reschedule, id, next_scheduled_at)
687
+ }
682
688
  fn cancel_job(&self, id: &str) -> Result<bool> {
683
689
  delegate!(self, cancel_job, id)
684
690
  }
@@ -89,22 +89,38 @@ impl RedisStorage {
89
89
  let dlq_key = self.key(&["dlq", &dlq_id]);
90
90
  let dlq_all = self.key(&["dlq", "all"]);
91
91
 
92
- let pipe = &mut redis::pipe();
93
- pipe.set(&dlq_key, &json);
94
- pipe.zadd(&dlq_all, &dlq_id, now as f64);
95
- pipe.query::<()>(&mut conn).map_err(map_err)?;
96
-
97
- // Archive the now-Dead job out of the live indices.
98
92
  let mut dead_job = job.clone();
99
93
  let old_status = dead_job.status;
100
94
  dead_job.status = JobStatus::Dead;
101
95
  dead_job.error = Some(error.to_string());
102
96
  dead_job.completed_at = Some(now);
103
- self.archive_job_immediately(&mut conn, &dead_job, old_status)?;
97
+ let dead_json =
98
+ serde_json::to_string(&dead_job).map_err(|e| QueueError::Other(e.to_string()))?;
99
+
100
+ // Commit the DLQ entry and the live→archive move together, but only if the
101
+ // job is still live in its expected state. A racing complete/fail or the
102
+ // stale-job reaper may have archived it first; WATCH aborts the EXEC if
103
+ // `job:<id>` changes between the liveness check and the commit, so we never
104
+ // create a duplicate DLQ entry or overwrite a terminal archive.
105
+ let job_live_key = self.key(&["job", &job.id]);
106
+ let dead_lettered: bool =
107
+ redis::transaction(&mut conn, &[job_live_key.as_str()], |conn, pipe| {
108
+ if !conn.exists::<_, bool>(&job_live_key)? {
109
+ return Ok(Some(false));
110
+ }
111
+ pipe.set(&dlq_key, &json).ignore();
112
+ pipe.zadd(&dlq_all, &dlq_id, now as f64).ignore();
113
+ self.push_archive_ops(pipe, &dead_job, old_status, &dead_json);
114
+ Ok(pipe.query::<Option<()>>(conn)?.map(|()| true))
115
+ })
116
+ .map_err(map_err)?;
104
117
 
105
- // Cascade cancel dependents
118
+ // Cascade-cancel dependents only if we actually dead-lettered the job
119
+ // (skipped when a racer had already archived it).
106
120
  drop(conn);
107
- self.cascade_cancel(&job.id, "dependency failed")?;
121
+ if dead_lettered {
122
+ self.cascade_cancel(&job.id, "dependency failed")?;
123
+ }
108
124
 
109
125
  Ok(())
110
126
  }
@@ -6,7 +6,54 @@ use crate::error::{QueueError, Result};
6
6
  use crate::job::{Job, JobStatus};
7
7
  use crate::storage::redis_backend::{map_err, RedisStorage};
8
8
 
9
+ /// Lua: claim a candidate by flipping it Pending→Running, but only if it is
10
+ /// still a member of the pending status set (`jobs:status:0`). This is the
11
+ /// Redis equivalent of the Diesel `UPDATE ... WHERE status = Pending`
12
+ /// affected-row guard: a concurrent cancel/expire that already archived the
13
+ /// job has removed it from `jobs:status:0`, so the claim is refused (returns 0)
14
+ /// instead of resurrecting the job as a Running orphan. Redis runs the script
15
+ /// atomically, which also closes the double-claim window between schedulers.
16
+ ///
17
+ /// KEYS: job_key, pending_status_set, running_status_set, pending_zset
18
+ /// ARGV: job_id, running_json
19
+ const CLAIM_JOB_SCRIPT: &str = r#"
20
+ if redis.call('SISMEMBER', KEYS[2], ARGV[1]) == 0 then return 0 end
21
+ redis.call('SET', KEYS[1], ARGV[2])
22
+ redis.call('SREM', KEYS[2], ARGV[1])
23
+ redis.call('SADD', KEYS[3], ARGV[1])
24
+ redis.call('ZREM', KEYS[4], ARGV[1])
25
+ return 1
26
+ "#;
27
+
9
28
  impl RedisStorage {
29
+ /// Atomically claim a candidate job (Pending→Running) via [`CLAIM_JOB_SCRIPT`].
30
+ /// The caller must have already set `job.status = Running` and `started_at`.
31
+ /// Returns `false` if the job was concurrently cancelled/expired/claimed, so
32
+ /// the dequeue scan should skip it.
33
+ fn claim_pending(
34
+ &self,
35
+ conn: &mut redis::Connection,
36
+ job: &Job,
37
+ queue_key: &str,
38
+ ) -> Result<bool> {
39
+ let job_json = serde_json::to_string(job).map_err(|e| QueueError::Other(e.to_string()))?;
40
+ let job_key = self.key(&["job", &job.id]);
41
+ let pending_status =
42
+ self.key(&["jobs", "status", &(JobStatus::Pending as i32).to_string()]);
43
+ let running_status =
44
+ self.key(&["jobs", "status", &(JobStatus::Running as i32).to_string()]);
45
+ let claimed: i32 = redis::Script::new(CLAIM_JOB_SCRIPT)
46
+ .key(&job_key)
47
+ .key(&pending_status)
48
+ .key(&running_status)
49
+ .key(queue_key)
50
+ .arg(&job.id)
51
+ .arg(&job_json)
52
+ .invoke(conn)
53
+ .map_err(map_err)?;
54
+ Ok(claimed == 1)
55
+ }
56
+
10
57
  pub fn dequeue(
11
58
  &self,
12
59
  queue_name: &str,
@@ -101,14 +148,13 @@ impl RedisStorage {
101
148
  }
102
149
  }
103
150
 
104
- // Claim the job
151
+ // Claim the job atomically; if we lost the race (cancelled / expired
152
+ // / claimed by another scheduler) skip to the next candidate.
105
153
  job.status = JobStatus::Running;
106
154
  job.started_at = Some(now);
107
- self.save_job_and_move_status(&mut conn, &job, JobStatus::Pending)?;
108
- conn.zrem::<_, _, ()>(&queue_key, &job_id)
109
- .map_err(map_err)?;
110
-
111
- return Ok(Some(job));
155
+ if self.claim_pending(&mut conn, &job, &queue_key)? {
156
+ return Ok(Some(job));
157
+ }
112
158
  }
113
159
 
114
160
  Ok(None)
@@ -240,14 +286,13 @@ impl RedisStorage {
240
286
  }
241
287
  }
242
288
 
243
- // Claim the job
289
+ // Claim the job atomically; skip candidates lost to a concurrent
290
+ // cancel / expire / claim instead of resurrecting them.
244
291
  job.status = JobStatus::Running;
245
292
  job.started_at = Some(now);
246
- self.save_job_and_move_status(&mut conn, &job, JobStatus::Pending)?;
247
- conn.zrem::<_, _, ()>(&queue_key, &job_id)
248
- .map_err(map_err)?;
249
-
250
- claimed.push(job);
293
+ if self.claim_pending(&mut conn, &job, &queue_key)? {
294
+ claimed.push(job);
295
+ }
251
296
  }
252
297
 
253
298
  Ok(claimed)
@@ -2,10 +2,23 @@
2
2
 
3
3
  use redis::Commands;
4
4
 
5
+ use super::dequeue_score;
5
6
  use crate::error::{QueueError, Result};
6
7
  use crate::job::{Job, JobStatus};
7
8
  use crate::storage::redis_backend::{map_err, RedisStorage};
8
9
 
10
+ /// Lua: release a unique-key pointer only if it still points at `ARGV[1]`.
11
+ /// A newer job may have reused the same `unique_key` after this job left the
12
+ /// live indices, so an unconditional `DEL` would clobber the new job's dedup
13
+ /// lock. Mirrors `RELEASE_LOCK_SCRIPT` in `locks.rs`.
14
+ const RELEASE_UNIQUE_IF_OWNER: &str = r#"
15
+ if redis.call('GET', KEYS[1]) == ARGV[1] then
16
+ redis.call('DEL', KEYS[1])
17
+ return 1
18
+ end
19
+ return 0
20
+ "#;
21
+
9
22
  impl RedisStorage {
10
23
  pub(in crate::storage::redis_backend) fn load_job(
11
24
  &self,
@@ -74,22 +87,71 @@ impl RedisStorage {
74
87
  Ok(())
75
88
  }
76
89
 
77
- /// Move a terminal job out of the live indices into the archive in a single
78
- /// pipeline. Removes it from `job:<id>`, the live status / by_queue /
79
- /// by_task sets and the `jobs:all` zset, then writes `archived:<id>`, adds
80
- /// it to `archived:status:<n>` and scores it into `archived:all` by
81
- /// completed_at.
90
+ /// Reset a job to `Pending` and (re)insert it into the per-queue pending
91
+ /// zset in a single MULTI/EXEC. Folding the status-set move and the zset
92
+ /// add into one transaction means a crash can no longer strand the job as
93
+ /// `Pending` in the status set but absent from the queue zset (where it
94
+ /// would never be dequeued and never reaped).
82
95
  ///
83
- /// `old_status` is the status the job held in the live `jobs:status:<n>`
84
- /// set; the caller must have already set the job's terminal `status`,
85
- /// `completed_at` (and `error`/`result` as appropriate).
86
- pub(in crate::storage::redis_backend) fn archive_job_immediately(
96
+ /// The caller must have already set the job's `status = Pending`,
97
+ /// `scheduled_at`, and cleared `started_at`/`completed_at`/`error`.
98
+ pub(in crate::storage::redis_backend) fn requeue_pending(
87
99
  &self,
88
100
  conn: &mut redis::Connection,
89
101
  job: &Job,
90
102
  old_status: JobStatus,
91
103
  ) -> Result<()> {
92
104
  let job_json = serde_json::to_string(job).map_err(|e| QueueError::Other(e.to_string()))?;
105
+ let job_key = self.key(&["job", &job.id]);
106
+ let old_status_key = self.key(&["jobs", "status", &(old_status as i32).to_string()]);
107
+ let pending_status_key =
108
+ self.key(&["jobs", "status", &(JobStatus::Pending as i32).to_string()]);
109
+ let queue_key = self.key(&["queue", &job.queue, "pending"]);
110
+ let score = dequeue_score(job.priority, job.scheduled_at);
111
+
112
+ let pipe = &mut redis::pipe();
113
+ pipe.atomic();
114
+ pipe.set(&job_key, &job_json);
115
+ if old_status != JobStatus::Pending {
116
+ pipe.srem(&old_status_key, &job.id);
117
+ pipe.sadd(&pending_status_key, &job.id);
118
+ }
119
+ pipe.zadd(&queue_key, &job.id, score);
120
+ pipe.query::<()>(conn).map_err(map_err)?;
121
+
122
+ Ok(())
123
+ }
124
+
125
+ /// Release a job's unique-key pointer iff it still belongs to this job, via
126
+ /// an atomic compare-and-delete (mirrors `RELEASE_LOCK_SCRIPT`). Safe to
127
+ /// call when a newer job may have reused the same `unique_key`.
128
+ pub(in crate::storage::redis_backend) fn release_unique_key(
129
+ &self,
130
+ conn: &mut redis::Connection,
131
+ unique_key: &str,
132
+ job_id: &str,
133
+ ) -> Result<()> {
134
+ let key = self.key(&["jobs", "unique", unique_key]);
135
+ redis::Script::new(RELEASE_UNIQUE_IF_OWNER)
136
+ .key(&key)
137
+ .arg(job_id)
138
+ .invoke::<i32>(conn)
139
+ .map_err(map_err)?;
140
+ Ok(())
141
+ }
142
+
143
+ /// Append the live→archive command sequence to `pipe` (no MULTI/EXEC of its
144
+ /// own). Removes the job from the live indices and writes the archived row.
145
+ /// Shared by `archive_job_immediately` and `move_to_dlq` so the DLQ write and
146
+ /// the archive can commit in one transaction. The caller must have already
147
+ /// set the terminal `status`/`completed_at` and serialized `job_json`.
148
+ pub(in crate::storage::redis_backend) fn push_archive_ops(
149
+ &self,
150
+ pipe: &mut redis::Pipeline,
151
+ job: &Job,
152
+ old_status: JobStatus,
153
+ job_json: &str,
154
+ ) {
93
155
  let completed_at = job.completed_at.unwrap_or_else(crate::job::now_millis);
94
156
 
95
157
  let job_key = self.key(&["job", &job.id]);
@@ -104,24 +166,38 @@ impl RedisStorage {
104
166
  let archived_by_queue = self.key(&["archived", "by_queue", &job.queue]);
105
167
  let archived_all = self.key(&["archived", "all"]);
106
168
 
107
- // `.atomic()` wraps the live→archive move in MULTI/EXEC so the job is
108
- // never observable in both the live and archived indices at once.
109
- let pipe = &mut redis::pipe();
110
- pipe.atomic();
111
- pipe.del(&job_key);
112
- pipe.srem(&status_key, &job.id);
113
- pipe.srem(&by_queue_key, &job.id);
114
- pipe.srem(&by_task_key, &job.id);
115
- pipe.zrem(&all_key, &job.id);
169
+ // Results are ignored so callers can query the pipe as `()` (or
170
+ // `Option<()>` inside a WATCH transaction).
171
+ pipe.del(&job_key).ignore();
172
+ pipe.srem(&status_key, &job.id).ignore();
173
+ pipe.srem(&by_queue_key, &job.id).ignore();
174
+ pipe.srem(&by_task_key, &job.id).ignore();
175
+ pipe.zrem(&all_key, &job.id).ignore();
116
176
  // Pending jobs still sit in the per-queue pending zset; running jobs
117
177
  // were removed at dequeue, so only remove on a Pending→terminal move.
118
178
  if old_status == JobStatus::Pending {
119
- pipe.zrem(&pending_key, &job.id);
179
+ pipe.zrem(&pending_key, &job.id).ignore();
120
180
  }
121
- pipe.set(&archived_key, &job_json);
122
- pipe.sadd(&archived_status_key, &job.id);
123
- pipe.sadd(&archived_by_queue, &job.id);
124
- pipe.zadd(&archived_all, &job.id, completed_at as f64);
181
+ pipe.set(&archived_key, job_json).ignore();
182
+ pipe.sadd(&archived_status_key, &job.id).ignore();
183
+ pipe.sadd(&archived_by_queue, &job.id).ignore();
184
+ pipe.zadd(&archived_all, &job.id, completed_at as f64)
185
+ .ignore();
186
+ }
187
+
188
+ /// Move a terminal job out of the live indices into the archive in one
189
+ /// atomic pipeline (`.atomic()` MULTI/EXEC), so it is never observable in
190
+ /// both the live and archived indices at once.
191
+ pub(in crate::storage::redis_backend) fn archive_job_immediately(
192
+ &self,
193
+ conn: &mut redis::Connection,
194
+ job: &Job,
195
+ old_status: JobStatus,
196
+ ) -> Result<()> {
197
+ let job_json = serde_json::to_string(job).map_err(|e| QueueError::Other(e.to_string()))?;
198
+ let pipe = &mut redis::pipe();
199
+ pipe.atomic();
200
+ self.push_archive_ops(pipe, job, old_status, &job_json);
125
201
  pipe.query::<()>(conn).map_err(map_err)?;
126
202
 
127
203
  Ok(())
@@ -153,21 +229,15 @@ impl RedisStorage {
153
229
  pipe.del(&errors_key);
154
230
  pipe.del(&deps_key);
155
231
  pipe.del(&dependents_key);
232
+ pipe.query::<()>(conn).map_err(map_err)?;
156
233
 
157
- // Only release the unique-key pointer if it still points at THIS job.
158
- // `enqueue_unique` stores the job id at `jobs:unique:<uk>`; a newer live
159
- // job may have reused the same `unique_key` after this row was archived,
160
- // and deleting the pointer would clobber the new job's lock.
234
+ // Release the unique-key pointer through the atomic compare-and-delete so
235
+ // a `enqueue_unique` that reused the key between a plain GET and DEL can't
236
+ // have its lock clobbered.
161
237
  if let Some(ref uk) = job.unique_key {
162
- let unique_key = self.key(&["jobs", "unique", uk]);
163
- let owner: Option<String> = conn.get(&unique_key).map_err(map_err)?;
164
- if owner.as_deref() == Some(job.id.as_str()) {
165
- pipe.del(&unique_key);
166
- }
238
+ self.release_unique_key(conn, uk, &job.id)?;
167
239
  }
168
240
 
169
- pipe.query::<()>(conn).map_err(map_err)?;
170
-
171
241
  Ok(())
172
242
  }
173
243
  }