Implementing custom states


#1

I’m trying to implement custom states using IState & IStateHandler. I’ve got my states defined, but not sure 1) where the processing should actually happen, is it in State Handler Apply? or somewhere else
2) how/where to transition to the next state, should it be in the ElectStateFilter or the State Handler?


#2

I would like to know that too, the documentation on it seems to only explain the custom IState


#3

has anyone made progress implementing their own IStateHandler?

I tried copying and implementing my own version of Enqueued State and it didn’t seem to be running the handler.


#4

I shouldn’t have had to pull in the HangFire code projects to figure this out but such is life.
(FYI, We are using the SQL Server database but I think this should apply to other connections)

To start I added a hander to a state that just added to the counter table for testing.

public class ReadyToEnqueue : IState
....
internal class Handler : IStateHandler
    {
        public void Apply(ApplyStateContext context, IWriteOnlyTransaction transaction)
        {
            transaction.IncrementCounter("i win");
        }
        public void Unapply(ApplyStateContext context, IWriteOnlyTransaction transaction)
        {
        }
        public string StateName
        {
            get
            {
                return ReadyToEnqueue.StateName;
            }
        }
    }
}

Next, I created a Job Storage class that extended the SqlServerStorage:

public class MyJobStorage : SqlServerStorage
{
    public override IEnumerable<IStateHandler> GetStateHandlers()
    {
        return new List<IStateHandler>()
        {
            new ReadyToEnqueue.Handler()
        };
    }
    public SovosJobStorage(string nameOrConnectionString) : base(nameOrConnectionString)
    {
    }
    public SovosJobStorage(string nameOrConnectionString, SqlServerStorageOptions options) : base(
        nameOrConnectionString, options)
    {
    }
    public SovosJobStorage(DbConnection existingConnection) : base(existingConnection)
    {
    }
    public SovosJobStorage(DbConnection existingConnection, SqlServerStorageOptions options) : base(
        existingConnection, options)
    {
    }
}

Finally in our ApiBootstrap.cs file I changed:

GlobalConfiguration.Configuration.UseSqlServerStorage(dbConnectionString);

to

GlobalConfiguration.Configuration.UseStorage(new MyJobStorage(dbConnectionString));

#5
  1. Processing logic should be done in either state handler or ApplyStateFilter (they’re equivalent).
  2. Transition logic should be done in ElectStateFilter.