public IBrokerTransaction BeginTransaction(IJobServiceScope scope)
        {
            var dbContext = scope.GetRequiredService <TDbContext>();
            var tx        = dbContext.Database.BeginTransaction();

            return(new BrokerTransaction(tx));
        }
        public void AckMessageProcessed(IJobServiceScope scope, ulong deliveryTag)
        {
            var dbContext = scope.GetRequiredService <TDbContext>();

            var affectedCount = _sqlDialect.MessageQueueAckProcessed(dbContext, _instanceName, _timeProvider.GetCurrentTimeUtc());

            if (affectedCount != 1)
            {
                throw new Exception($"Ack failed. Expected 1 row, but instead, {affectedCount} rows were affected");
            }
        }
示例#3
0
        protected Worker(string queueName, int batchSize, int masMaxDegreeOfParallelism, bool singleActiveConsumer,
                         IJobServiceScopeFactory serviceScopeFactory, IJobLogger <Worker> logger)
            : base(batchSize, logger)
        {
            ServiceScopeFactory = serviceScopeFactory;
            ServiceScope        = ServiceScopeFactory.CreateScope();

            _maxDegreeOfParallelism = masMaxDegreeOfParallelism;
            _singleActiveConsumer   = singleActiveConsumer;
            _messageConsumer        = ServiceScope.GetRequiredService <IMessageConsumer>();

            QueueName = queueName;
        }
        public SqlServerMessageReceiver(string queueName, bool singleActiveConsumer, IJobServiceScopeFactory scopeFactory, IJobLogger <SqlServerMessageReceiver <TDbContext> > logger)
        {
            _scopeFactory = scopeFactory;
            _scope        = scopeFactory.CreateScope();

            _queueName            = queueName;
            _singleActiveConsumer = singleActiveConsumer;
            _sqlDialect           = _scope.GetRequiredService <ISqlDialect>();
            _timeProvider         = _scope.GetRequiredService <ITimeProvider>();
            _logger       = logger;
            _instanceName = $"{Environment.MachineName}/{Guid.NewGuid()}";

            _timer              = _scope.GetRequiredService <ITimer>();
            _timer.TimeElapsed += TimerCallback;
        }
示例#5
0
        public WorkerCoordinator(IJobServiceFactory serviceFactory, IJobLogger <WorkerCoordinator> logger = null)
        {
            ServiceScopeFactory = serviceFactory.GetRequiredService <IJobServiceScopeFactory>();
            ServiceScope        = ServiceScopeFactory.CreateScope();

            _settings = ServiceScope.GetRequiredService <MassiveJobsSettings>();

            _reconnectTimer              = ServiceScope.GetRequiredService <ITimer>();
            _reconnectTimer.TimeElapsed += Reconnect;

            Workers = new List <IWorker>();
            Logger  = logger ?? ServiceScope.GetRequiredService <IJobLogger <WorkerCoordinator> >();

            MessageConsumer = ServiceScope.GetRequiredService <IMessageConsumer>();
            MessageConsumer.Disconnected += MessageBrokerDisconnected;
        }
示例#6
0
        protected bool TryDeserializeJob(RawMessage rawMessage, IJobServiceScope scope, out JobInfo job)
        {
            job = null;

            var argsTag = rawMessage.TypeTag;

            if (string.IsNullOrEmpty(argsTag))
            {
                return(false);
            }

            var serializer   = scope.GetRequiredService <IJobSerializer>();
            var typeProvider = scope.GetRequiredService <IJobTypeProvider>();

            job = serializer.Deserialize(rawMessage.Body, argsTag, typeProvider);

            return(job != null);
        }
 public void AckBatchMessageProcessed(IJobServiceScope scope, ulong deliveryTag)
 {
 }
 public void AckMessageProcessed(IJobServiceScope scope, ulong deliveryTag)
 {
     _model.BasicAck(deliveryTag, false);
 }
 public IBrokerTransaction BeginTransaction(IJobServiceScope scope)
 {
     return(null);
 }
 public void AckBatchMessageProcessed(IJobServiceScope scope, ulong deliveryTag)
 {
     _messages.RemoveMessage(_queueName, deliveryTag);
 }
示例#11
0
 protected void OnMessageProcessed(IJobServiceScope scope, ulong deliveryTag)
 {
     _messageReceiver.AckMessageProcessed(scope, deliveryTag);
 }
示例#12
0
        protected void InvokePerform(IJobPublisher publisher, IMessageReceiver receiver, JobInfo jobInfo, ulong deliveryTag, IJobServiceScope serviceScope, CancellationToken cancellationToken)
        {
            IBrokerTransaction tx = null;

            try
            {
                var reflectionInfo = ReflectionUtilities.ReflectionCache.GetJobReflectionInfo(jobInfo.JobType, jobInfo.ArgsType);

                object job;

                switch (reflectionInfo.CtorType)
                {
                case ReflectionUtilities.ConstructorType.NoArgs:
                    job = reflectionInfo.Ctor.Invoke(null);
                    break;

                case ReflectionUtilities.ConstructorType.NeedsPublisher:
                    job = reflectionInfo.Ctor.Invoke(new object[] { publisher });
                    break;

                default:
                    var parametersInfo = reflectionInfo.Ctor.GetParameters();
                    var parameters     = new object[parametersInfo.Length];

                    for (var i = 0; i < parametersInfo.Length; i++)
                    {
                        if (parametersInfo[i].IsOut)
                        {
                            throw new Exception("Out parameters are not supported.");
                        }
                        parameters[i] = serviceScope.GetRequiredService(parametersInfo[i].ParameterType);
                    }

                    job = reflectionInfo.Ctor.Invoke(parameters);
                    break;
                }

                if (job == null)
                {
                    throw new Exception($"Job type {jobInfo.JobType} is not registered in service scope and appropriate constructor does not exist!");
                }

                if ((bool)reflectionInfo.UseTransactionGetter(job))
                {
                    tx = receiver.BeginTransaction(serviceScope);
                }

                object result;

                switch (reflectionInfo.PerfMethodType)
                {
                case ReflectionUtilities.PerformMethodType.NoArgs:
                    result = reflectionInfo.PerformDelegate1(job);
                    break;

                case ReflectionUtilities.PerformMethodType.NeedsArgs:
                    result = reflectionInfo.PerformDelegate2(job, jobInfo.Args);
                    break;

                case ReflectionUtilities.PerformMethodType.NeedsCancellationToken:
                    result = reflectionInfo.PerformDelegate3(job, cancellationToken);
                    break;

                case ReflectionUtilities.PerformMethodType.NeedsArgsAndCancellationToken:
                    result = reflectionInfo.PerformDelegate4(job, jobInfo.Args, cancellationToken);
                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(reflectionInfo.PerfMethodType));
                }

                if (result != null && result is Task taskResult)
                {
                    taskResult.Wait(cancellationToken);
                }

                receiver.AckBatchMessageProcessed(serviceScope, deliveryTag);

                tx?.Commit();
            }
            catch (TargetInvocationException ex)
            {
                try
                {
                    tx?.Rollback();
                }
                catch (Exception rollbackEx)
                {
                    _logger.LogError(rollbackEx, "Rollback failed");
                }

                if (ex.InnerException == null)
                {
                    throw;
                }
                ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
            }
            finally
            {
                tx.SafeDispose(_logger);
            }
        }
示例#13
0
        public void RunJob(IJobPublisher publisher, IMessageReceiver receiver, JobInfo jobInfo, ulong deliveryTag, IJobServiceScope serviceScope, CancellationToken cancellationToken)
        {
            try
            {
                using (var timeoutTokenSource = new CancellationTokenSource(jobInfo.TimeoutMs ?? DefaultJobTimeoutMs))
                {
                    var timeoutToken = timeoutTokenSource.Token;

                    using (var combinedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutToken))
                    {
                        try
                        {
                            InvokePerform(publisher, receiver, jobInfo, deliveryTag, serviceScope, combinedTokenSource.Token);
                        }
                        catch (OperationCanceledException)
                        {
                            if (timeoutToken.IsCancellationRequested)
                            {
                                throw new OperationCanceledException("A job timed out.");
                            }
                            throw;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Failed running job: {jobInfo.JobType} / {jobInfo.ArgsType} / {jobInfo.GroupKey}");

                publisher.RescheduleJob(jobInfo, ex);

                receiver.AckBatchMessageProcessed(serviceScope, deliveryTag);
            }
        }