Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions benches/dependencies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use pprof::criterion::{Output, PProfProfiler};
use serde::{Deserialize, Serialize};
use taskmill::{
Domain, DomainKey, Scheduler, SchedulerEvent, TaskContext, TaskError, TaskStore,
Domain, DomainKey, DomainTaskContext, Scheduler, SchedulerEvent, TaskError, TaskStore,
TaskSubmission, TypedExecutor, TypedTask,
};
use tokio::runtime::Runtime;
Expand All @@ -30,7 +30,11 @@ impl TypedTask for BenchTask {
struct NoopExecutor;

impl TypedExecutor<BenchTask> for NoopExecutor {
async fn execute(&self, _payload: BenchTask, _ctx: &TaskContext) -> Result<(), TaskError> {
async fn execute<'a>(
&'a self,
_payload: BenchTask,
_ctx: DomainTaskContext<'a, BenchDomain>,
) -> Result<(), TaskError> {
Ok(())
}
}
Expand Down
8 changes: 6 additions & 2 deletions benches/groups.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::time::{Duration, Instant};
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use serde::{Deserialize, Serialize};
use taskmill::{
Domain, DomainKey, Scheduler, SchedulerEvent, TaskContext, TaskError, TaskStore,
Domain, DomainKey, DomainTaskContext, Scheduler, SchedulerEvent, TaskError, TaskStore,
TaskSubmission, TypedExecutor, TypedTask,
};
use tokio::runtime::Runtime;
Expand All @@ -28,7 +28,11 @@ impl TypedTask for BenchTask {
struct NoopExecutor;

impl TypedExecutor<BenchTask> for NoopExecutor {
async fn execute(&self, _payload: BenchTask, _ctx: &TaskContext) -> Result<(), TaskError> {
async fn execute<'a>(
&'a self,
_payload: BenchTask,
_ctx: DomainTaskContext<'a, BenchDomain>,
) -> Result<(), TaskError> {
Ok(())
}
}
Expand Down
8 changes: 6 additions & 2 deletions benches/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::time::Duration;
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use serde::{Deserialize, Serialize};
use taskmill::{
Domain, DomainKey, Scheduler, SchedulerEvent, TaskContext, TaskError, TaskStore,
Domain, DomainKey, DomainTaskContext, Scheduler, SchedulerEvent, TaskError, TaskStore,
TaskSubmission, TypedExecutor, TypedTask,
};
use tokio::runtime::Runtime;
Expand All @@ -28,7 +28,11 @@ impl TypedTask for BenchTask {
struct NoopExecutor;

impl TypedExecutor<BenchTask> for NoopExecutor {
async fn execute(&self, _payload: BenchTask, _ctx: &TaskContext) -> Result<(), TaskError> {
async fn execute<'a>(
&'a self,
_payload: BenchTask,
_ctx: DomainTaskContext<'a, BenchDomain>,
) -> Result<(), TaskError> {
Ok(())
}
}
Expand Down
14 changes: 11 additions & 3 deletions benches/retry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::time::{Duration, Instant};
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
use serde::{Deserialize, Serialize};
use taskmill::{
BackoffStrategy, Domain, DomainKey, RetryPolicy, Scheduler, SchedulerEvent, TaskContext,
BackoffStrategy, Domain, DomainKey, DomainTaskContext, RetryPolicy, Scheduler, SchedulerEvent,
TaskError, TaskStore, TaskSubmission, TypedExecutor, TypedTask,
};
use tokio::runtime::Runtime;
Expand All @@ -34,15 +34,23 @@ impl TypedTask for FailTask {
struct FailPermanentExecutor;

impl TypedExecutor<FailTask> for FailPermanentExecutor {
async fn execute(&self, _payload: FailTask, _ctx: &TaskContext) -> Result<(), TaskError> {
async fn execute<'a>(
&'a self,
_payload: FailTask,
_ctx: DomainTaskContext<'a, BenchDomain>,
) -> Result<(), TaskError> {
Err(TaskError::permanent("bench: permanent failure"))
}
}

struct FailRetryableExecutor;

impl TypedExecutor<FailTask> for FailRetryableExecutor {
async fn execute(&self, _payload: FailTask, _ctx: &TaskContext) -> Result<(), TaskError> {
async fn execute<'a>(
&'a self,
_payload: FailTask,
_ctx: DomainTaskContext<'a, BenchDomain>,
) -> Result<(), TaskError> {
Err(TaskError::retryable("bench: transient failure"))
}
}
Expand Down
16 changes: 12 additions & 4 deletions benches/scheduler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use std::time::{Duration, Instant};
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use serde::{Deserialize, Serialize};
use taskmill::{
Domain, DomainKey, Priority, Scheduler, SchedulerEvent, TaskContext, TaskError, TaskStore,
TaskSubmission, TypedExecutor, TypedTask,
Domain, DomainKey, DomainTaskContext, Priority, Scheduler, SchedulerEvent, TaskError,
TaskStore, TaskSubmission, TypedExecutor, TypedTask,
};
use tokio::runtime::Runtime;
use tokio_util::sync::CancellationToken;
Expand Down Expand Up @@ -41,7 +41,11 @@ impl TypedTask for ByteTestTask {
struct NoopExecutor;

impl TypedExecutor<BenchTask> for NoopExecutor {
async fn execute(&self, _payload: BenchTask, _ctx: &TaskContext) -> Result<(), TaskError> {
async fn execute<'a>(
&'a self,
_payload: BenchTask,
_ctx: DomainTaskContext<'a, BenchDomain>,
) -> Result<(), TaskError> {
Ok(())
}
}
Expand All @@ -53,7 +57,11 @@ struct ByteProgressExecutor {
}

impl TypedExecutor<ByteTestTask> for ByteProgressExecutor {
async fn execute(&self, _payload: ByteTestTask, ctx: &TaskContext) -> Result<(), TaskError> {
async fn execute<'a>(
&'a self,
_payload: ByteTestTask,
ctx: DomainTaskContext<'a, BenchDomain>,
) -> Result<(), TaskError> {
ctx.set_bytes_total(self.total);
let mut remaining = self.total;
while remaining > 0 {
Expand Down
10 changes: 7 additions & 3 deletions benches/tags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use std::time::{Duration, Instant};
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use serde::{Deserialize, Serialize};
use taskmill::{
Domain, DomainKey, Scheduler, TaskContext, TaskError, TaskStore, TaskSubmission, TypedExecutor,
TypedTask,
Domain, DomainKey, DomainTaskContext, Scheduler, TaskError, TaskStore, TaskSubmission,
TypedExecutor, TypedTask,
};
use tokio::runtime::Runtime;

Expand All @@ -27,7 +27,11 @@ impl TypedTask for BenchTask {
struct NoopExecutor;

impl TypedExecutor<BenchTask> for NoopExecutor {
async fn execute(&self, _payload: BenchTask, _ctx: &TaskContext) -> Result<(), TaskError> {
async fn execute<'a>(
&'a self,
_payload: BenchTask,
_ctx: DomainTaskContext<'a, BenchDomain>,
) -> Result<(), TaskError> {
Ok(())
}
}
Expand Down
176 changes: 176 additions & 0 deletions docs/migrating-to-0.6.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# Migrating from 0.5.x to 0.6.0

0.6.0 replaces the untyped `&TaskContext` in `TypedExecutor` with a
domain-parameterized `DomainTaskContext<'a, D>` wrapper. It also removes the
untyped executor API (`TaskExecutor`, `TaskContext`, `raw_executor`,
`submit_raw`) from the public surface.

### 1. Executor signature change

All `TypedExecutor` implementations must update `execute`, `finalize`, and
`on_cancel` to accept `DomainTaskContext<'a, T::Domain>` instead of
`&'a TaskContext`.

**Before:**

```rust
impl TypedExecutor<Thumbnail> for ThumbnailExec {
async fn execute<'a>(
&'a self,
thumb: Thumbnail,
ctx: &'a TaskContext,
) -> Result<(), TaskError> {
// ...
}
}
```

**After:**

```rust
impl TypedExecutor<Thumbnail> for ThumbnailExec {
async fn execute<'a>(
&'a self,
thumb: Thumbnail,
ctx: DomainTaskContext<'a, Media>,
) -> Result<(), TaskError> {
// ...
}
}
```

All accessor methods (`record()`, `token()`, `check_cancelled()`, `progress()`,
`state()`, `domain_state()`, `domain()`, `try_domain()`, IO tracking, and
byte-level progress) are delegated identically — no call-site changes needed.

### 2. Generic executors

For generic `impl<T: TypedTask> TypedExecutor<T>` implementations, use
`T::Domain` as the type parameter:

**Before:**

```rust
impl<T: TypedTask> TypedExecutor<T> for NoopExecutor {
async fn execute<'a>(
&'a self,
_payload: T,
_ctx: &'a TaskContext,
) -> Result<(), TaskError> {
Ok(())
}
}
```

**After:**

```rust
impl<T: TypedTask> TypedExecutor<T> for NoopExecutor {
async fn execute<'a>(
&'a self,
_payload: T,
_ctx: DomainTaskContext<'a, T::Domain>,
) -> Result<(), TaskError> {
Ok(())
}
}
```

### 3. Child spawning (same domain)

`spawn_child(TaskSubmission)` is no longer exposed on `DomainTaskContext`.
Use `spawn_child_with(task)` which is type-safe — only tasks where
`T::Domain == D` are accepted.

**Before:**

```rust
ctx.spawn_child(
TaskSubmission::new("upload-part")
.key(&part.etag)
.payload_json(&UploadPart { etag: part.etag.clone(), size: part.size })?,
).await?;
```

**After:**

```rust
ctx.spawn_child_with(UploadPart { etag: part.etag.clone(), size: part.size })
.key(&part.etag)
.await?;
```

`ChildSpawnBuilder` supports `.key()`, `.priority()`, `.ttl()`, and `.group()`
overrides before `.await`.

### 4. Batch child spawning

`spawn_children(Vec<TaskSubmission>)` (mixed types) is replaced by
`spawn_children_with(tasks)` (single type `T`).

**Before:**

```rust
let subs: Vec<TaskSubmission> = parts.iter()
.map(|p| TaskSubmission::new("upload-part").key(&p.etag).payload_json(p).unwrap())
.collect();
ctx.spawn_children(subs).await?;
```

**After:**

```rust
ctx.spawn_children_with(parts).await?;
```

Mixed-type fan-out now requires separate `spawn_child_with` calls per type.
This forgoes SQL batching for that specific pattern.

### 5. Cross-domain children

Use the new `child_of(&ctx)` method instead of manually extracting the parent ID.

**Before:**

```rust
ctx.domain::<Analytics>()
.submit_with(ScanStartedEvent { .. })
.parent(ctx.record().id)
.await?;
```

**After:**

```rust
ctx.domain::<Analytics>()
.submit_with(ScanStartedEvent { .. })
.child_of(&ctx)
.await?;
```

### 6. Removed public API

The following are no longer exported from the crate root:

| Removed | Replacement |
|---|---|
| `TaskExecutor` trait | Use `TypedExecutor<T>` |
| `TaskContext` struct | Use `DomainTaskContext<'a, D>` |
| `Domain::raw_executor(name, exec)` | Use `Domain::task::<T>(exec)` |
| `DomainHandle::submit_raw(sub)` | Use `DomainHandle::submit(task)` or `submit_with(task)` |

### 7. Import changes

**Before:**

```rust
use taskmill::{TaskContext, TaskExecutor, TypedExecutor, /* ... */};
```

**After:**

```rust
use taskmill::{DomainTaskContext, TypedExecutor, /* ... */};
// Optional, if using typed child spawning directly:
use taskmill::ChildSpawnBuilder;
```
6 changes: 3 additions & 3 deletions examples/profile_dep_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use std::time::{Duration, Instant};

use serde::{Deserialize, Serialize};
use taskmill::{
Domain, DomainKey, Scheduler, TaskContext, TaskError, TaskStore, TaskSubmission, TypedExecutor,
TypedTask,
Domain, DomainKey, DomainTaskContext, Scheduler, TaskError, TaskStore, TaskSubmission,
TypedExecutor, TypedTask,
};

struct BenchDomain;
Expand All @@ -25,7 +25,7 @@ impl TypedExecutor<BenchTask> for NoopExecutor {
async fn execute<'a>(
&'a self,
_payload: BenchTask,
_ctx: &'a TaskContext,
_ctx: DomainTaskContext<'a, BenchDomain>,
) -> Result<(), TaskError> {
Ok(())
}
Expand Down
Loading
Loading