taskito 0.7.0__tar.gz → 0.8.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.
- {taskito-0.7.0 → taskito-0.8.0}/Cargo.lock +3 -3
- {taskito-0.7.0 → taskito-0.8.0}/PKG-INFO +1 -1
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/Cargo.toml +1 -1
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/scheduler/maintenance.rs +1 -1
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/scheduler/mod.rs +15 -6
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/scheduler/poller.rs +4 -1
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/diesel_common/jobs.rs +27 -5
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/mod.rs +24 -9
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/models.rs +3 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/postgres/archival.rs +1 -1
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/postgres/dead_letter.rs +2 -1
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/postgres/mod.rs +10 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/redis_backend/dead_letter.rs +5 -1
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/redis_backend/jobs.rs +39 -3
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/schema.rs +2 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/sqlite/archival.rs +1 -1
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/sqlite/dead_letter.rs +2 -1
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/sqlite/mod.rs +10 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/sqlite/tests.rs +29 -17
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/traits.rs +9 -2
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/tests/rust/storage_tests.rs +6 -6
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-python/Cargo.toml +1 -1
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-python/src/py_job.rs +3 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-python/src/py_queue/inspection.rs +6 -3
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-python/src/py_queue/mod.rs +6 -3
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-python/src/py_queue/worker.rs +6 -1
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/__init__.py +1 -1
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/_taskito.pyi +4 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/app.py +3 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/mixins.py +19 -2
- {taskito-0.7.0 → taskito-0.8.0}/pyproject.toml +1 -1
- {taskito-0.7.0 → taskito-0.8.0}/Cargo.toml +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/LICENSE +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/README.md +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/error.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/job.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/lib.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/periodic.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/resilience/circuit_breaker.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/resilience/dlq.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/resilience/mod.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/resilience/rate_limiter.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/resilience/retry.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/scheduler/result_handler.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/diesel_common/locks.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/diesel_common/logs.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/diesel_common/metrics.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/diesel_common/mod.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/postgres/circuit_breakers.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/postgres/jobs.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/postgres/locks.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/postgres/logs.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/postgres/metrics.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/postgres/periodic.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/postgres/queue_state.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/postgres/rate_limits.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/postgres/trait_impl.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/postgres/workers.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/redis_backend/archival.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/redis_backend/circuit_breakers.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/redis_backend/locks.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/redis_backend/logs.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/redis_backend/metrics.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/redis_backend/mod.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/redis_backend/periodic.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/redis_backend/queue_state.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/redis_backend/rate_limits.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/redis_backend/trait_impl.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/redis_backend/workers.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/sqlite/circuit_breakers.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/sqlite/jobs.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/sqlite/locks.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/sqlite/logs.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/sqlite/metrics.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/sqlite/periodic.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/sqlite/queue_state.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/sqlite/rate_limits.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/sqlite/trait_impl.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/sqlite/workers.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/worker.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/tests/rust.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-python/src/async_worker.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-python/src/lib.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-python/src/py_config.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/crates/taskito-python/src/py_worker.rs +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/async_support/__init__.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/async_support/context.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/async_support/executor.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/async_support/helpers.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/async_support/locks.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/async_support/mixins.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/async_support/result.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/canvas.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/cli.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/context.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/contrib/__init__.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/contrib/django/__init__.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/contrib/django/admin.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/contrib/django/apps.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/contrib/django/management/__init__.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/contrib/django/management/commands/__init__.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/contrib/django/management/commands/taskito_dashboard.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/contrib/django/management/commands/taskito_info.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/contrib/django/management/commands/taskito_worker.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/contrib/django/settings.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/contrib/fastapi.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/contrib/flask.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/contrib/otel.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/contrib/prometheus.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/contrib/sentry.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/dashboard.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/events.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/exceptions.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/health.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/inject.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/interception/__init__.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/interception/built_in.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/interception/converters.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/interception/errors.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/interception/interceptor.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/interception/metrics.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/interception/reconstruct.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/interception/registry.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/interception/strategy.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/interception/walker.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/locks.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/middleware.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/proxies/__init__.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/proxies/built_in.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/proxies/handler.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/proxies/handlers/__init__.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/proxies/handlers/boto3_client.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/proxies/handlers/file.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/proxies/handlers/gcs_client.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/proxies/handlers/httpx_client.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/proxies/handlers/logger.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/proxies/handlers/requests_session.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/proxies/metrics.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/proxies/no_proxy.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/proxies/reconstruct.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/proxies/registry.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/proxies/schema.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/proxies/signing.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/py.typed +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/resources/__init__.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/resources/definition.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/resources/frozen.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/resources/graph.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/resources/health.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/resources/pool.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/resources/runtime.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/resources/thread_local.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/resources/toml_config.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/result.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/scaler.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/serializers.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/task.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/templates/dashboard.css +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/templates/dashboard.html +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/templates/js/actions.js +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/templates/js/app.js +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/templates/js/chart.js +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/templates/js/components.js +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/templates/js/utils.js +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/templates/js/views.js +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/testing.py +0 -0
- {taskito-0.7.0 → taskito-0.8.0}/py_src/taskito/webhooks.py +0 -0
|
@@ -1201,7 +1201,7 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
|
|
1201
1201
|
|
|
1202
1202
|
[[package]]
|
|
1203
1203
|
name = "taskito-async"
|
|
1204
|
-
version = "0.
|
|
1204
|
+
version = "0.8.0"
|
|
1205
1205
|
dependencies = [
|
|
1206
1206
|
"async-trait",
|
|
1207
1207
|
"crossbeam-channel",
|
|
@@ -1213,7 +1213,7 @@ dependencies = [
|
|
|
1213
1213
|
|
|
1214
1214
|
[[package]]
|
|
1215
1215
|
name = "taskito-core"
|
|
1216
|
-
version = "0.
|
|
1216
|
+
version = "0.8.0"
|
|
1217
1217
|
dependencies = [
|
|
1218
1218
|
"async-trait",
|
|
1219
1219
|
"chrono",
|
|
@@ -1237,7 +1237,7 @@ dependencies = [
|
|
|
1237
1237
|
|
|
1238
1238
|
[[package]]
|
|
1239
1239
|
name = "taskito-python"
|
|
1240
|
-
version = "0.
|
|
1240
|
+
version = "0.8.0"
|
|
1241
1241
|
dependencies = [
|
|
1242
1242
|
"async-trait",
|
|
1243
1243
|
"crossbeam-channel",
|
|
@@ -128,6 +128,7 @@ pub struct Scheduler {
|
|
|
128
128
|
config: SchedulerConfig,
|
|
129
129
|
shutdown: Arc<Notify>,
|
|
130
130
|
paused_cache: Mutex<(HashSet<String>, Instant)>,
|
|
131
|
+
namespace: Option<String>,
|
|
131
132
|
}
|
|
132
133
|
|
|
133
134
|
/// Counters for tick-based scheduling of periodic maintenance tasks.
|
|
@@ -139,7 +140,12 @@ struct TickCounters {
|
|
|
139
140
|
}
|
|
140
141
|
|
|
141
142
|
impl Scheduler {
|
|
142
|
-
pub fn new(
|
|
143
|
+
pub fn new(
|
|
144
|
+
storage: StorageBackend,
|
|
145
|
+
queues: Vec<String>,
|
|
146
|
+
config: SchedulerConfig,
|
|
147
|
+
namespace: Option<String>,
|
|
148
|
+
) -> Self {
|
|
143
149
|
let rate_limiter = RateLimiter::new(storage.clone());
|
|
144
150
|
let dlq = DeadLetterQueue::new(storage.clone());
|
|
145
151
|
let circuit_breaker = CircuitBreaker::new(storage.clone());
|
|
@@ -155,6 +161,7 @@ impl Scheduler {
|
|
|
155
161
|
config,
|
|
156
162
|
shutdown: Arc::new(Notify::new()),
|
|
157
163
|
paused_cache: Mutex::new((HashSet::new(), Instant::now())),
|
|
164
|
+
namespace,
|
|
158
165
|
}
|
|
159
166
|
}
|
|
160
167
|
|
|
@@ -249,6 +256,7 @@ mod tests {
|
|
|
249
256
|
storage,
|
|
250
257
|
vec!["default".to_string()],
|
|
251
258
|
SchedulerConfig::default(),
|
|
259
|
+
None,
|
|
252
260
|
)
|
|
253
261
|
}
|
|
254
262
|
|
|
@@ -445,7 +453,7 @@ mod tests {
|
|
|
445
453
|
// The second job should be back in pending with a future scheduled_at
|
|
446
454
|
let jobs = scheduler
|
|
447
455
|
.storage
|
|
448
|
-
.list_jobs(Some(JobStatus::Pending as i32), None, None, 10, 0)
|
|
456
|
+
.list_jobs(Some(JobStatus::Pending as i32), None, None, 10, 0, None)
|
|
449
457
|
.unwrap();
|
|
450
458
|
assert_eq!(jobs.len(), 1);
|
|
451
459
|
assert!(jobs[0].scheduled_at > now_millis());
|
|
@@ -486,7 +494,7 @@ mod tests {
|
|
|
486
494
|
// Job should be rescheduled
|
|
487
495
|
let jobs = scheduler
|
|
488
496
|
.storage
|
|
489
|
-
.list_jobs(Some(JobStatus::Pending as i32), None, None, 10, 0)
|
|
497
|
+
.list_jobs(Some(JobStatus::Pending as i32), None, None, 10, 0, None)
|
|
490
498
|
.unwrap();
|
|
491
499
|
assert_eq!(jobs.len(), 1);
|
|
492
500
|
assert!(jobs[0].scheduled_at > now_millis());
|
|
@@ -562,6 +570,7 @@ mod tests {
|
|
|
562
570
|
Some("periodic_task"),
|
|
563
571
|
10,
|
|
564
572
|
0,
|
|
573
|
+
None,
|
|
565
574
|
)
|
|
566
575
|
.unwrap();
|
|
567
576
|
assert_eq!(jobs.len(), 1);
|
|
@@ -575,13 +584,13 @@ mod tests {
|
|
|
575
584
|
result_ttl_ms: Some(1), // 1ms TTL
|
|
576
585
|
..SchedulerConfig::default()
|
|
577
586
|
};
|
|
578
|
-
let scheduler = Scheduler::new(storage, vec!["default".to_string()], config);
|
|
587
|
+
let scheduler = Scheduler::new(storage, vec!["default".to_string()], config, None);
|
|
579
588
|
|
|
580
589
|
// Enqueue, dequeue, and complete a job
|
|
581
590
|
let job = scheduler.storage.enqueue(make_job("cleanup_task")).unwrap();
|
|
582
591
|
scheduler
|
|
583
592
|
.storage
|
|
584
|
-
.dequeue("default", now_millis() + 1000)
|
|
593
|
+
.dequeue("default", now_millis() + 1000, None)
|
|
585
594
|
.unwrap();
|
|
586
595
|
scheduler.storage.complete(&job.id, Some(vec![1])).unwrap();
|
|
587
596
|
|
|
@@ -605,7 +614,7 @@ mod tests {
|
|
|
605
614
|
cleanup_interval: 1,
|
|
606
615
|
..SchedulerConfig::default()
|
|
607
616
|
};
|
|
608
|
-
let scheduler = Scheduler::new(storage, vec!["default".to_string()], config);
|
|
617
|
+
let scheduler = Scheduler::new(storage, vec!["default".to_string()], config, None);
|
|
609
618
|
|
|
610
619
|
scheduler.storage.enqueue(make_job("tick_task")).unwrap();
|
|
611
620
|
|
|
@@ -51,7 +51,10 @@ impl Scheduler {
|
|
|
51
51
|
return Ok(false);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
let job = match self
|
|
54
|
+
let job = match self
|
|
55
|
+
.storage
|
|
56
|
+
.dequeue_from(&active_queues, now, self.namespace.as_deref())?
|
|
57
|
+
{
|
|
55
58
|
Some(j) => j,
|
|
56
59
|
None => return Ok(false),
|
|
57
60
|
};
|
|
@@ -270,17 +270,27 @@ macro_rules! impl_diesel_job_ops {
|
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
/// Atomically dequeue the highest-priority ready job from the given queue.
|
|
273
|
-
/// Skips expired jobs.
|
|
274
|
-
|
|
273
|
+
/// Skips expired jobs. When `namespace` is `Some`, only jobs in that
|
|
274
|
+
/// namespace are considered; when `None`, only jobs with no namespace.
|
|
275
|
+
pub fn dequeue(&self, queue_name: &str, now: i64, namespace: Option<&str>) -> Result<Option<Job>> {
|
|
275
276
|
let mut conn = self.conn()?;
|
|
276
277
|
|
|
277
278
|
conn.transaction(|conn| {
|
|
278
|
-
let
|
|
279
|
+
let mut query = jobs::table
|
|
279
280
|
.filter(jobs::queue.eq(queue_name))
|
|
280
281
|
.filter(jobs::status.eq(JobStatus::Pending as i32))
|
|
281
282
|
.filter(jobs::scheduled_at.le(now))
|
|
282
283
|
.order((jobs::priority.desc(), jobs::scheduled_at.asc()))
|
|
283
284
|
.limit(100)
|
|
285
|
+
.into_boxed();
|
|
286
|
+
|
|
287
|
+
if let Some(ns) = namespace {
|
|
288
|
+
query = query.filter(jobs::namespace.eq(ns));
|
|
289
|
+
} else {
|
|
290
|
+
query = query.filter(jobs::namespace.is_null());
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
let candidates: Vec<JobRow> = query
|
|
284
294
|
.select(JobRow::as_select())
|
|
285
295
|
.load(conn)?;
|
|
286
296
|
|
|
@@ -327,9 +337,9 @@ macro_rules! impl_diesel_job_ops {
|
|
|
327
337
|
}
|
|
328
338
|
|
|
329
339
|
/// Dequeue from multiple queues, checking each in order.
|
|
330
|
-
pub fn dequeue_from(&self, queues: &[String], now: i64) -> Result<Option<Job>> {
|
|
340
|
+
pub fn dequeue_from(&self, queues: &[String], now: i64, namespace: Option<&str>) -> Result<Option<Job>> {
|
|
331
341
|
for queue_name in queues {
|
|
332
|
-
if let Some(job) = self.dequeue(queue_name, now)? {
|
|
342
|
+
if let Some(job) = self.dequeue(queue_name, now, namespace)? {
|
|
333
343
|
return Ok(Some(job));
|
|
334
344
|
}
|
|
335
345
|
}
|
|
@@ -554,6 +564,8 @@ macro_rules! impl_diesel_job_ops {
|
|
|
554
564
|
}
|
|
555
565
|
|
|
556
566
|
/// List jobs with optional filters and pagination.
|
|
567
|
+
/// When `namespace` is `Some`, only jobs in that namespace are returned.
|
|
568
|
+
/// When `None`, all jobs are returned regardless of namespace.
|
|
557
569
|
pub fn list_jobs(
|
|
558
570
|
&self,
|
|
559
571
|
status: Option<i32>,
|
|
@@ -561,6 +573,7 @@ macro_rules! impl_diesel_job_ops {
|
|
|
561
573
|
task_name: Option<&str>,
|
|
562
574
|
limit: i64,
|
|
563
575
|
offset: i64,
|
|
576
|
+
namespace: Option<&str>,
|
|
564
577
|
) -> Result<Vec<Job>> {
|
|
565
578
|
let mut conn = self.conn()?;
|
|
566
579
|
|
|
@@ -575,6 +588,9 @@ macro_rules! impl_diesel_job_ops {
|
|
|
575
588
|
if let Some(t) = task_name {
|
|
576
589
|
query = query.filter(jobs::task_name.eq(t));
|
|
577
590
|
}
|
|
591
|
+
if let Some(ns) = namespace {
|
|
592
|
+
query = query.filter(jobs::namespace.eq(ns));
|
|
593
|
+
}
|
|
578
594
|
|
|
579
595
|
let rows: Vec<JobRow> = query
|
|
580
596
|
.limit(limit)
|
|
@@ -678,6 +694,8 @@ macro_rules! impl_diesel_job_ops {
|
|
|
678
694
|
}
|
|
679
695
|
|
|
680
696
|
/// List jobs with extended filters.
|
|
697
|
+
/// When `namespace` is `Some`, only jobs in that namespace are returned.
|
|
698
|
+
/// When `None`, all jobs are returned regardless of namespace.
|
|
681
699
|
#[allow(clippy::too_many_arguments)]
|
|
682
700
|
pub fn list_jobs_filtered(
|
|
683
701
|
&self,
|
|
@@ -690,6 +708,7 @@ macro_rules! impl_diesel_job_ops {
|
|
|
690
708
|
created_before: Option<i64>,
|
|
691
709
|
limit: i64,
|
|
692
710
|
offset: i64,
|
|
711
|
+
namespace: Option<&str>,
|
|
693
712
|
) -> Result<Vec<Job>> {
|
|
694
713
|
let mut conn = self.conn()?;
|
|
695
714
|
|
|
@@ -716,6 +735,9 @@ macro_rules! impl_diesel_job_ops {
|
|
|
716
735
|
if let Some(before) = created_before {
|
|
717
736
|
query = query.filter(jobs::created_at.le(before));
|
|
718
737
|
}
|
|
738
|
+
if let Some(ns) = namespace {
|
|
739
|
+
query = query.filter(jobs::namespace.eq(ns));
|
|
740
|
+
}
|
|
719
741
|
|
|
720
742
|
let rows: Vec<JobRow> = query
|
|
721
743
|
.limit(limit)
|
|
@@ -40,6 +40,7 @@ pub struct DeadJob {
|
|
|
40
40
|
pub max_retries: i32,
|
|
41
41
|
pub timeout_ms: i64,
|
|
42
42
|
pub result_ttl_ms: Option<i64>,
|
|
43
|
+
pub namespace: Option<String>,
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
impl From<models::DeadLetterRow> for DeadJob {
|
|
@@ -58,6 +59,7 @@ impl From<models::DeadLetterRow> for DeadJob {
|
|
|
58
59
|
max_retries: row.max_retries,
|
|
59
60
|
timeout_ms: row.timeout_ms,
|
|
60
61
|
result_ttl_ms: row.result_ttl_ms,
|
|
62
|
+
namespace: row.namespace,
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
65
|
}
|
|
@@ -93,15 +95,17 @@ macro_rules! impl_storage {
|
|
|
93
95
|
&self,
|
|
94
96
|
queue_name: &str,
|
|
95
97
|
now: i64,
|
|
98
|
+
namespace: Option<&str>,
|
|
96
99
|
) -> $crate::error::Result<Option<$crate::job::Job>> {
|
|
97
|
-
self.dequeue(queue_name, now)
|
|
100
|
+
self.dequeue(queue_name, now, namespace)
|
|
98
101
|
}
|
|
99
102
|
fn dequeue_from(
|
|
100
103
|
&self,
|
|
101
104
|
queues: &[String],
|
|
102
105
|
now: i64,
|
|
106
|
+
namespace: Option<&str>,
|
|
103
107
|
) -> $crate::error::Result<Option<$crate::job::Job>> {
|
|
104
|
-
self.dequeue_from(queues, now)
|
|
108
|
+
self.dequeue_from(queues, now, namespace)
|
|
105
109
|
}
|
|
106
110
|
fn complete(
|
|
107
111
|
&self,
|
|
@@ -151,8 +155,9 @@ macro_rules! impl_storage {
|
|
|
151
155
|
task_name: Option<&str>,
|
|
152
156
|
limit: i64,
|
|
153
157
|
offset: i64,
|
|
158
|
+
namespace: Option<&str>,
|
|
154
159
|
) -> $crate::error::Result<Vec<$crate::job::Job>> {
|
|
155
|
-
self.list_jobs(status, queue_name, task_name, limit, offset)
|
|
160
|
+
self.list_jobs(status, queue_name, task_name, limit, offset, namespace)
|
|
156
161
|
}
|
|
157
162
|
fn get_job(&self, id: &str) -> $crate::error::Result<Option<$crate::job::Job>> {
|
|
158
163
|
self.get_job(id)
|
|
@@ -473,6 +478,7 @@ macro_rules! impl_storage {
|
|
|
473
478
|
created_before: Option<i64>,
|
|
474
479
|
limit: i64,
|
|
475
480
|
offset: i64,
|
|
481
|
+
namespace: Option<&str>,
|
|
476
482
|
) -> $crate::error::Result<Vec<$crate::job::Job>> {
|
|
477
483
|
self.list_jobs_filtered(
|
|
478
484
|
status,
|
|
@@ -484,6 +490,7 @@ macro_rules! impl_storage {
|
|
|
484
490
|
created_before,
|
|
485
491
|
limit,
|
|
486
492
|
offset,
|
|
493
|
+
namespace,
|
|
487
494
|
)
|
|
488
495
|
}
|
|
489
496
|
}
|
|
@@ -526,11 +533,16 @@ impl Storage for StorageBackend {
|
|
|
526
533
|
fn enqueue_unique(&self, new_job: NewJob) -> Result<Job> {
|
|
527
534
|
delegate!(self, enqueue_unique, new_job)
|
|
528
535
|
}
|
|
529
|
-
fn dequeue(&self, queue_name: &str, now: i64) -> Result<Option<Job>> {
|
|
530
|
-
delegate!(self, dequeue, queue_name, now)
|
|
536
|
+
fn dequeue(&self, queue_name: &str, now: i64, namespace: Option<&str>) -> Result<Option<Job>> {
|
|
537
|
+
delegate!(self, dequeue, queue_name, now, namespace)
|
|
531
538
|
}
|
|
532
|
-
fn dequeue_from(
|
|
533
|
-
|
|
539
|
+
fn dequeue_from(
|
|
540
|
+
&self,
|
|
541
|
+
queues: &[String],
|
|
542
|
+
now: i64,
|
|
543
|
+
namespace: Option<&str>,
|
|
544
|
+
) -> Result<Option<Job>> {
|
|
545
|
+
delegate!(self, dequeue_from, queues, now, namespace)
|
|
534
546
|
}
|
|
535
547
|
fn complete(&self, id: &str, result_bytes: Option<Vec<u8>>) -> Result<()> {
|
|
536
548
|
delegate!(self, complete, id, result_bytes)
|
|
@@ -572,8 +584,9 @@ impl Storage for StorageBackend {
|
|
|
572
584
|
task_name: Option<&str>,
|
|
573
585
|
limit: i64,
|
|
574
586
|
offset: i64,
|
|
587
|
+
namespace: Option<&str>,
|
|
575
588
|
) -> Result<Vec<Job>> {
|
|
576
|
-
delegate!(self, list_jobs, status, queue_name, task_name, limit, offset)
|
|
589
|
+
delegate!(self, list_jobs, status, queue_name, task_name, limit, offset, namespace)
|
|
577
590
|
}
|
|
578
591
|
fn get_job(&self, id: &str) -> Result<Option<Job>> {
|
|
579
592
|
delegate!(self, get_job, id)
|
|
@@ -818,6 +831,7 @@ impl Storage for StorageBackend {
|
|
|
818
831
|
created_before: Option<i64>,
|
|
819
832
|
limit: i64,
|
|
820
833
|
offset: i64,
|
|
834
|
+
namespace: Option<&str>,
|
|
821
835
|
) -> Result<Vec<Job>> {
|
|
822
836
|
delegate!(
|
|
823
837
|
self,
|
|
@@ -830,7 +844,8 @@ impl Storage for StorageBackend {
|
|
|
830
844
|
created_after,
|
|
831
845
|
created_before,
|
|
832
846
|
limit,
|
|
833
|
-
offset
|
|
847
|
+
offset,
|
|
848
|
+
namespace
|
|
834
849
|
)
|
|
835
850
|
}
|
|
836
851
|
}
|
|
@@ -75,6 +75,7 @@ pub struct DeadLetterRow {
|
|
|
75
75
|
pub max_retries: i32,
|
|
76
76
|
pub timeout_ms: i64,
|
|
77
77
|
pub result_ttl_ms: Option<i64>,
|
|
78
|
+
pub namespace: Option<String>,
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
/// Insertable struct for dead letter entries.
|
|
@@ -94,6 +95,7 @@ pub struct NewDeadLetterRow<'a> {
|
|
|
94
95
|
pub max_retries: i32,
|
|
95
96
|
pub timeout_ms: i64,
|
|
96
97
|
pub result_ttl_ms: Option<i64>,
|
|
98
|
+
pub namespace: Option<&'a str>,
|
|
97
99
|
}
|
|
98
100
|
|
|
99
101
|
/// A row in the `rate_limits` table.
|
|
@@ -394,4 +396,5 @@ pub struct ArchivedJobRow {
|
|
|
394
396
|
pub cancel_requested: i32,
|
|
395
397
|
pub expires_at: Option<i64>,
|
|
396
398
|
pub result_ttl_ms: Option<i64>,
|
|
399
|
+
pub namespace: Option<String>,
|
|
397
400
|
}
|
|
@@ -30,6 +30,7 @@ impl PostgresStorage {
|
|
|
30
30
|
max_retries: job.max_retries,
|
|
31
31
|
timeout_ms: job.timeout_ms,
|
|
32
32
|
result_ttl_ms: job.result_ttl_ms,
|
|
33
|
+
namespace: job.namespace.as_deref(),
|
|
33
34
|
};
|
|
34
35
|
|
|
35
36
|
diesel::insert_into(dead_letter::table)
|
|
@@ -94,7 +95,7 @@ impl PostgresStorage {
|
|
|
94
95
|
depends_on: vec![],
|
|
95
96
|
expires_at: None,
|
|
96
97
|
result_ttl_ms: dead_row.result_ttl_ms,
|
|
97
|
-
namespace:
|
|
98
|
+
namespace: dead_row.namespace,
|
|
98
99
|
};
|
|
99
100
|
|
|
100
101
|
let job = new_job.into_job();
|
|
@@ -434,6 +434,16 @@ impl PostgresStorage {
|
|
|
434
434
|
"ALTER TABLE circuit_breakers ADD COLUMN IF NOT EXISTS half_open_failure_count INTEGER NOT NULL DEFAULT 0",
|
|
435
435
|
);
|
|
436
436
|
|
|
437
|
+
// Migration: add namespace column to dead_letter and archived_jobs
|
|
438
|
+
migration_alter(
|
|
439
|
+
&mut conn,
|
|
440
|
+
"ALTER TABLE dead_letter ADD COLUMN IF NOT EXISTS namespace TEXT",
|
|
441
|
+
);
|
|
442
|
+
migration_alter(
|
|
443
|
+
&mut conn,
|
|
444
|
+
"ALTER TABLE archived_jobs ADD COLUMN IF NOT EXISTS namespace TEXT",
|
|
445
|
+
);
|
|
446
|
+
|
|
437
447
|
// ── Distributed Locks ─────────────────────────────
|
|
438
448
|
diesel::sql_query(
|
|
439
449
|
"CREATE TABLE IF NOT EXISTS distributed_locks (
|
{taskito-0.7.0 → taskito-0.8.0}/crates/taskito-core/src/storage/redis_backend/dead_letter.rs
RENAMED
|
@@ -21,6 +21,8 @@ struct DeadJobEntry {
|
|
|
21
21
|
pub max_retries: i32,
|
|
22
22
|
pub timeout_ms: i64,
|
|
23
23
|
pub result_ttl_ms: Option<i64>,
|
|
24
|
+
#[serde(default)]
|
|
25
|
+
pub namespace: Option<String>,
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
impl From<DeadJobEntry> for DeadJob {
|
|
@@ -39,6 +41,7 @@ impl From<DeadJobEntry> for DeadJob {
|
|
|
39
41
|
max_retries: e.max_retries,
|
|
40
42
|
timeout_ms: e.timeout_ms,
|
|
41
43
|
result_ttl_ms: e.result_ttl_ms,
|
|
44
|
+
namespace: e.namespace,
|
|
42
45
|
}
|
|
43
46
|
}
|
|
44
47
|
}
|
|
@@ -63,6 +66,7 @@ impl RedisStorage {
|
|
|
63
66
|
max_retries: job.max_retries,
|
|
64
67
|
timeout_ms: job.timeout_ms,
|
|
65
68
|
result_ttl_ms: job.result_ttl_ms,
|
|
69
|
+
namespace: job.namespace.clone(),
|
|
66
70
|
};
|
|
67
71
|
|
|
68
72
|
let json = serde_json::to_string(&entry).map_err(|e| QueueError::Other(e.to_string()))?;
|
|
@@ -145,7 +149,7 @@ impl RedisStorage {
|
|
|
145
149
|
depends_on: vec![],
|
|
146
150
|
expires_at: None,
|
|
147
151
|
result_ttl_ms: entry.result_ttl_ms,
|
|
148
|
-
namespace:
|
|
152
|
+
namespace: entry.namespace,
|
|
149
153
|
};
|
|
150
154
|
|
|
151
155
|
let job = self.enqueue(new_job)?;
|
|
@@ -326,7 +326,12 @@ impl RedisStorage {
|
|
|
326
326
|
}
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
-
pub fn dequeue(
|
|
329
|
+
pub fn dequeue(
|
|
330
|
+
&self,
|
|
331
|
+
queue_name: &str,
|
|
332
|
+
now: i64,
|
|
333
|
+
namespace: Option<&str>,
|
|
334
|
+
) -> Result<Option<Job>> {
|
|
330
335
|
let mut conn = self.conn()?;
|
|
331
336
|
let queue_key = self.key(&["queue", queue_name, "pending"]);
|
|
332
337
|
|
|
@@ -356,6 +361,15 @@ impl RedisStorage {
|
|
|
356
361
|
continue;
|
|
357
362
|
}
|
|
358
363
|
|
|
364
|
+
// Filter by namespace: Some(ns) matches that namespace, None matches only jobs without a namespace
|
|
365
|
+
if let Some(ns) = namespace {
|
|
366
|
+
if job.namespace.as_deref() != Some(ns) {
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
} else if job.namespace.is_some() {
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
|
|
359
373
|
// Skip expired jobs
|
|
360
374
|
if let Some(expires_at) = job.expires_at {
|
|
361
375
|
if now > expires_at {
|
|
@@ -403,9 +417,14 @@ impl RedisStorage {
|
|
|
403
417
|
Ok(None)
|
|
404
418
|
}
|
|
405
419
|
|
|
406
|
-
pub fn dequeue_from(
|
|
420
|
+
pub fn dequeue_from(
|
|
421
|
+
&self,
|
|
422
|
+
queues: &[String],
|
|
423
|
+
now: i64,
|
|
424
|
+
namespace: Option<&str>,
|
|
425
|
+
) -> Result<Option<Job>> {
|
|
407
426
|
for queue_name in queues {
|
|
408
|
-
if let Some(job) = self.dequeue(queue_name, now)? {
|
|
427
|
+
if let Some(job) = self.dequeue(queue_name, now, namespace)? {
|
|
409
428
|
return Ok(Some(job));
|
|
410
429
|
}
|
|
411
430
|
}
|
|
@@ -632,6 +651,7 @@ impl RedisStorage {
|
|
|
632
651
|
task_name: Option<&str>,
|
|
633
652
|
limit: i64,
|
|
634
653
|
offset: i64,
|
|
654
|
+
namespace: Option<&str>,
|
|
635
655
|
) -> Result<Vec<Job>> {
|
|
636
656
|
let mut conn = self.conn()?;
|
|
637
657
|
|
|
@@ -661,6 +681,11 @@ impl RedisStorage {
|
|
|
661
681
|
let mut jobs = Vec::new();
|
|
662
682
|
for id in &ids {
|
|
663
683
|
if let Some(job) = self.load_job(&mut conn, id)? {
|
|
684
|
+
if let Some(ns) = namespace {
|
|
685
|
+
if job.namespace.as_deref() != Some(ns) {
|
|
686
|
+
continue;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
664
689
|
jobs.push(job);
|
|
665
690
|
}
|
|
666
691
|
}
|
|
@@ -687,6 +712,11 @@ impl RedisStorage {
|
|
|
687
712
|
continue;
|
|
688
713
|
}
|
|
689
714
|
}
|
|
715
|
+
if let Some(ns) = namespace {
|
|
716
|
+
if job.namespace.as_deref() != Some(ns) {
|
|
717
|
+
continue;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
690
720
|
jobs.push(job);
|
|
691
721
|
}
|
|
692
722
|
}
|
|
@@ -802,6 +832,7 @@ impl RedisStorage {
|
|
|
802
832
|
created_before: Option<i64>,
|
|
803
833
|
limit: i64,
|
|
804
834
|
offset: i64,
|
|
835
|
+
namespace: Option<&str>,
|
|
805
836
|
) -> Result<Vec<Job>> {
|
|
806
837
|
let mut conn = self.conn()?;
|
|
807
838
|
|
|
@@ -860,6 +891,11 @@ impl RedisStorage {
|
|
|
860
891
|
continue;
|
|
861
892
|
}
|
|
862
893
|
}
|
|
894
|
+
if let Some(ns) = namespace {
|
|
895
|
+
if job.namespace.as_deref() != Some(ns) {
|
|
896
|
+
continue;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
863
899
|
jobs.push(job);
|
|
864
900
|
}
|
|
865
901
|
}
|
|
@@ -40,6 +40,7 @@ diesel::table! {
|
|
|
40
40
|
max_retries -> Integer,
|
|
41
41
|
timeout_ms -> BigInt,
|
|
42
42
|
result_ttl_ms -> Nullable<BigInt>,
|
|
43
|
+
namespace -> Nullable<Text>,
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
|
|
@@ -186,6 +187,7 @@ diesel::table! {
|
|
|
186
187
|
cancel_requested -> Integer,
|
|
187
188
|
expires_at -> Nullable<BigInt>,
|
|
188
189
|
result_ttl_ms -> Nullable<BigInt>,
|
|
190
|
+
namespace -> Nullable<Text>,
|
|
189
191
|
}
|
|
190
192
|
}
|
|
191
193
|
|
|
@@ -30,6 +30,7 @@ impl SqliteStorage {
|
|
|
30
30
|
max_retries: job.max_retries,
|
|
31
31
|
timeout_ms: job.timeout_ms,
|
|
32
32
|
result_ttl_ms: job.result_ttl_ms,
|
|
33
|
+
namespace: job.namespace.as_deref(),
|
|
33
34
|
};
|
|
34
35
|
|
|
35
36
|
diesel::insert_into(dead_letter::table)
|
|
@@ -100,7 +101,7 @@ impl SqliteStorage {
|
|
|
100
101
|
depends_on: vec![],
|
|
101
102
|
expires_at: None,
|
|
102
103
|
result_ttl_ms: dead_row.result_ttl_ms,
|
|
103
|
-
namespace:
|
|
104
|
+
namespace: dead_row.namespace,
|
|
104
105
|
};
|
|
105
106
|
|
|
106
107
|
let job = new_job.into_job();
|
|
@@ -430,6 +430,16 @@ impl SqliteStorage {
|
|
|
430
430
|
"ALTER TABLE circuit_breakers ADD COLUMN half_open_failure_count INTEGER NOT NULL DEFAULT 0",
|
|
431
431
|
);
|
|
432
432
|
|
|
433
|
+
// Migration: add namespace column to dead_letter and archived_jobs
|
|
434
|
+
migration_alter(
|
|
435
|
+
&mut conn,
|
|
436
|
+
"ALTER TABLE dead_letter ADD COLUMN namespace TEXT",
|
|
437
|
+
);
|
|
438
|
+
migration_alter(
|
|
439
|
+
&mut conn,
|
|
440
|
+
"ALTER TABLE archived_jobs ADD COLUMN namespace TEXT",
|
|
441
|
+
);
|
|
442
|
+
|
|
433
443
|
// ── Distributed Locks ─────────────────────────────
|
|
434
444
|
diesel::sql_query(
|
|
435
445
|
"CREATE TABLE IF NOT EXISTS distributed_locks (
|