示例#1
0
        public TaskExecutionInfo ProcessTaskDefinition(SingleTaskDefinition taskDefinition)
        {
            var lockInfo     = LockInfo.Empty(taskDefinition.Identifier);
            var taskTypeInfo = _taskManager.GetTaskInfo(taskDefinition.Identifier);
            //links this task's cancellation token to the manager's token
            var ctSource = CancellationTokenSource.CreateLinkedTokenSource(_listenerCtSource.Token);

            try
            {
                //Inter-process lock. Ignores the task if it doesn't acquire lock
                if (taskTypeInfo == null || !_taskManager.LockManager.TryRenewLock(lockInfo, taskTypeInfo.LockCycle, retryLock: true))
                {
                    return(new TaskExecutionInfo(_managedThreadPool.CreateCompletedTask(), ctSource, lockInfo, taskDefinition));
                }

                var executionInfoLocal = new TaskExecutionInfo(null, ctSource, lockInfo, taskDefinition);

                var taskBody = CreateTaskBody(executionInfoLocal, taskTypeInfo);
                var task     = _managedThreadPool.QueueUserWorkItem((o) => taskBody(), null);

                executionInfoLocal.SetTask(task);

                return(executionInfoLocal);
            }
            catch (Exception ex)
            {
                ex.LogException();

                return(new TaskExecutionInfo(_managedThreadPool.CreateCompletedTask(), ctSource, lockInfo, taskDefinition));
            }
        }
示例#2
0
        private Action CreateTaskBody(TaskExecutionInfo executionInfoLocal, TaskTypeInfo taskTypeInfo)
        {
            return(() =>
            {
                try
                {
                    executionInfoLocal.SendAliveSignal();
                    executionInfoLocal.SetTaskThread(Thread.CurrentThread);

                    if (executionInfoLocal.CancellationTokenSource.IsCancellationRequested)
                    {
                        return;
                    }

                    if (!SetRunningStatus(executionInfoLocal, taskTypeInfo))
                    {
                        return;
                    }

                    executionInfoLocal.SendAliveSignal();

                    //Flags executionInfoLocal right before invoking the task implementation
                    executionInfoLocal.RealTaskInvokedFlag = true;
                    taskTypeInfo.Invoke(executionInfoLocal.TaskDefinition.JsonParameters, executionInfoLocal);

                    SetCompletedOrCancelledStatus(executionInfoLocal);
                }
                catch (ThreadAbortException ex)
                {
                    //Tries to save information about the task status.
                    //Reverts ThreadAbort
                    Thread.ResetAbort();

                    SetAbortedStatus(executionInfoLocal);
                }
                catch (Exception ex)
                {
                    ex.LogException();

                    SetCompletedOrCancelledStatus(executionInfoLocal);
                }
                finally
                {
                    try
                    {
                        //See comment below
                        executionInfoLocal.LockWillBeReleasedFlag = true;
                        _taskManager.LockManager.Release(executionInfoLocal.LockInfo);

                        //**** LockWillBeReleasedFlag avoids having the task being aborted right here when it's about to end, because we just released the lock
                        // and the lifetime manager could try to cancel it forcefully.
                    }
                    catch (Exception ex)
                    {
                        ex.LogException();
                    }
                }
            });
        }
        internal void Invoke(string jsonParameter, TaskExecutionInfo executionInfo)
        {
            object parameter = null;

            if (jsonParameter != null)
            {
                parameter = JsonConvert.DeserializeObject(jsonParameter, this.ParamType);
            }

            var instance = Activator.CreateInstance(this.TaskType);

            TaskTypeInfo.TypedInvoke((dynamic)instance, (dynamic)parameter, executionInfo);
        }
示例#4
0
        private bool SetRunningStatus(TaskExecutionInfo executionInfoLocal, TaskTypeInfo taskTypeInfo)
        {
            var lockInfo       = executionInfoLocal.LockInfo;
            var taskDefinition = executionInfoLocal.TaskDefinition;

            //It may be that the task scheduler took too long to start the thread.
            //Renews the lock. Ignores the task if it doesn't acquire lock
            if (!_taskManager.LockManager.TryRenewLock(lockInfo, taskTypeInfo.LockCycle, retryLock: true))
            {
                return(false);
            }

            using (var tr = new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled))
                using (var conn = _taskManager.CreateConnection())
                    using (var command = DbAccessHelper.CreateDbCommand(conn, SET_RUNNING_STATUS_SQL))
                    {
                        //milisecond precision
                        var lastRunAt = _taskManager.GetUtcNow().SetFractionalSecondPrecision(3);
                        var lockState = lockInfo.AsImmutable();

                        command.Parameters.Add(new SqlParameter("Id", taskDefinition.Id));
                        command.Parameters.Add(new SqlParameter("LastRunAt", System.Data.SqlDbType.DateTime2)
                        {
                            Value = lastRunAt
                        });
                        command.Parameters.Add(new SqlParameter("LockedUntil", System.Data.SqlDbType.DateTime2)
                        {
                            Value = lockState.LockedUntil
                        });

                        //Has the task been deleted or already handled?
                        if (command.ExecuteNonQuery() != 1)
                        {
                            return(false);
                        }

                        executionInfoLocal.LastRunAt = lastRunAt;

                        return(true);
                    }
        }
示例#5
0
        private void SetCompletedOrCancelledStatus(TaskExecutionInfo executionInfoLocal)
        {
            executionInfoLocal.SendAliveSignal();

            var lockInfo       = executionInfoLocal.LockInfo;
            var taskDefinition = executionInfoLocal.TaskDefinition;

            /* We should not renew lock here because the task has already completed */

            //If the task didn't run, don't do anything.
            if (executionInfoLocal.LastRunAt == null)
            {
                return;
            }

            try
            {
                using (var tr = new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled))
                    using (var conn = _taskManager.CreateConnection())
                        using (var command = DbAccessHelper.CreateDbCommand(conn, SET_COMPLETED_STATUS_FOR_RUNNING))
                        {
                            var newStatus = executionInfoLocal.IsCancellationRequested ? Distributed.SingleTaskStatus.CompletedCancelled : Distributed.SingleTaskStatus.Completed;

                            command.Parameters.Add(new SqlParameter("Id", taskDefinition.Id));
                            command.Parameters.Add(new SqlParameter("LastRunAt", System.Data.SqlDbType.DateTime2)
                            {
                                Value = executionInfoLocal.LastRunAt
                            });
                            command.Parameters.Add(new SqlParameter("NewStatus", (int)newStatus));

                            command.ExecuteNonQuery();
                        }
            }
            catch (Exception ex)
            {
                ex.LogException();
            }
        }
示例#6
0
        private void RenewTaskLock(TaskExecutionInfo taskInfo)
        {
            //renews lock
            if (_taskManager.LockManager.TryRenewLock(taskInfo.LockInfo))
            {
                try
                {
                    using (var tr = new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled))
                        using (var conn = _taskManager.CreateConnection())
                            using (var command = DbAccessHelper.CreateDbCommand(conn, SET_LOCKEDUNTIL_SQL))
                            {
                                var lockedUntil = taskInfo.LockInfo.AsImmutable().LockedUntil;
                                if (lockedUntil == null)
                                {
                                    return;
                                }

                                command.Parameters.Add(new SqlParameter("Id", taskInfo.TaskDefinition.Id));
                                command.Parameters.Add(new SqlParameter("LastRunAt", System.Data.SqlDbType.DateTime2)
                                {
                                    Value = taskInfo.LastRunAt
                                });
                                command.Parameters.Add(new SqlParameter("LockedUntil", System.Data.SqlDbType.DateTime2)
                                {
                                    Value = lockedUntil
                                });

                                command.ExecuteNonQuery();
                            }
                }
                catch (Exception ex)
                {
                    ex.LogException();
                }
            }
        }
 internal static void TypedInvoke <P>(IDistributedTask <P> instance, P parameter, TaskExecutionInfo executionInfo)
 {
     instance.Run(parameter, executionInfo);
 }