taskito 0.9.0__tar.gz → 0.10.0__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 (177) hide show
  1. {taskito-0.9.0 → taskito-0.10.0}/Cargo.lock +3 -3
  2. {taskito-0.9.0 → taskito-0.10.0}/PKG-INFO +6 -6
  3. {taskito-0.9.0 → taskito-0.10.0}/README.md +1 -1
  4. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/Cargo.toml +1 -1
  5. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/scheduler/mod.rs +69 -8
  6. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/scheduler/result_handler.rs +10 -0
  7. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-python/Cargo.toml +1 -1
  8. taskito-0.10.0/crates/taskito-python/src/prefork/dispatch.rs +65 -0
  9. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/__init__.py +1 -1
  10. taskito-0.10.0/py_src/taskito/dashboard.py +404 -0
  11. taskito-0.10.0/py_src/taskito/templates/dashboard.html +233 -0
  12. {taskito-0.9.0 → taskito-0.10.0}/pyproject.toml +5 -5
  13. taskito-0.9.0/crates/taskito-python/src/prefork/dispatch.rs +0 -32
  14. taskito-0.9.0/py_src/taskito/dashboard.py +0 -387
  15. taskito-0.9.0/py_src/taskito/templates/dashboard.css +0 -368
  16. taskito-0.9.0/py_src/taskito/templates/dashboard.html +0 -40
  17. taskito-0.9.0/py_src/taskito/templates/js/actions.js +0 -34
  18. taskito-0.9.0/py_src/taskito/templates/js/app.js +0 -93
  19. taskito-0.9.0/py_src/taskito/templates/js/chart.js +0 -150
  20. taskito-0.9.0/py_src/taskito/templates/js/components.js +0 -58
  21. taskito-0.9.0/py_src/taskito/templates/js/utils.js +0 -19
  22. taskito-0.9.0/py_src/taskito/templates/js/views.js +0 -348
  23. {taskito-0.9.0 → taskito-0.10.0}/Cargo.toml +0 -0
  24. {taskito-0.9.0 → taskito-0.10.0}/LICENSE +0 -0
  25. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/error.rs +0 -0
  26. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/job.rs +0 -0
  27. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/lib.rs +0 -0
  28. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/periodic.rs +0 -0
  29. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/resilience/circuit_breaker.rs +0 -0
  30. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/resilience/dlq.rs +0 -0
  31. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/resilience/mod.rs +0 -0
  32. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/resilience/rate_limiter.rs +0 -0
  33. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/resilience/retry.rs +0 -0
  34. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/scheduler/maintenance.rs +0 -0
  35. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/scheduler/poller.rs +0 -0
  36. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/diesel_common/jobs.rs +0 -0
  37. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/diesel_common/locks.rs +0 -0
  38. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/diesel_common/logs.rs +0 -0
  39. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/diesel_common/metrics.rs +0 -0
  40. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/diesel_common/mod.rs +0 -0
  41. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/mod.rs +0 -0
  42. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/models.rs +0 -0
  43. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/postgres/archival.rs +0 -0
  44. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/postgres/circuit_breakers.rs +0 -0
  45. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/postgres/dead_letter.rs +0 -0
  46. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/postgres/jobs.rs +0 -0
  47. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/postgres/locks.rs +0 -0
  48. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/postgres/logs.rs +0 -0
  49. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/postgres/metrics.rs +0 -0
  50. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/postgres/mod.rs +0 -0
  51. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/postgres/periodic.rs +0 -0
  52. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/postgres/queue_state.rs +0 -0
  53. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/postgres/rate_limits.rs +0 -0
  54. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/postgres/trait_impl.rs +0 -0
  55. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/postgres/workers.rs +0 -0
  56. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/redis_backend/archival.rs +0 -0
  57. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/redis_backend/circuit_breakers.rs +0 -0
  58. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/redis_backend/dead_letter.rs +0 -0
  59. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/redis_backend/jobs.rs +0 -0
  60. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/redis_backend/locks.rs +0 -0
  61. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/redis_backend/logs.rs +0 -0
  62. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/redis_backend/metrics.rs +0 -0
  63. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/redis_backend/mod.rs +0 -0
  64. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/redis_backend/periodic.rs +0 -0
  65. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/redis_backend/queue_state.rs +0 -0
  66. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/redis_backend/rate_limits.rs +0 -0
  67. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/redis_backend/trait_impl.rs +0 -0
  68. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/redis_backend/workers.rs +0 -0
  69. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/schema.rs +0 -0
  70. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/sqlite/archival.rs +0 -0
  71. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/sqlite/circuit_breakers.rs +0 -0
  72. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/sqlite/dead_letter.rs +0 -0
  73. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/sqlite/jobs.rs +0 -0
  74. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/sqlite/locks.rs +0 -0
  75. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/sqlite/logs.rs +0 -0
  76. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/sqlite/metrics.rs +0 -0
  77. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/sqlite/mod.rs +0 -0
  78. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/sqlite/periodic.rs +0 -0
  79. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/sqlite/queue_state.rs +0 -0
  80. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/sqlite/rate_limits.rs +0 -0
  81. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/sqlite/tests.rs +0 -0
  82. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/sqlite/trait_impl.rs +0 -0
  83. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/sqlite/workers.rs +0 -0
  84. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/storage/traits.rs +0 -0
  85. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/src/worker.rs +0 -0
  86. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/tests/rust/storage_tests.rs +0 -0
  87. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-core/tests/rust.rs +0 -0
  88. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-python/src/async_worker.rs +0 -0
  89. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-python/src/lib.rs +0 -0
  90. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-python/src/prefork/child.rs +0 -0
  91. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-python/src/prefork/mod.rs +0 -0
  92. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-python/src/prefork/protocol.rs +0 -0
  93. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-python/src/py_config.rs +0 -0
  94. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-python/src/py_job.rs +0 -0
  95. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-python/src/py_queue/inspection.rs +0 -0
  96. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-python/src/py_queue/mod.rs +0 -0
  97. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-python/src/py_queue/worker.rs +0 -0
  98. {taskito-0.9.0 → taskito-0.10.0}/crates/taskito-python/src/py_worker.rs +0 -0
  99. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/_taskito.pyi +0 -0
  100. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/app.py +0 -0
  101. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/async_support/__init__.py +0 -0
  102. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/async_support/context.py +0 -0
  103. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/async_support/executor.py +0 -0
  104. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/async_support/helpers.py +0 -0
  105. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/async_support/locks.py +0 -0
  106. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/async_support/mixins.py +0 -0
  107. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/async_support/result.py +0 -0
  108. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/canvas.py +0 -0
  109. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/cli.py +0 -0
  110. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/context.py +0 -0
  111. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/contrib/__init__.py +0 -0
  112. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/contrib/django/__init__.py +0 -0
  113. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/contrib/django/admin.py +0 -0
  114. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/contrib/django/apps.py +0 -0
  115. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/contrib/django/management/__init__.py +0 -0
  116. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/contrib/django/management/commands/__init__.py +0 -0
  117. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/contrib/django/management/commands/taskito_dashboard.py +0 -0
  118. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/contrib/django/management/commands/taskito_info.py +0 -0
  119. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/contrib/django/management/commands/taskito_worker.py +0 -0
  120. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/contrib/django/settings.py +0 -0
  121. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/contrib/fastapi.py +0 -0
  122. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/contrib/flask.py +0 -0
  123. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/contrib/otel.py +0 -0
  124. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/contrib/prometheus.py +0 -0
  125. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/contrib/sentry.py +0 -0
  126. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/events.py +0 -0
  127. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/exceptions.py +0 -0
  128. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/health.py +0 -0
  129. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/inject.py +0 -0
  130. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/interception/__init__.py +0 -0
  131. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/interception/built_in.py +0 -0
  132. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/interception/converters.py +0 -0
  133. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/interception/errors.py +0 -0
  134. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/interception/interceptor.py +0 -0
  135. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/interception/metrics.py +0 -0
  136. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/interception/reconstruct.py +0 -0
  137. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/interception/registry.py +0 -0
  138. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/interception/strategy.py +0 -0
  139. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/interception/walker.py +0 -0
  140. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/locks.py +0 -0
  141. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/middleware.py +0 -0
  142. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/mixins.py +0 -0
  143. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/prefork/__init__.py +0 -0
  144. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/prefork/__main__.py +0 -0
  145. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/prefork/child.py +0 -0
  146. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/proxies/__init__.py +0 -0
  147. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/proxies/built_in.py +0 -0
  148. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/proxies/handler.py +0 -0
  149. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/proxies/handlers/__init__.py +0 -0
  150. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/proxies/handlers/boto3_client.py +0 -0
  151. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/proxies/handlers/file.py +0 -0
  152. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/proxies/handlers/gcs_client.py +0 -0
  153. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/proxies/handlers/httpx_client.py +0 -0
  154. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/proxies/handlers/logger.py +0 -0
  155. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/proxies/handlers/requests_session.py +0 -0
  156. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/proxies/metrics.py +0 -0
  157. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/proxies/no_proxy.py +0 -0
  158. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/proxies/reconstruct.py +0 -0
  159. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/proxies/registry.py +0 -0
  160. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/proxies/schema.py +0 -0
  161. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/proxies/signing.py +0 -0
  162. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/py.typed +0 -0
  163. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/resources/__init__.py +0 -0
  164. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/resources/definition.py +0 -0
  165. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/resources/frozen.py +0 -0
  166. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/resources/graph.py +0 -0
  167. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/resources/health.py +0 -0
  168. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/resources/pool.py +0 -0
  169. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/resources/runtime.py +0 -0
  170. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/resources/thread_local.py +0 -0
  171. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/resources/toml_config.py +0 -0
  172. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/result.py +0 -0
  173. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/scaler.py +0 -0
  174. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/serializers.py +0 -0
  175. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/task.py +0 -0
  176. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/testing.py +0 -0
  177. {taskito-0.9.0 → taskito-0.10.0}/py_src/taskito/webhooks.py +0 -0
@@ -1217,7 +1217,7 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
1217
1217
 
1218
1218
  [[package]]
1219
1219
  name = "taskito-async"
1220
- version = "0.9.0"
1220
+ version = "0.10.0"
1221
1221
  dependencies = [
1222
1222
  "async-trait",
1223
1223
  "crossbeam-channel",
@@ -1229,7 +1229,7 @@ dependencies = [
1229
1229
 
1230
1230
  [[package]]
1231
1231
  name = "taskito-core"
1232
- version = "0.9.0"
1232
+ version = "0.10.0"
1233
1233
  dependencies = [
1234
1234
  "async-trait",
1235
1235
  "chrono",
@@ -1253,7 +1253,7 @@ dependencies = [
1253
1253
 
1254
1254
  [[package]]
1255
1255
  name = "taskito-python"
1256
- version = "0.9.0"
1256
+ version = "0.10.0"
1257
1257
  dependencies = [
1258
1258
  "async-trait",
1259
1259
  "base64",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: taskito
3
- Version: 0.9.0
3
+ Version: 0.10.0
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -49,17 +49,17 @@ License-File: LICENSE
49
49
  Summary: Rust-powered task queue for Python. No broker required.
50
50
  Requires-Python: >=3.10
51
51
  Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
52
- Project-URL: Changelog, https://github.com/pratyush618/taskito/blob/master/docs/changelog.md
52
+ Project-URL: Changelog, https://github.com/ByteVeda/taskito/blob/master/docs/changelog.md
53
53
  Project-URL: Documentation, https://taskito.grigori.in
54
- Project-URL: Homepage, https://github.com/pratyush618/taskito
55
- Project-URL: Issues, https://github.com/pratyush618/taskito/issues
56
- Project-URL: Repository, https://github.com/pratyush618/taskito
54
+ Project-URL: Homepage, https://github.com/ByteVeda/taskito
55
+ Project-URL: Issues, https://github.com/ByteVeda/taskito/issues
56
+ Project-URL: Repository, https://github.com/ByteVeda/taskito
57
57
 
58
58
  # taskito
59
59
 
60
60
  [![PyPI version](https://img.shields.io/pypi/v/taskito.svg)](https://pypi.org/project/taskito/)
61
61
  [![Python versions](https://img.shields.io/pypi/pyversions/taskito.svg)](https://pypi.org/project/taskito/)
62
- [![License](https://img.shields.io/pypi/l/taskito.svg)](https://github.com/pratyush618/taskito/blob/master/LICENSE)
62
+ [![License](https://img.shields.io/pypi/l/taskito.svg)](https://github.com/ByteVeda/taskito/blob/master/LICENSE)
63
63
 
64
64
  A Rust-powered task queue for Python. No broker required — just SQLite or Postgres.
65
65
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![PyPI version](https://img.shields.io/pypi/v/taskito.svg)](https://pypi.org/project/taskito/)
4
4
  [![Python versions](https://img.shields.io/pypi/pyversions/taskito.svg)](https://pypi.org/project/taskito/)
5
- [![License](https://img.shields.io/pypi/l/taskito.svg)](https://github.com/pratyush618/taskito/blob/master/LICENSE)
5
+ [![License](https://img.shields.io/pypi/l/taskito.svg)](https://github.com/ByteVeda/taskito/blob/master/LICENSE)
6
6
 
7
7
  A Rust-powered task queue for Python. No broker required — just SQLite or Postgres.
8
8
 
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "taskito-core"
3
- version = "0.9.0"
3
+ version = "0.10.0"
4
4
  edition = "2021"
5
5
 
6
6
  [features]
@@ -22,6 +22,9 @@ pub use crate::job::Job;
22
22
  pub struct SchedulerConfig {
23
23
  /// Interval between scheduler poll cycles.
24
24
  pub poll_interval: Duration,
25
+ /// Priority boost per second of wait time. `None` disables aging.
26
+ /// Example: `Some(1)` boosts priority by 1 per second of wait.
27
+ pub aging_factor: Option<i64>,
25
28
  /// Reap stale jobs every N iterations.
26
29
  pub reap_interval: u32,
27
30
  /// Check periodic tasks every N iterations.
@@ -36,6 +39,7 @@ impl Default for SchedulerConfig {
36
39
  fn default() -> Self {
37
40
  Self {
38
41
  poll_interval: Duration::from_millis(50),
42
+ aging_factor: None,
39
43
  reap_interval: 100,
40
44
  periodic_check_interval: 60,
41
45
  cleanup_interval: 1200,
@@ -116,6 +120,34 @@ pub struct QueueConfig {
116
120
  pub max_concurrent: Option<i32>,
117
121
  }
118
122
 
123
+ /// In-memory cache of average task execution duration.
124
+ /// Updated on every `handle_result()` — no DB queries needed.
125
+ struct TaskDurationCache {
126
+ durations: HashMap<String, (u64, i64)>, // (count, sum_ns)
127
+ }
128
+
129
+ impl TaskDurationCache {
130
+ fn new() -> Self {
131
+ Self {
132
+ durations: HashMap::new(),
133
+ }
134
+ }
135
+
136
+ fn record(&mut self, task_name: &str, wall_time_ns: i64) {
137
+ let entry = self.durations.entry(task_name.to_string()).or_default();
138
+ entry.0 += 1;
139
+ entry.1 = entry.1.saturating_add(wall_time_ns);
140
+ }
141
+
142
+ #[allow(dead_code)]
143
+ fn avg_ns(&self, task_name: &str) -> Option<i64> {
144
+ self.durations
145
+ .get(task_name)
146
+ .filter(|(count, _)| *count > 0)
147
+ .map(|(count, sum)| sum / *count as i64)
148
+ }
149
+ }
150
+
119
151
  /// The central scheduler that coordinates job dispatch, retries, rate limiting, and circuit breakers.
120
152
  pub struct Scheduler {
121
153
  storage: StorageBackend,
@@ -129,6 +161,7 @@ pub struct Scheduler {
129
161
  shutdown: Arc<Notify>,
130
162
  paused_cache: Mutex<(HashSet<String>, Instant)>,
131
163
  namespace: Option<String>,
164
+ duration_cache: Mutex<TaskDurationCache>,
132
165
  }
133
166
 
134
167
  /// Counters for tick-based scheduling of periodic maintenance tasks.
@@ -162,6 +195,7 @@ impl Scheduler {
162
195
  shutdown: Arc::new(Notify::new()),
163
196
  paused_cache: Mutex::new((HashSet::new(), Instant::now())),
164
197
  namespace,
198
+ duration_cache: Mutex::new(TaskDurationCache::new()),
165
199
  }
166
200
  }
167
201
 
@@ -192,24 +226,44 @@ impl Scheduler {
192
226
 
193
227
  /// Run the scheduler loop. Polls for ready jobs and dispatches them
194
228
  /// to the worker pool via the provided channel.
229
+ ///
230
+ /// Uses adaptive polling: starts at `poll_interval`, backs off
231
+ /// exponentially (up to 1s) when no jobs are found, resets immediately
232
+ /// when a job is dispatched.
195
233
  pub async fn run(&self, job_tx: tokio::sync::mpsc::Sender<Job>) {
196
234
  let mut counters = TickCounters::default();
235
+ let base_interval = self.config.poll_interval;
236
+ let max_interval = Duration::from_millis(200);
237
+ let mut current_interval = base_interval;
197
238
 
198
239
  loop {
199
240
  tokio::select! {
200
241
  _ = self.shutdown.notified() => break,
201
- _ = tokio::time::sleep(self.config.poll_interval) => {}
242
+ _ = tokio::time::sleep(current_interval) => {}
202
243
  }
203
244
 
204
- self.tick(&job_tx, &mut counters);
245
+ let had_work = self.tick(&job_tx, &mut counters);
246
+ if had_work {
247
+ current_interval = base_interval;
248
+ } else {
249
+ current_interval = (current_interval * 2).min(max_interval);
250
+ }
205
251
  }
206
252
  }
207
253
 
208
254
  /// Execute one iteration of the scheduler loop.
209
- fn tick(&self, job_tx: &tokio::sync::mpsc::Sender<Job>, counters: &mut TickCounters) {
210
- if let Err(e) = self.try_dispatch(job_tx) {
211
- error!("scheduler error: {e}");
212
- }
255
+ /// Returns true if any work was done (job dispatched or periodic task enqueued),
256
+ /// which resets the adaptive poll interval.
257
+ fn tick(&self, job_tx: &tokio::sync::mpsc::Sender<Job>, counters: &mut TickCounters) -> bool {
258
+ let dispatched = match self.try_dispatch(job_tx) {
259
+ Ok(d) => d,
260
+ Err(e) => {
261
+ error!("scheduler error: {e}");
262
+ false
263
+ }
264
+ };
265
+
266
+ let mut had_maintenance = false;
213
267
 
214
268
  counters.reap += 1;
215
269
  counters.periodic += 1;
@@ -225,8 +279,13 @@ impl Scheduler {
225
279
  .periodic
226
280
  .is_multiple_of(self.config.periodic_check_interval)
227
281
  {
228
- if let Err(e) = self.check_periodic() {
229
- error!("periodic check error: {e}");
282
+ match self.check_periodic() {
283
+ Ok(()) => {
284
+ // Periodic tasks may have been enqueued — reset polling
285
+ // so the next tick picks them up quickly.
286
+ had_maintenance = true;
287
+ }
288
+ Err(e) => error!("periodic check error: {e}"),
230
289
  }
231
290
  }
232
291
 
@@ -238,6 +297,8 @@ impl Scheduler {
238
297
  error!("auto-cleanup error: {e}");
239
298
  }
240
299
  }
300
+
301
+ dispatched || had_maintenance
241
302
  }
242
303
  }
243
304
 
@@ -36,6 +36,11 @@ impl Scheduler {
36
36
  error!("circuit breaker error for {task_name}: {e}");
37
37
  }
38
38
 
39
+ // Update in-memory duration cache for smart scheduling
40
+ if let Ok(mut cache) = self.duration_cache.lock() {
41
+ cache.record(task_name, wall_time_ns);
42
+ }
43
+
39
44
  Ok(ResultOutcome::Success {
40
45
  job_id,
41
46
  task_name: task_name.clone(),
@@ -71,6 +76,11 @@ impl Scheduler {
71
76
  log::error!("circuit breaker error for {task_name}: {e}");
72
77
  }
73
78
 
79
+ // Update in-memory duration cache for smart scheduling
80
+ if let Ok(mut cache) = self.duration_cache.lock() {
81
+ cache.record(&task_name, wall_time_ns);
82
+ }
83
+
74
84
  // Look up the job to get the queue name for middleware context
75
85
  let queue = self
76
86
  .storage
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "taskito-python"
3
- version = "0.9.0"
3
+ version = "0.10.0"
4
4
  edition = "2021"
5
5
 
6
6
  [features]
@@ -0,0 +1,65 @@
1
+ //! Job dispatch strategies for distributing work across child processes.
2
+
3
+ /// Selects the child with the fewest in-flight jobs (least-loaded).
4
+ /// Falls back to round-robin if all children have equal load.
5
+ pub fn least_loaded(in_flight_counts: &[u32]) -> usize {
6
+ in_flight_counts
7
+ .iter()
8
+ .enumerate()
9
+ .min_by_key(|(_, &count)| count)
10
+ .map(|(idx, _)| idx)
11
+ .unwrap_or(0)
12
+ }
13
+
14
+ /// Selects the child with the lowest weighted load.
15
+ ///
16
+ /// Score = in_flight_count * avg_task_duration_ns. A worker with 1 slow job
17
+ /// scores higher than one with 3 fast jobs, enabling better load distribution
18
+ /// across heterogeneous workloads.
19
+ ///
20
+ /// Falls back to `least_loaded` when `avg_duration_ns` is 0.
21
+ #[allow(dead_code)]
22
+ pub fn weighted_least_loaded(in_flight_counts: &[u32], avg_duration_ns: i64) -> usize {
23
+ if avg_duration_ns <= 0 {
24
+ return least_loaded(in_flight_counts);
25
+ }
26
+ in_flight_counts
27
+ .iter()
28
+ .enumerate()
29
+ .min_by_key(|(_, &count)| count as i64 * avg_duration_ns)
30
+ .map(|(idx, _)| idx)
31
+ .unwrap_or(0)
32
+ }
33
+
34
+ #[cfg(test)]
35
+ mod tests {
36
+ use super::*;
37
+
38
+ #[test]
39
+ fn test_least_loaded_picks_idle() {
40
+ assert_eq!(least_loaded(&[3, 0, 2]), 1);
41
+ }
42
+
43
+ #[test]
44
+ fn test_least_loaded_picks_first_on_tie() {
45
+ assert_eq!(least_loaded(&[1, 1, 1]), 0);
46
+ }
47
+
48
+ #[test]
49
+ fn test_least_loaded_single() {
50
+ assert_eq!(least_loaded(&[5]), 0);
51
+ }
52
+
53
+ #[test]
54
+ fn test_weighted_picks_lowest_score() {
55
+ // Worker 0: 2 in-flight * 100ns = 200
56
+ // Worker 1: 1 in-flight * 100ns = 100 ← pick this
57
+ // Worker 2: 3 in-flight * 100ns = 300
58
+ assert_eq!(weighted_least_loaded(&[2, 1, 3], 100), 1);
59
+ }
60
+
61
+ #[test]
62
+ fn test_weighted_falls_back_on_zero_duration() {
63
+ assert_eq!(weighted_least_loaded(&[3, 0, 2], 0), 1); // same as least_loaded
64
+ }
65
+ }
@@ -99,4 +99,4 @@ try:
99
99
 
100
100
  __version__ = _get_version("taskito")
101
101
  except PackageNotFoundError:
102
- __version__ = "0.9.0"
102
+ __version__ = "0.10.0"