nop
nop

Reputation: 6353

Hangfire use of variables inside jobs

I know hangfire doesn't run in same context as ASP.NET and it has its own thread pool but I should use variables inside my background jobs. It's understandable because in fact, those jobs may not run on same server. This means if I execute _locked = false; (in Checker()), it will never get applied because it's running in another context. It's the same for BackgroundJob.Enqueue(() => Start(bot));, if it was a recurring job (cron job), those variables I'm using inside, would always be reset on every single cron job pop up.

How do I use variables in this situation?

private UpdateSubscription _subscription;

private StringBuilder _sb = new StringBuilder();
private bool _locked = false;

public void RunStart(Bot bot)
{
    BackgroundJob.Enqueue(() => Start(bot));
}

public void Start(Bot bot)
{
    ApplyCredentialsOnClient();

    var lastKnownKline = _client.GetKlines(bot.CryptoPair.Symbol, bot.TimeInterval.Interval, limit: 2).Data.First();
    _subscription = _socketClient.SubscribeToKlineUpdates(bot.CryptoPair.Symbol, bot.TimeInterval.Interval, async data =>
    {
        if (data.Data.Final)
        {
            _logger.LogError($"Final | Open time: {data.Data.OpenTime.ToLocalTime()}");
        }

        if (lastKnownKline.OpenTime != data.Data.OpenTime)
        {
            // Static
            _logger.LogError($"Static | Open time: {lastKnownKline.OpenTime.ToLocalTime()} | {lastKnownKline.Close}");
        }
        else if (lastKnownKline.OpenTime == data.Data.OpenTime && lastKnownKline.Close != data.Data.Close)
        {
            // Real time
            if (!_locked)
            {
                _logger.LogError($"Real time | Open time: {data.Data.OpenTime.ToLocalTime()} | {data.Data.Close}");
                _locked = true;

                BackgroundJob.Schedule(() => Checker(), TimeSpan.FromMinutes(1));
            }
            else
            {
                _logger.LogInformation("Locked");
            }
        }

        lastKnownKline = data.Data.ToKline();
    }).Data;
}

public void Checker()
{
    _logger.LogWarning($"{DateTime.UtcNow.ToLocalTime()}");

    _locked = false;
}

Upvotes: 5

Views: 1727

Answers (1)

AminSojoudi
AminSojoudi

Reputation: 2016

Multiple solutions come to my mind, I will start from the simplest one.

If you are running a Single instance then:

1- Use a static variable:

public static bool _locked = false;

Or

2- Define the whole class as Singleton in startup, so each time Hangfire tries to activate the class, it reaches to the same instance.

public void ConfigureServices(IServiceCollection services)
{
    //....

    services.AddSingleton<SomeClass>();

    //....
}

And if you are running this task on multiple instances

Then you should store this variable to a database like Redis and change its states using the database. So the same variable can be accessed from multiple jobs.

Upvotes: 3

Related Questions