DEV Community

Cover image for WJb v1.1: From WJb Action to WJb Job
Oleksandr Viktor
Oleksandr Viktor

Posted on

WJb v1.1: From WJb Action to WJb Job

WJb v1.1: From WJb Action to WJb Job

Most developers discover WJb through Actions.

An Action is easy to understand.

It is just a class that performs work.

await action.ExecuteAsync(input);
Enter fullscreen mode Exit fullscreen mode

For many scenarios, that is enough.

So why would we introduce Jobs?


Step 1. Execute the Action Directly

Suppose we already have an Action:

public sealed class SendEmailAction
    : JobAction<EmailInput>
{
    public override async ValueTask<ActionResult> ExecuteAsync(
        EmailInput input, CancellationToken ct = default)
    {
        await EmailSdk.SendAsync(input, ct);

        return Results.Done();
    }
}
Enter fullscreen mode Exit fullscreen mode

We can execute it directly:

await action.ExecuteAsync(
    new EmailInput
    {
        To = "john@example.com",
        Subject = "Hello"
    });
Enter fullscreen mode Exit fullscreen mode

The Action runs.

The email is sent.

The work is complete.

For small applications, nothing more is required.


Step 2. The Action Has a Limitation

Imagine the application crashes halfway through processing.

What happened?

Action
 ↓
Execute
 ↓
Crash
Enter fullscreen mode Exit fullscreen mode

Questions immediately appear:

  • Did the Action start?
  • Did it finish?
  • Did it fail?
  • Should it be retried?

The Action itself does not answer these questions.

An Action performs work.

It does not track work.


Step 3. Introduce a Job

A Job represents a request to execute an Action.

Instead of running:

await action.ExecuteAsync(input);
Enter fullscreen mode Exit fullscreen mode

we create a Job:

await wjb.EnqueueAsync("send-email",
    new EmailInput
    {
        To = "john@example.com",
        Subject = "Hello"
    });
Enter fullscreen mode Exit fullscreen mode

Now something new exists:

Job
 ↓
Action
 ↓
Business Logic
Enter fullscreen mode Exit fullscreen mode

The Job becomes a record of the work.


Step 4. Why Is This Useful?

A Job can answer questions that an Action cannot.

Was it created?
Was it started?
Was it completed?
Did it fail?
Enter fullscreen mode Exit fullscreen mode

The Action still sends the email.

The Job tracks the execution.

Responsibilities become clear:

Action
 ↓
Performs work
Enter fullscreen mode Exit fullscreen mode
Job
 ↓
Tracks work
Enter fullscreen mode Exit fullscreen mode

Step 5. What Actually Changed?

The business logic did not change.

The Action did not change.

Only the execution model changed.

Before:

Application
 ↓
Action
 ↓
Business Logic
Enter fullscreen mode Exit fullscreen mode

After:

Application
 ↓
Job
 ↓
Action
 ↓
Business Logic
Enter fullscreen mode Exit fullscreen mode

The Action remains focused on the task.

The Job adds execution tracking.


Step 6. Build on Top of Jobs

Once work is represented by Jobs, additional capabilities become possible.

Job
 ↓
Retry
Enter fullscreen mode Exit fullscreen mode
Job
 ↓
Scheduling
Enter fullscreen mode Exit fullscreen mode
Job
 ↓
Monitoring
Enter fullscreen mode Exit fullscreen mode
Job
 ↓
Workflows
Enter fullscreen mode Exit fullscreen mode

These features become possible because the execution is now represented by an object that can be stored, queried, and managed.


The Main Idea

An Action answers:

How is the work performed?

A Job answers:

What work should be performed?

The evolution looks like this:

Business Logic
      ↓
Action
      ↓
Job
Enter fullscreen mode Exit fullscreen mode

Actions execute work.

Jobs represent work.

WJb combines both concepts to make execution reliable, observable, and scalable.

Top comments (0)