示例#1
0
        private async Task RetryJob(Job job, ExecutedJob run, ITransaction transaction)
        {
            run.Retries++;
            run.Status    = JobStatus.Retrying;
            run.NextRetry = CalculateNextRetry(run);
            await SaveJobRun(run, transaction);

            transaction.SetAddAsync($"{_options.KeyPrefix}_job_retries", job.RunId.ToString());
        }
示例#2
0
        private async Task SaveJobRun(Job job, JobStatus status, ITransaction transaction)
        {
            var run = await GetRun(job.RunId.ToString());

            var execution = new ExecutedJob(job, status, _id);

            if (run != null)
            {
                execution.Retries   = run.Retries;
                execution.NextRetry = run.NextRetry;
            }

            await SaveJobRun(execution, transaction);
        }
示例#3
0
        private async Task SaveJobRun(ExecutedJob job, ITransaction transaction)
        {
            var last = await GetRun(job.RunId.ToString());

            if (last != null)
            {
                transaction.SetRemoveAsync($"{_options.KeyPrefix}_job_status_{last.Status.ToString()}",
                                           last.RunId.ToString());
            }
            job.Timestamp = DateTime.UtcNow.Ticks;
            var lastRun = $"{_options.KeyPrefix}_{job.Name}_last_run";
            var key     = $"{_options.KeyPrefix}_{job.Name}_runs";

            transaction.StringSetAsync($"{_options.KeyPrefix}_{job.RunId}_run", BsonSerializer.ToBson(job));
            transaction.SetAddAsync(key, job.RunId.ToString());
            transaction.StringSetAsync(lastRun, job.Timestamp);
            transaction.SetAddAsync($"{_options.KeyPrefix}_job_status_{job.Status.ToString()}", job.RunId.ToString());
        }
示例#4
0
        private async Task ExecuteJob(ExecutedJob job, ITransaction transaction)
        {
            if (!_listeners.ContainsKey(job.Name) && !_listenersNoArgs.ContainsKey(job.Name))
            {
                await OnJobError(job, new NoHandlerFoundException(job), transaction);

                return;
            }

            await OnJobStart(job, transaction);

            await transaction.ExecuteAsync();

            transaction = _connection.GetDatabase().CreateTransaction();

            try
            {
                if (_listeners.ContainsKey(job.Name))
                {
                    await _listeners[job.Name](job.Parameters);
                }
                else
                {
                    await _listenersNoArgs[job.Name]();
                }
            }
            catch (Exception e)
            {
                await OnJobError(job, e, transaction);

                return;
            }

            try
            {
                transaction.StringIncrementAsync($"{_options.KeyPrefix}_job_{job.Name}_run_count");
                transaction.ListRemoveAsync($"{_options.KeyPrefix}_progress", job.RunId.ToString());
                transaction.StringIncrementAsync($"{_options.KeyPrefix}_stats_total_runs");
                await SaveJobRun(job, JobStatus.Success, transaction);

                switch (job.Type)
                {
                case JobType.Immediate:
                    await OnImmediateJobFinish(job, transaction);

                    break;

                case JobType.Scheduled:
                    await OnScheduledJobFinish(job, transaction);

                    break;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            finally
            {
                await transaction.ExecuteAsync(CommandFlags.FireAndForget);
            }
        }
示例#5
0
        private async Task ExecuteQueue()
        {
            await _semaphore.WaitAsync();

            ExecutedJob job   = null;
            string      runId = string.Empty;

            try
            {
                var db    = _connection.GetDatabase();
                var trans = _connection.GetDatabase().CreateTransaction();

                var value = await db.ListRightPopLeftPushAsync($"{_options.KeyPrefix}_enqueued",
                                                               $"{_options.KeyPrefix}_progress");

                if (!value.HasValue)
                {
                    return;
                }

                runId = value.ToString();
                job   = await GetRun(runId);

                if (job == null)
                {
                    throw new Exception($"Failed to find job run details relating to job run {runId}");
                }

                var key = $"{_options.KeyPrefix}_{job.Name}_lock";

                if (job.Options != null && !job.Options.AllowConcurrentExecution)
                {
                    using (var jobLock = await _lockFactory.CreateLockAsync(key, TimeSpan.FromSeconds(30)))
                    {
                        if (!jobLock.IsAcquired)
                        {
                            trans.ListRightPushAsync($"{_options.KeyPrefix}_enqueued", value);
                            trans.ListRemoveAsync($"{_options.KeyPrefix}_progress", value);
                            await trans.ExecuteAsync(CommandFlags.FireAndForget);

                            return;
                        }

                        await ExecuteJob(job, trans);
                    }
                }
                else
                {
                    await ExecuteJob(job, trans);
                }
            }
            catch (Exception e)
            {
                var trans = _connection.GetDatabase().CreateTransaction();
                if (_options.OnQueueError != null)
                {
                    await _options.OnQueueError(e);
                }

                if (job != null)
                {
                    await OnJobError(job, e, trans);

                    await trans.ExecuteAsync(CommandFlags.FireAndForget);
                }

                if (_options.OnQueueError == null)
                {
                    throw;
                }
            }
            finally
            {
                _semaphore.Release();
            }
        }
示例#6
0
        private long CalculateNextRetry(ExecutedJob run)
        {
            var ticks = (run.Retries * _options.RetryBackOff).Ticks;

            return(DateTime.UtcNow.AddTicks(ticks).Ticks);
        }
示例#7
0
 private async Task Enqueue(ExecutedJob run)
 {
     await EnqueueMany(new[] { run });
 }