Table of Contents

Storage

The store holds tickers, cron occurrences, run history and locks. Without configuration SharpTicker uses an in-memory store, which is lost when the process stops and cannot be shared between instances.

Store Package Shared between instances
In-memory (default) SharpTicker No
Entity Framework Core SharpTicker.EntityFrameworkCore Yes
MongoDB SharpTicker.MongoDB Yes
Redis SharpTicker.Caching.StackExchangeRedis Yes

Entity Framework Core

Works with any relational EF Core provider, such as SQL Server, PostgreSQL, SQLite or MySQL. There are two ways to use it.

A separate DbContext

SharpTicker brings its own SharpTickerDbContext:

using Microsoft.EntityFrameworkCore;
using SharpTicker.DependencyInjection;
using SharpTicker.EntityFrameworkCore.DbContextFactory;
using SharpTicker.EntityFrameworkCore.DependencyInjection;

builder.Services.AddSharpTicker(options =>
{
    options.AddOperationalStore(ef =>
    {
        ef.UseSharpTickerDbContext<SharpTickerDbContext>(db =>
            db.UseNpgsql(builder.Configuration.GetConnectionString("Scheduler")));
    });
});

Your own DbContext

To keep the tables in your application's database and migrations, map them into your own context:

using SharpTicker.EntityFrameworkCore.Customizer;

options.AddOperationalStore(ef =>
{
    ef.UseApplicationDbContext<AppDbContext>(ConfigurationType.UseModelCustomizer);
});

With ConfigurationType.UseModelCustomizer the tables are added to your model automatically. With IgnoreModelCustomizer, apply (from SharpTicker.EntityFrameworkCore.Configurations) TimeTickerConfigurations<TimeTickerEntity>, CronTickerConfigurations<CronTickerEntity> and CronTickerOccurrenceConfigurations<CronTickerEntity> yourself in OnModelCreating.

Schema and tables

Tables are created in the ticker schema: TimeTickers, CronTickers and CronTickerOccurrences. Change the schema with ef.SetSchema("..."). Create the tables with EF Core migrations, or with EnsureCreated() / GenerateCreateScript() when you do not use migrations.

Other options: SetDbContextPoolSize(int) (default 1024).

MongoDB

using SharpTicker.MongoDB.DependencyInjection;

options.AddOperationalStore(mongo =>
{
    mongo.UseSharpTickerMongoClient("mongodb://localhost:27017", "scheduler");
});
  • UseExistingMongoClient(databaseName) reuses an IMongoClient that is already registered in dependency injection.
  • One of the two is required; startup fails otherwise.
  • Collections use the prefix ticker_ (ticker_TimeTickers, ticker_CronTickers, ticker_CronTickerOccurrences). Change it with SetCollectionPrefix("...").
  • Indexes are created at startup.

Redis

using SharpTicker.Caching.StackExchangeRedis.DependencyInjection;

options.AddStackExchangeRedis(redis =>
{
    redis.Configuration = "localhost:6379";
});
  • Set one of Configuration, ConfigurationOptions, ConnectionMultiplexer or ConnectionMultiplexerFactory; startup fails otherwise.
  • InstanceName (default sharpticker:) is the prefix under which nodes report that they are alive. Job data uses its own tq:* keys.
  • Each node sends a heartbeat every NodeHeartbeatInterval (default one minute). Jobs held by a node that stopped sending heartbeats are released for others.
  • For trimmed or AOT applications, set JsonSerializerContext.

Choosing a store

  • In-memory for development, tests and single-process tools where losing jobs on restart is acceptable.
  • EF Core when you already run a relational database. With your own DbContext the tables live next to your data and in your migrations.
  • MongoDB when your application already uses MongoDB.
  • Redis for a fast, shared store when you already run Redis and accept its persistence model.