Beispiel #1
0
        public string CreateInState(
            Job job,
            IDictionary <string, string> parameters,
            IState state)
        {
            if (job == null)
            {
                throw new ArgumentNullException("job");
            }
            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }
            if (state == null)
            {
                throw new ArgumentNullException("state");
            }

            var createdAt = DateTime.UtcNow;
            var jobId     = _connection.CreateExpiredJob(
                job,
                parameters,
                createdAt,
                TimeSpan.FromHours(1));

            var context = new StateContext(jobId, job, createdAt, _connection);

            _stateChangeProcess.ChangeState(context, state, null);

            return(jobId);
        }
        public bool ChangeState(StateContext context, IState toState, string oldStateName)
        {
            try
            {
                var filterInfo = GetFilters(context.Job);

                var electStateContext = new ElectStateContext(context, toState, oldStateName);
                var electedState = ElectState(electStateContext, filterInfo.ElectStateFilters);

                var applyStateContext = new ApplyStateContext(context, electedState, oldStateName);
                ApplyState(applyStateContext, filterInfo.ApplyStateFilters);

                // State transition was succeeded.
                return true;
            }
            catch (Exception ex)
            {
                var failedState = new FailedState(ex)
                {
                    Reason = "An exception occurred during the transition of job's state"
                };

                var applyStateContext = new ApplyStateContext(context, failedState, oldStateName);

                // We should not use any state changed filters, because
                // some of the could cause an exception.
                ApplyState(applyStateContext, Enumerable.Empty<IApplyStateFilter>());

                // State transition was failed due to exception.
                return false;
            }
        }
Beispiel #3
0
        public bool ChangeState(StateContext context, IState toState, string oldStateName)
        {
            try
            {
                var filterInfo = GetFilters(context.Job);

                var electStateContext = new ElectStateContext(context, toState, oldStateName);
                var electedState      = ElectState(electStateContext, filterInfo.ElectStateFilters);

                var applyStateContext = new ApplyStateContext(context, electedState, oldStateName);
                ApplyState(applyStateContext, filterInfo.ApplyStateFilters);

                // State transition was succeeded.
                return(true);
            }
            catch (Exception ex)
            {
                var failedState = new FailedState(ex)
                {
                    Reason = "An exception occurred during the transition of job's state"
                };

                var applyStateContext = new ApplyStateContext(context, failedState, oldStateName);

                // We should not use any state changed filters, because
                // some of the could cause an exception.
                ApplyState(applyStateContext, Enumerable.Empty <IApplyStateFilter>());

                // State transition was failed due to exception.
                return(false);
            }
        }
        public ApplyStateContext(StateContext context, IState newState, string oldStateName)
            : base(context)
        {
            if (newState == null) throw new ArgumentNullException("newState");

            OldStateName = oldStateName;
            NewState = newState;
            JobExpirationTimeout = TimeSpan.FromDays(1);
        }
        public void CopyCtor_CopiesAllProperties()
        {
            var context = CreateContext();
            var contextCopy = new StateContext(context);

            Assert.Equal(context.JobId, contextCopy.JobId);
            Assert.Equal(context.CreatedAt, contextCopy.CreatedAt);
            Assert.Same(context.Job, contextCopy.Job);
            Assert.Same(context.Connection, contextCopy.Connection);
        }
Beispiel #6
0
        internal ElectStateContext(StateContext context, IState candidateState, string currentState)
            : base(context)
        {
            if (candidateState == null)
            {
                throw new ArgumentNullException("candidateState");
            }

            CandidateState = candidateState;
            CurrentState   = currentState;
        }
Beispiel #7
0
        public ApplyStateContext(StateContext context, IState newState, string oldStateName)
            : base(context)
        {
            if (newState == null)
            {
                throw new ArgumentNullException("newState");
            }

            OldStateName         = oldStateName;
            NewState             = newState;
            JobExpirationTimeout = TimeSpan.FromDays(1);
        }
Beispiel #8
0
        public string CreateInState(
            Job job,
            IDictionary<string, string> parameters,
            IState state)
        {
            if (job == null) throw new ArgumentNullException("job");
            if (parameters == null) throw new ArgumentNullException("parameters");
            if (state == null) throw new ArgumentNullException("state");

            var createdAt = DateTime.UtcNow;
            var jobId = _connection.CreateExpiredJob(
                job,
                parameters,
                createdAt,
                TimeSpan.FromHours(1));

            var context = new StateContext(jobId, job, createdAt, _connection);
            _stateChangeProcess.ChangeState(context, state, null);

            return jobId;
        }
Beispiel #9
0
        public bool TryToChangeState(
            string jobId, IState toState, string[] fromStates)
        {
            if (jobId == null)
            {
                throw new ArgumentNullException("jobId");
            }
            if (toState == null)
            {
                throw new ArgumentNullException("toState");
            }
            if (fromStates != null && fromStates.Length == 0)
            {
                throw new ArgumentException("From states array should be null or non-empty.", "fromStates");
            }

            // To ensure that job state will be changed only from one of the
            // specified states, we need to ensure that other users/workers
            // are not able to change the state of the job during the
            // execution of this method. To guarantee this behavior, we are
            // using distributed application locks and rely on fact, that
            // any state transitions will be made only within a such lock.
            using (_connection.AcquireDistributedLock(
                       String.Format("job:{0}:state-lock", jobId),
                       JobLockTimeout))
            {
                var jobData = _connection.GetJobData(jobId);

                if (jobData == null)
                {
                    // The job does not exist. This may happen, because not
                    // all storage backends support foreign keys.
                    return(false);
                }

                if (fromStates != null && !fromStates.Contains(jobData.State, StringComparer.OrdinalIgnoreCase))
                {
                    return(false);
                }

                bool loadSucceeded = true;

                try
                {
                    jobData.EnsureLoaded();
                }
                catch (JobLoadException ex)
                {
                    // If the job type could not be loaded, we are unable to
                    // load corresponding filters, unable to process the job
                    // and sometimes unable to change its state (the enqueued
                    // state depends on the type of a job).

                    if (!toState.IgnoreJobLoadException)
                    {
                        toState = new FailedState(ex.InnerException)
                        {
                            Reason = String.Format(
                                "Can not change the state of a job to '{0}': target method was not found.",
                                toState.Name)
                        };

                        loadSucceeded = false;
                    }
                }

                var context      = new StateContext(jobId, jobData.Job, jobData.CreatedAt, _connection);
                var stateChanged = _stateChangeProcess.ChangeState(context, toState, jobData.State);

                return(loadSucceeded && stateChanged);
            }
        }
Beispiel #10
0
 internal StateContext(StateContext context)
     : this(context.JobId, context.Job, context.CreatedAt, context.Connection)
 {
 }
Beispiel #11
0
 internal StateContext(StateContext context)
     : this(context.JobId, context.Job, context.CreatedAt, context.Connection)
 {
 }
Beispiel #12
0
        public bool TryToChangeState(
            string jobId, IState toState, string[] fromStates)
        {
            if (jobId == null) throw new ArgumentNullException("jobId");
            if (toState == null) throw new ArgumentNullException("toState");
            if (fromStates != null && fromStates.Length == 0)
            {
                throw new ArgumentException("From states array should be null or non-empty.", "fromStates");
            }

            // To ensure that job state will be changed only from one of the
            // specified states, we need to ensure that other users/workers
            // are not able to change the state of the job during the
            // execution of this method. To guarantee this behavior, we are
            // using distributed application locks and rely on fact, that
            // any state transitions will be made only within a such lock.
            using (_connection.AcquireDistributedLock(
                String.Format("job:{0}:state-lock", jobId),
                JobLockTimeout))
            {
                var jobData = _connection.GetJobData(jobId);

                if (jobData == null)
                {
                    // The job does not exist. This may happen, because not
                    // all storage backends support foreign keys. 
                    return false;
                }

                if (fromStates != null && !fromStates.Contains(jobData.State, StringComparer.OrdinalIgnoreCase))
                {
                    return false;
                }

                bool loadSucceeded = true;

                try
                {
                    jobData.EnsureLoaded();
                }
                catch (JobLoadException ex)
                {
                    // If the job type could not be loaded, we are unable to
                    // load corresponding filters, unable to process the job
                    // and sometimes unable to change its state (the enqueued
                    // state depends on the type of a job).

                    if (!toState.IgnoreJobLoadException)
                    {
                        toState = new FailedState(ex.InnerException)
                        {
                            Reason = String.Format(
                                "Can not change the state of a job to '{0}': target method was not found.",
                                toState.Name)
                        };

                        loadSucceeded = false;
                    }
                }

                var context = new StateContext(jobId, jobData.Job, jobData.CreatedAt, _connection);
                var stateChanged = _stateChangeProcess.ChangeState(context, toState, jobData.State);

                return loadSucceeded && stateChanged;
            }
        }