Skip to content

firebend/jobba

Repository files navigation

jobba

A durable job scheduling platform for dotnet

Setup

Check out the Sample project for a working example.

  1. Install the library
<ItemGroup>
   <PackageReference Include="Jobba.Core" />
   <PackageReference Include="Jobba.MassTransit" />
   <PackageReference Include="Jobba.Redis" />
   <PackageReference Include="Jobba.Store.Mongo" />
</ItemGroup>

or

dotnet add package Jobba.Core
dotnet add package Jobba.MassTransit
dotnet add package Jobba.Redis
dotnet add package Jobba.Store.Mongo
  1. Create a new SampleJob class that extends AbstractJobBaseClass. You can also create classes for JobState and JobParameters, or use object as a placeholder
using System;
using System.Threading;
using System.Threading.Tasks;
using Jobba.Core.Abstractions;
using Jobba.Core.Interfaces.Repositories;
using Jobba.Core.Models;
using Microsoft.Extensions.Logging;

namespace Jobba.Sample
{
    public class SampleJobState
    {
        public int Tries { get; set; }
    }

    public class SampleJobParameters
    {
        public string Greeting { get; set; }
    }

    public class SampleJob : AbstractJobBaseClass<SampleJobParameters, SampleJobState> // or use `AbstractJobBaseClass<DefaultJobParams, DefaultJobState>` to not use state or parameters
    {
        private readonly ILogger<SampleJob> _logger;

        public SampleJob(IJobProgressStore progressStore, ILogger<SampleJob> logger) : base(progressStore)
        {
            _logger = logger;
        }

        protected override async Task OnStartAsync(JobStartContext<SampleJobParameters, SampleJobState> jobStartContext, CancellationToken cancellationToken)
        {
            // implement your job's behavior
            var tries = jobStartContext.JobState.Tries + 1;
            _logger.LogInformation("Hey I'm trying! Tries: {Tries} {JobId} {Now}", tries, jobStartContext.JobId, DateTimeOffset.Now);
            await LogProgressAsync(new SampleJobState { Tries = tries }, 50, jobStartContext.JobParameters.Greeting, cancellationToken);
            await Task.Delay(100 * tries, cancellationToken);

            if (tries < 10)
            {
                throw new Exception($"Haven't tried enough {tries}"); // jobba will retry if it encounters an exception
            }
            _logger.LogInformation("Now I'm done!");
        }

        public override string JobName => "Sample Job";
    }
}
  1. In Program.cs, add the jobba configuration to the ConfigureServices callback in CreateHostBuilder
   services
      .AddLogging(o => o.AddSimpleConsole(c => c.TimestampFormat = "[yyyy-MM-dd HH:mm:ss] "))
      .AddJobba(jobba =>
        jobba.UsingMassTransit() // use MassTransit as an event bus
          .UsingMongo("mongodb://localhost:27017/jobba-sample", false) // Mongo currently is the only supported data store
          .UsingLitRedis("localhost:6379,defaultDatabase=0") // Use LitRedis for distributed locking
          .AddJob<SampleJob, SampleJobParameters, SampleJobState>() // `AddJob<SampleJob, object, object>` if not using state or parameters
        )
      .AddJobbaSampleMassTransit("rabbitmq://guest:guest@localhost/")
      .AddHostedService<SampleHostedService>();

This example uses

  1. Make a service SampleHostedService that extends BackgroundService and injects an IJobScheduler
using System;
using System.Threading;
using System.Threading.Tasks;
using Jobba.Core.Interfaces;
using Jobba.Core.Models;
using Microsoft.Extensions.Hosting;

namespace Jobba.Sample
{
    public class SampleHostedService : BackgroundService
    {
        private readonly IJobScheduler _jobScheduler;

        public SampleHostedService(IJobScheduler jobScheduler)
        {
            _jobScheduler = jobScheduler;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            // create and schedule your job
            var request = new JobRequest<SampleJobParameters, SampleJobState>
            {
                Description = "A Sample Job",
                JobParameters = new SampleJobParameters { Greeting = "Hello" },
                JobType = typeof(SampleJob),
                InitialJobState = new SampleJobState { Tries = 0 },
                JobWatchInterval = TimeSpan.FromSeconds(10),
                MaxNumberOfTries = 100
            };

            await _jobScheduler.ScheduleJobAsync(request, stoppingToken);
        }
    }
}

Usage

ScheduleJobAsync

Create a new JobRequest and schedule it with _jobScheduler in SampleHostedService's ExecuteAsync

   protected override async Task ExecuteAsync(CancellationToken stoppingToken)
   {
      // create a job request
      var request = new JobRequest<SampleJobParameters, SampleJobState>
      {
         Description = "A Sample Job",
         JobParameters = new SampleJobParameters { Greeting = "Hello" },
         JobType = typeof(SampleJob), // the class for the job to run
         InitialJobState = new SampleJobState { Tries = 0 },
         JobWatchInterval = TimeSpan.FromSeconds(10), // time to wait between retries if the job fails
         MaxNumberOfTries = 100 // maximum number of times to retry when a job fails
      };

      // schedule it with the passed-in cancellation token
      await _jobScheduler.ScheduleJobAsync(request, stoppingToken);
   }

CancelJobAsync

Use the job's ID and the provided cancellation token to cancel a scheduled or running job

   protected override async Task ExecuteAsync(CancellationToken stoppingToken)
   {
      // create a job request
      var request = new JobRequest<SampleJobParameters, SampleJobState>
      {
         Description = "A Sample Job",
         JobParameters = new SampleJobParameters { Greeting = "Hello" },
         JobType = typeof(SampleJob), // the class for the job to run
         InitialJobState = new SampleJobState { Tries = 0 },
         JobWatchInterval = TimeSpan.FromSeconds(10), // time to wait between retries if the job fails
         MaxNumberOfTries = 100 // maximum number of times to retry when a job fails
      };

      // schedule it with the passed-in cancellation token
      await _jobScheduler.ScheduleJobAsync(request, stoppingToken);

      // wait a second and cancel the job
      await Task.Delay(TimeSpan.FromSeconds(1), stoppingToken);
      await _jobScheduler.CancelJobAsync(request.Id, stoppingToken);
   }

About

A durable job scheduling platform for dotnet

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages