public Activity(IDataReader reader)
 {
     Id        = reader.SafeGet <int>("ID");
     Label     = reader.SafeGet <string>("LABEL", String.Empty);
     LabelLang = reader.SafeGet <string>("LABEL_LANG", String.Empty);
     Details   = reader.SafeGet <string>("INBOX_DETAIL", String.Empty);
     DueDate   = reader.SafeGet <DateTime>("DUE_DATE", BuiltInFunction.NullDate());
     IsOpened  = reader.SafeGet <bool>("OPENED");
     IsSeen    = reader.SafeGet <bool>("SEEN");
 }
Esempio n. 2
0
        public static bool IsRunnableActivity(DateTime isRunningSince, ActivityStatus?forInitialStatus, ActivityStatus currentStatus, DateTime previousNextRun, DateTime nextRun)
        {
            //#605602 - Ensure the activity is not already running "isRunningSince"
            //Ensure the conditions that made the scheduler request the activity to run have not changed. "currentStatus" and "nextRun"
            bool runnable = (isRunningSince == BuiltInFunction.NullDate()) &&
                            (!forInitialStatus.HasValue || forInitialStatus.Value == currentStatus) &&
                            (previousNextRun == BuiltInFunction.NullDate() ||
                             //#1188860 - To avoid issues with daylight saving time, use universal time to compare the two date times
                             (Math.Abs((previousNextRun.ToUniversalTime() - nextRun.ToUniversalTime()).TotalMilliseconds) < 1));

            return(runnable);
        }
        /// <summary>
        /// Returns (currently not used): 1 if scheduler should retry later; 0 otherwise
        /// </summary>
        /// <param name="heContext"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public static int Execute(HeContext heContext, int timeout)
        {
            string   schedule;
            int      cyclicJobId;
            bool     isShared;
            DateTime dbNow, newNextRun;

            int eSpaceId = Global.eSpaceId;
            int tenantId = heContext.AppInfo.Tenant.Id;

            string   errorLogId = "";
            DateTime dbStartTime, lastRun, nextRun, previousNextRun, isRunnSince;
            DateTime localStartedDateTime = DateTime.Now;             // used to measure the timer duration
            DateTime newIsRunningSince, currentIsRunningSince;
            int      duration = 0;
            string   isRunningBy;
            int      numberOfTries      = 0;
            int      maxNumberOfRetries = RuntimePlatformSettings.Timers.NumberOfRetries.GetValue();

            // ExceptionLogged signals that this type of exception has been logged
            bool ExceptionLogged = false;

            try {
                try {
                    using (Transaction mainTrans = DatabaseAccess.ForRuntimeDatabase.GetRequestTransaction()) {
                        dbStartTime = DBRuntimePlatform.Instance.GetDbDatetime(mainTrans);
                        cyclicJobId = DBRuntimePlatform.Instance.GetCyclicJobId(mainTrans, eSpaceId, tenantId, TimerKey, out isShared);
                    }
                    using (Transaction privTrans = DatabaseAccess.ForRuntimeDatabase.GetCommitableTransaction()) {
                        try {
                            bool ok = DBRuntimePlatform.Instance.GetCyclicJobForUpdate(privTrans, cyclicJobId, isShared, out isRunnSince,
                                                                                       out schedule, out lastRun, out previousNextRun, out isRunningBy);
                            if (!ok)
                            {
                                throw new DataBaseException("Unable to get data for Bootstrap Timer (" + cyclicJobId + ") in Execute method.");
                            }

                            // return if not yet time to execute
                            if (dbStartTime.CompareTo(previousNextRun) < 0)
                            {
                                return(0);
                            }

                            // some node is executing it
                            if (isRunnSince != BuiltInFunction.NullDate())
                            {
                                // In normal cases, it will return from execution because
                                // some other node is executing this timer
                                if (dbStartTime.CompareTo(isRunnSince.AddSeconds(1.2 * timeout)) < 0)
                                {
                                    return(0);
                                }

                                // recover mechanism: if it is executing for too long
                                // maybe there was a problem with the node, but the database
                                // was left with data stating it is still executing.

                                TimeSpan ts;
                                string   recoverDetail = "";
                                try {
                                    string isRunnBy = "?";
                                    ts            = (dbStartTime - isRunnSince);
                                    recoverDetail = "Marked as running since " + isRunnSince.ToString() + " (" + ts.TotalMinutes.ToString() + " minutes) by hubnode '" + isRunnBy + "'. Timeout defined is " + (timeout / 60.0).ToString() + " minutes";
                                } catch {}
                                ErrorLog.LogApplicationError("Recovering timer Bootstrap execution. It is marked as running for too long", recoverDetail, heContext, "");
                            }

                            // lets update db, stating that I'm executing the job
                            numberOfTries = DBRuntimePlatform.Instance.GetNumberOfTries(privTrans, cyclicJobId, isShared);
                            if (numberOfTries >= maxNumberOfRetries)
                            {
                                DBRuntimePlatform.Instance.GetTimerScheduleNextRunAndDbDate(privTrans, cyclicJobId, isShared, out schedule, out dbNow, out newNextRun, out currentIsRunningSince);
                                RuntimeScheduler.NextRun(schedule, dbNow, out nextRun);
                                DBRuntimePlatform.Instance.SetTimerNextRun(privTrans, cyclicJobId, isShared, nextRun);
                                errorLogId = ErrorLog.StaticWrite(DateTime.Now, heContext.Session.SessionID, heContext.AppInfo.eSpaceId, heContext.AppInfo.Tenant.Id, heContext.Session.UserId, String.Format("Timer Bootstrap reached maximum number of retries ({0}) [Calculating next run]", maxNumberOfRetries), "", "");
                                duration   = (int)((TimeSpan)(DateTime.Now - localStartedDateTime)).TotalSeconds;

                                // lets update the rest of the cyclic job stuff...
                                DBRuntimePlatform.Instance.SetTimerLastRun(privTrans, cyclicJobId, isShared, dbStartTime, duration);

                                CyclicJobLog jobLog = new CyclicJobLog();
                                jobLog.Write(dbStartTime,
                                             duration,
                                             TimerKey,
                                             heContext.AppInfo.eSpaceId,
                                             heContext.AppInfo.Tenant.Id,
                                             RuntimeEnvironment.MachineName,
                                             errorLogId,
                                             previousNextRun,
                                             nextRun,
                                             heContext.AppInfo.eSpaceName,
                                             heContext.AppInfo.ApplicationName,
                                             heContext.AppInfo.ApplicationUIDAsKey,
                                             TimerName);
                                return(0);
                            }
                            DBRuntimePlatform.Instance.SetTimerRunningBy(privTrans, cyclicJobId, isShared, RuntimeEnvironment.MachineName, out newIsRunningSince);
                            DBRuntimePlatform.Instance.IncrementNumberOfTries(privTrans, cyclicJobId, isShared);
                        } finally {
                            privTrans.Commit();
                            // NOTE: Must release and reget the session... the timer action might commit or something!
                        }
                    }
                } catch (Exception e) {
                    duration        = (int)((TimeSpan)(DateTime.Now - localStartedDateTime)).TotalSeconds;
                    errorLogId      = ErrorLog.LogApplicationError("Timer Bootstrap error (before executing action 'BootstrapContacts'). Timer duration = " + duration + " secs: " + e.Message + " [Will retry later]", e.ToString(), heContext, "");
                    ExceptionLogged = true;
                    return(1);                    // assume some error in update, so it will retry later...
                }
                // from tests in framework 1.0, it seems this ScriptTimeout is not working as expected...
                // but it seems in framework 1.1 it works fine (if not in debug mode)
                heContext.Context.Server.ScriptTimeout = timeout;

                try {
                    Actions.ActionBootstrapContacts(heContext);
                } catch (Exception e) {
                    // error in timer action: we must rollback all pending transactions
                    DatabaseAccess.RollbackAllTransactions();
                    using (Transaction mainTrans = DatabaseAccess.ForRuntimeDatabase.GetRequestTransaction()) {
                        if (!ExceptionLogged)                           // if already logged, don't log the same error
                        {
                            duration = (int)((TimeSpan)(DateTime.Now - localStartedDateTime)).TotalSeconds;

                            currentIsRunningSince = DBRuntimePlatform.Instance.GetTimerRunningSince(mainTrans, cyclicJobId, isShared);
                            if (currentIsRunningSince != newIsRunningSince)
                            {
                                ErrorLog.LogApplicationError("Timer 'Bootstrap' Running Since Date changed unexpectedly. Expected '" + BuiltInFunction.DateTimeToText(newIsRunningSince) + "' but was '" + BuiltInFunction.DateTimeToText(currentIsRunningSince) + "'.", "", heContext, "");
                            }

                            DBRuntimePlatform.Instance.ClearTimerRunningBy(mainTrans, cyclicJobId, isShared);
                            ExceptionLogged = true;
                            errorLogId      = ErrorLog.LogApplicationError("Timer Bootstrap error (inside action 'BootstrapContacts'). Timer duration = " + duration + " secs:" + e.Message + String.Format(" [retry {0} of {1} scheduled]", numberOfTries + 1, maxNumberOfRetries), e.ToString(), heContext, "");
                            CyclicJobLog jobLog = new CyclicJobLog();
                            jobLog.Write(
                                dbStartTime,
                                duration,
                                TimerKey,
                                heContext.AppInfo.eSpaceId,
                                heContext.AppInfo.Tenant.Id,
                                RuntimeEnvironment.MachineName,
                                errorLogId,
                                previousNextRun,
                                previousNextRun,
                                heContext.AppInfo.eSpaceName,
                                heContext.AppInfo.ApplicationName,
                                heContext.AppInfo.ApplicationUIDAsKey,
                                TimerName);
                            return(0);
                        }
                    }
                }

                using (Transaction mainTrans = DatabaseAccess.ForRuntimeDatabase.GetRequestTransaction()) {
                    try {
                        // calculate next run based on current date in db server and also
                        // on scheduler (that may have been changed inside the user action
                        // for example)

                        DBRuntimePlatform.Instance.GetTimerScheduleNextRunAndDbDate(mainTrans, cyclicJobId, isShared, out schedule, out dbNow, out newNextRun, out currentIsRunningSince);

                        RuntimeScheduler.NextRun(schedule, dbNow, out nextRun);

                        if (newNextRun == previousNextRun)
                        {
                            DBRuntimePlatform.Instance.SetTimerNextRun(mainTrans, cyclicJobId, isShared, nextRun);
                        }
                        else
                        {
                            nextRun = newNextRun;
                        }

                        duration = (int)((TimeSpan)(DateTime.Now - localStartedDateTime)).TotalSeconds;

                        if (currentIsRunningSince != newIsRunningSince)
                        {
                            ErrorLog.LogApplicationError("Timer 'Bootstrap' Running Since Date changed unexpectedly. Expected '" + BuiltInFunction.DateTimeToText(newIsRunningSince) + "' but was '" + BuiltInFunction.DateTimeToText(currentIsRunningSince) + "'.", "", heContext, "");
                        }
                        // lets update the rest of the cyclic job stuff...
                        DBRuntimePlatform.Instance.SetTimerLastRun(mainTrans, cyclicJobId, isShared, dbStartTime, duration);
                        DBRuntimePlatform.Instance.ResetNumberOfTries(mainTrans, cyclicJobId, isShared);

                        CyclicJobLog jobLog = new CyclicJobLog();
                        jobLog.Write(
                            dbStartTime,
                            duration,
                            TimerKey,
                            heContext.AppInfo.eSpaceId,
                            heContext.AppInfo.Tenant.Id,
                            RuntimeEnvironment.MachineName,
                            errorLogId,
                            previousNextRun,
                            nextRun,
                            heContext.AppInfo.eSpaceName,
                            heContext.AppInfo.ApplicationName,
                            heContext.AppInfo.ApplicationUIDAsKey,
                            TimerName);
                        return(0);
                    } catch (Exception e) {
                        if (!ExceptionLogged)                           // if already logged, don't log the same error
                        {
                            duration        = (int)((TimeSpan)(DateTime.Now - localStartedDateTime)).TotalSeconds;
                            errorLogId      = ErrorLog.LogApplicationError("Timer Bootstrap error (after executing action 'BootstrapContacts'). Timer duration = " + duration + " secs: " + e.Message + " [Will retry later]", e.ToString(), heContext, "");
                            ExceptionLogged = true;
                        }
                        return(1);                        // assume some error in update, so it will retry later...
                    }
                }
            } catch (Exception e) {
                if (!ExceptionLogged)                   // if already logged, don't log the same error
                {
                    duration        = (int)((TimeSpan)(DateTime.Now - localStartedDateTime)).TotalSeconds;
                    errorLogId      = ErrorLog.LogApplicationError("Timer Bootstrap error. Timer duration = " + duration + " secs: " + e.Message + " [Will retry later]", e.ToString(), heContext, "");
                    ExceptionLogged = true;
                }
                return(1);
            }
        }
 public System.IAsyncResult BeginExecuteActivityAction(string ssKey, int activityId, int processId, int tenantId, ActivityStatus forInitialStatus, System.AsyncCallback callback, object asyncState)
 {
     return(BeginExecuteActivityActionv2(ssKey, activityId, processId, tenantId, forInitialStatus, BuiltInFunction.NullDate(), callback, asyncState));
 }
 // Execute Activity Action
 public bool ExecuteActivityAction(string ssKey, int activityId, int processId, int tenantId, ActivityStatus forInitialStatus)
 {
     return(ExecuteActivityActionv2(ssKey, activityId, processId, tenantId, forInitialStatus, BuiltInFunction.NullDate()));
 }
Esempio n. 6
0
        protected void StartActivityExecution(HeContext heContext, int activityId, int processId, ActivityStatus?forInitialStatus, out bool runnable, out ActivityStatus currentStatus, DateTime previousNextRun)
        {
            runnable = false;

            using (Transaction trans = DatabaseAccess.ForSystemDatabase.GetRequestTransaction()) {
                int tenantId = heContext.AppInfo.Tenant.Id;
                int precedentActivityId;
                int precedentActivitySuccessorsCount;
                int rootProcessId;
                if (Debugger.IsRunning)
                {
                    rootProcessId       = DBRuntimePlatform.Instance.GetTopProcessId(trans, processId);
                    precedentActivityId = DBRuntimePlatform.Instance.GetPrecedentActivityId(trans, activityId);
                    if (precedentActivityId == BuiltInFunction.NullIdentifier() && rootProcessId != processId)
                    {
                        // the precendent activity is the activity that launched the subprocess. We need to get
                        // an activity from the same eSpace we're in, because external processes are not executed
                        // in the same web app (contrary to what happens when debugging reference actions, whose code
                        // is all in the consumer eSpace)
                        precedentActivityId = DBRuntimePlatform.Instance.GetAncestorActivityIdInTenant(trans, processId, RunningInfo.TenantId);
                    }

                    precedentActivitySuccessorsCount = DBRuntimePlatform.Instance.GetActivitySuccessorsCount(trans, precedentActivityId);
                }
                else
                {
                    rootProcessId       = 0;
                    precedentActivityId = -1;
                    precedentActivitySuccessorsCount = 0;
                }
                SetCurrentProcessInfo(processId, activityId, precedentActivityId, precedentActivitySuccessorsCount, rootProcessId);

                if (DBRuntimePlatform.Instance.GetProcessStatus(trans, processId) == ProcessStatus.Suspended)
                {
                    throw new InvalidOperationException("Could not execute a built-in/extended action on activity '" + Name + "' (#" + activityId
                                                        + ") because its process is suspended.");
                }

                using (IDataReader reader = DBRuntimePlatform.Instance.GetActivity(trans, tenantId, activityId, true)) {
                    if (reader.Read())
                    {
                        DateTime nextRun = (DateTime)reader.SafeGet <DateTime>("NEXT_RUN");
                        currentStatus = (ActivityStatus)reader.SafeGet <int>("STATUS_ID");

                        DateTime isRunningSince = reader.SafeGet <DateTime>("IS_RUNNING_SINCE", BuiltInFunction.NullDate());

                        runnable = IsRunnableActivity(isRunningSince, forInitialStatus, currentStatus, previousNextRun, nextRun);
                    }
                    else
                    {
                        throw new InvalidOperationException("Could not execute a built-in/extended action on activity '" + Name + "' (#" + activityId
                                                            + ") because the activity does not exist.");
                    }
                }

                if (runnable)
                {
                    DBRuntimePlatform.Instance.UpdateActivity(trans, tenantId, activityId, null, null, null, null, null, null, null, null,
                                                              true, Settings.MachineName, null, null, null, null, null, null, null, null, null);
                }
            }

            DatabaseAccess.CommitAllTransactions();
        }
Esempio n. 7
0
 protected void StartActivityExecution(HeContext heContext, int activityId, int processId, ActivityStatus?forInitialStatus, out bool runnable, out ActivityStatus currentStatus)
 {
     StartActivityExecution(heContext, activityId, processId, null, out runnable, out currentStatus, BuiltInFunction.NullDate());
 }