Beispiel #1
0
            /// <summary>
            /// Returns config for schedule next campaign job by default campaign fire period.
            /// Uses to local time convertion to include daylight offset and reverts next fire time to UTC.
            /// </summary>
            /// <param name="schema">Campaign schema.
            /// Instance of <see cref="Terrasoft.Core.Campaign.CampaignSchema"/>.</param>
            /// <param name="scheduledTimeParameters">Parameters for schedule new job for campaign.</param>
            /// <param name="previousStepCalculatedTime">Instance of <see cref="CampaignFireTimeConfig"/> that contains
            /// information for schedule next campaign job by previous calculation step.</param>
            /// <returns>Instance of <see cref="CampaignFireTimeConfig"/> that contains
            /// all needed information for schedule next campaign job by current step.</returns>
            internal override CampaignFireTimeConfig Calculate(CoreCampaignSchema schema,
                                                               CampaignScheduledTimeParameters scheduledTimeParameters,
                                                               CampaignFireTimeConfig previousStepCalculatedTime)
            {
                var fireTimeConfig = new CampaignFireTimeConfig {
                    Time = DateTime.MaxValue,
                    ExecutionStrategy = CampaignSchemaExecutionStrategy.DefaultPeriod
                };

                if (scheduledTimeParameters.CampaignStatusId != CampaignConsts.RunCampaignStatusId)
                {
                    fireTimeConfig.ScheduledAction = CampaignScheduledAction.Start;
                    fireTimeConfig.Time            = scheduledTimeParameters.CurrentTime;
                    return(fireTimeConfig);
                }
                var localStartDate       = TimeZoneInfo.ConvertTimeFromUtc(scheduledTimeParameters.StartDate, schema.TimeZoneOffset);
                var localBenchmarkTime   = TimeZoneInfo.ConvertTimeFromUtc(scheduledTimeParameters.BenchmarkTime, schema.TimeZoneOffset);
                var campaignLifeTime     = localBenchmarkTime - localStartDate;
                var toPreviousDefault    = (int)Math.Round(campaignLifeTime.TotalMinutes) % schema.DefaultCampaignFirePeriod;
                var nextLocalDefaultTime = toPreviousDefault == 0 && !scheduledTimeParameters.PreviousFireTime.HasValue
                                        ? localBenchmarkTime
                                        : localBenchmarkTime
                                           .AddMinutes(schema.DefaultCampaignFirePeriod - toPreviousDefault);

                fireTimeConfig.Time = ConvertToUtcByCampaignTimeZone(schema, nextLocalDefaultTime);
                return(CallNextStep(schema, scheduledTimeParameters, fireTimeConfig));
            }
Beispiel #2
0
        /// <summary>
        /// Returns config <see cref="CampaignExecutionLatenessConfig"/>, which describes lateness parameters.
        /// Lateness calculates relatively <paramref name="scheduledTime"/>.
        /// </summary>
        /// <param name="schema">Campaign's schema instance of
        /// <see cref="Terrasoft.Core.Campaign.CampaignSchema"/></param>
        /// <param name="scheduledTime">Time relatively this need calculate lateness config.</param>
        /// <returns>Returns instance <see cref="CampaignExecutionLatenessConfig"/>.</returns>
        public CampaignExecutionLatenessConfig GetLatenessConfig(CoreCampaignSchema schema, DateTime scheduledTime)
        {
            schema.CampaignConfiguration["ScheduledUtcFireTime"] = RoundToSeconds(scheduledTime);
            var latenessTime     = RoundToMinutes(CurrentTime - scheduledTime);
            var criticalLateness = schema.CriticalExecutionLateness;
            var latenessConfig   = new CampaignExecutionLatenessConfig {
                MisfiredTimeConditionElements = new List <CampaignSchemaElement>(),
                LatenessTime = latenessTime,
                Lateness     = CampaignExecutionLateness.NoMisfire
            };

            if (latenessTime.TotalMinutes <= 0)
            {
                return(latenessConfig);
            }
            var misfiredTimedElements = GetMisfiredTimedElements(schema, scheduledTime, CurrentTime);

            latenessConfig.MisfiredTimeConditionElements = misfiredTimedElements;
            if (latenessTime.TotalMinutes <= criticalLateness)
            {
                latenessConfig.Lateness = !misfiredTimedElements.Any()
                                        ? CampaignExecutionLateness.NoMisfire
                                        : CampaignExecutionLateness.MisfiredTimeConditionElements;
            }
            else
            {
                latenessConfig.Lateness = !misfiredTimedElements.Any()
                                        ? CampaignExecutionLateness.Critical
                                        : CampaignExecutionLateness.CriticalAndMisfiredTimeConditionElements;
            }
            return(latenessConfig);
        }
Beispiel #3
0
            /// <summary>
            /// Converts local date and time to UTC based on current campaign time zone.
            /// If date is not valid (for example 26.03.2017 03:00-04:00 for Kiev GMT+02:00)
            /// Shifts it to the future by campaign default period.
            /// </summary>
            /// <param name="schema">Campaign schema.
            /// Instance of <see cref="Terrasoft.Core.Campaign.CampaignSchema"/>.</param>
            /// <param name="localTime">Local <see cref="System.DateTime"/> date and time to convert to UTC.</param>
            /// <returns>UTC <see cref="System.DateTime"/> with daylight offset.</returns>
            private DateTime ConvertToUtcByCampaignTimeZone(CoreCampaignSchema schema, DateTime localTime)
            {
                if (localTime.Kind == DateTimeKind.Utc)
                {
                    return(localTime);
                }
                var defaultPeriodAddingCount = 100;

                if (schema.TimeZoneOffset.IsInvalidTime(localTime))
                {
                    for (int i = 0; i < defaultPeriodAddingCount; i++)
                    {
                        localTime = localTime.AddMinutes(schema.DefaultCampaignFirePeriod);
                        if (!schema.TimeZoneOffset.IsInvalidTime(localTime))
                        {
                            break;
                        }
                    }
                    if (schema.TimeZoneOffset.IsInvalidTime(localTime))
                    {
                        var message = CampaignHelper
                                      .GetLczStringValue(nameof(CampaignTimeScheduler), "IsInvalidTimeOutOfRangeIterationError");
                        throw new Exception(message);
                    }
                }
                return(TimeZoneInfo.ConvertTimeToUtc(localTime, schema.TimeZoneOffset));
            }
 /// <summary>
 /// Reschedule job for the specified campaign.
 /// </summary>
 /// <param name="schema">The <see cref="Terrasoft.Core.Campaign.CampaignSchema"/> object for wich Job plans.</param>
 /// <param name="fireTimeConfig">Fire time config for job.</param>
 public void RescheduleJob(CoreCampaignSchema schema, CampaignFireTimeConfig fireTimeConfig)
 {
     lock (_rescheduleLockObject) {
         RemoveJobs(schema.EntityId);
         ScheduleJob(schema, fireTimeConfig);
     }
 }
 /// <summary>
 /// Schedule next job for the specified campaign.
 /// </summary>
 /// <param name="schema">The <see cref="Terrasoft.Core.Campaign.CampaignSchema"/> object for wich Job plans.</param>
 /// <param name="fireTimeConfig">Fire time config for job.</param>
 public void ScheduleJob(CoreCampaignSchema schema, CampaignFireTimeConfig fireTimeConfig)
 {
     try {
         schema.CheckArgumentNull(nameof(schema));
         fireTimeConfig.CheckArgumentNull(nameof(fireTimeConfig));
         Guid campaignId        = schema.EntityId;
         var  campaignJobName   = GetCampaignJobName(campaignId, fireTimeConfig.Time);
         var  sysUserConnection = _userConnection.AppConnection.SystemUserConnection;
         var  parameters        = new Dictionary <string, object> {
             { "CampaignSchemaUId", schema.UId },
             { "ScheduledUtcFireTime", fireTimeConfig.Time },
             { "SchemaGeneratorStrategy", fireTimeConfig.ExecutionStrategy },
             { "ScheduledAction", (int)fireTimeConfig.ScheduledAction }
         };
         IJobDetail job = AppScheduler.CreateClassJob <CampaignJobExecutor>(campaignJobName,
                                                                            CampaignConsts.CampaignJobGroupName, sysUserConnection, parameters);
         ITrigger trigger = new SimpleTriggerImpl(campaignJobName + "Trigger",
                                                  CampaignConsts.CampaignJobGroupName, fireTimeConfig.Time)
         {
             MisfireInstruction = MisfireInstruction.IgnoreMisfirePolicy
         };
         AppScheduler.Instance.ScheduleJob(job, trigger);
         LogScheduledJob(schema.EntityId, fireTimeConfig);
     } catch (Exception ex) {
         string message = CampaignHelper.GetLczStringValue(nameof(CampaignJobDispatcher), "ScheduleException");
         Logger.ErrorFormat(message, ex, schema == null ? Guid.Empty : schema.EntityId);
         throw;
     }
 }
Beispiel #6
0
 /// <summary>
 /// Calls next step in chain and returns result from this step.
 /// </summary>
 /// <param name="schema">Campaign schema.
 /// Instance of <see cref="Terrasoft.Core.Campaign.CampaignSchema"/></param>
 /// <param name="scheduledTimeParameters">Parameters which describes campaign state
 /// and includes parameters for calculates next fire time.</param>
 /// <param name="previousStepCalculatedTime"><see cref="CampaignFireTimeConfig"/> containes
 /// current step calculation result.</param>
 /// <returns>Returns <paramref name="previousStepCalculatedTime"/> when <see cref="NextCalculator"/>
 /// is not defined. And result of calculation from next step in otherwise.</returns>
 protected CampaignFireTimeConfig CallNextStep(CoreCampaignSchema schema,
                                               CampaignScheduledTimeParameters scheduledTimeParameters,
                                               CampaignFireTimeConfig previousStepCalculatedTime)
 {
     return(NextCalculator == null
                             ? previousStepCalculatedTime
                             : NextCalculator.Calculate(schema, scheduledTimeParameters, previousStepCalculatedTime));
 }
Beispiel #7
0
        private IEnumerable <CampaignSchemaElement> GetMisfiredTimedElements(CoreCampaignSchema schema,
                                                                             DateTime startTime, DateTime endTime)
        {
            var transitionElements = schema.FlowElements.OfType <ConditionalSequenceFlowElement>();
            var timerElements      = schema.FlowElements.OfType <CampaignTimerElement>();

            return(GetMisfiredTimedElements(transitionElements.Union <CampaignSchemaElement>(timerElements),
                                            startTime, endTime));
        }
Beispiel #8
0
            internal override CampaignFireTimeConfig Calculate(CoreCampaignSchema schema,
                                                               CampaignScheduledTimeParameters scheduledTimeParameters,
                                                               CampaignFireTimeConfig previousStepCalculatedTime)
            {
                var timerElements = schema.FlowElements.OfType <CampaignTimerElement>();
                CampaignFireTimeConfig fireTimeConfig = GetTimedElementsNextFireTime(timerElements, scheduledTimeParameters);

                return(CallNextStepWithMinValue(schema, scheduledTimeParameters, previousStepCalculatedTime,
                                                fireTimeConfig));
            }
Beispiel #9
0
        /// <summary>
        /// Returns next fire time for campaign's schema.
        /// </summary>
        /// <param name="schema">Campaign schema.
        /// Instance of <see cref="Terrasoft.Core.Campaign.CampaignSchema"/></param>
        /// <param name="previousScheduledFireTime">Time of the previous campaign run.
        /// It can be null when need calculate next fire time relatively current time.</param>
        /// <returns>Returns instance of <see cref="CampaignFireTimeConfig"/> that contains
        /// all needed information for schedule next campaign job.</returns>
        public CampaignFireTimeConfig GetNextFireTime(CoreCampaignSchema schema,
                                                      DateTime?previousScheduledFireTime)
        {
            var scheduledParameters = GetScheduledParameters(schema.EntityId);

            DefinesTimeParameters(schema, previousScheduledFireTime, scheduledParameters);
            var resultConfig = TimeCalculator.Calculate(schema, scheduledParameters, new CampaignFireTimeConfig());

            resultConfig.Time = DateTime.SpecifyKind(RoundToSeconds(resultConfig.Time), DateTimeKind.Utc);
            return(resultConfig);
        }
Beispiel #10
0
 private void DefinesTimeParameters(CoreCampaignSchema schema, DateTime?previousScheduledFireTime,
                                    CampaignScheduledTimeParameters scheduledParameters)
 {
     scheduledParameters.PreviousFireTime = previousScheduledFireTime
                                            ?? (scheduledParameters.PrevExecutedOn != default(DateTime)
                                 ? scheduledParameters.PrevExecutedOn
                                 : (DateTime?)null);
     scheduledParameters.CurrentTime   = CurrentTime;
     scheduledParameters.BenchmarkTime = scheduledParameters.PreviousFireTime ?? scheduledParameters.CurrentTime;
     schema.CampaignConfiguration["ScheduledUtcFireTime"] = RoundToSeconds(scheduledParameters.BenchmarkTime);
 }
Beispiel #11
0
            internal override CampaignFireTimeConfig Calculate(CoreCampaignSchema schema,
                                                               CampaignScheduledTimeParameters scheduledTimeParameters,
                                                               CampaignFireTimeConfig previousStepCalculatedTime)
            {
                var elements = schema.FlowElements
                               .Where(x => x.ElementType.HasFlag(CampaignSchemaElementType.Transition));
                var fireTimeConfig = GetTimedElementsNextFireTime(elements, scheduledTimeParameters);

                return(CallNextStepWithMinValue(schema, scheduledTimeParameters, previousStepCalculatedTime,
                                                fireTimeConfig));
            }
Beispiel #12
0
            /// <summary>
            /// Calls next step in chain with min value between <paramref name="previousStepCalculatedTime"/> and
            /// <paramref name="comparedCalculatedTime"/> and returns result from calculates next step.
            /// </summary>
            /// <param name="schema">Campaign schema.
            /// Instance of <see cref="Terrasoft.Core.Campaign.CampaignSchema"/></param>
            /// <param name="scheduledTimeParameters">Parameters which describes campaign state
            /// and includes parameters for calculates next fire time.</param>
            /// <param name="previousStepCalculatedTime"><see cref="CampaignFireTimeConfig"/> containes
            /// current step calculation result.</param>
            /// <param name="comparedCalculatedTime">This config should compare with
            /// <paramref name="previousStepCalculatedTime"/> and with minimum of this calls
            /// <see cref="CallNextStep(CoreCampaignSchema, CampaignScheduledTimeParameters, CampaignFireTimeConfig)"/>
            /// method.</param>
            /// <returns>Returns <paramref name="previousStepCalculatedTime"/> when <see cref="NextCalculator"/>
            /// is not defined. And result of calculation from next step in otherwise.</returns>
            protected CampaignFireTimeConfig CallNextStepWithMinValue(CoreCampaignSchema schema,
                                                                      CampaignScheduledTimeParameters scheduledTimeParameters,
                                                                      CampaignFireTimeConfig previousStepCalculatedTime,
                                                                      CampaignFireTimeConfig comparedCalculatedTime)
            {
                var minFireTime = comparedCalculatedTime.Time < previousStepCalculatedTime.Time &&
                                  comparedCalculatedTime.Time != default(DateTime)
                                        ? comparedCalculatedTime
                                        : previousStepCalculatedTime;

                return(CallNextStep(schema, scheduledTimeParameters, minFireTime));
            }
 /// <summary>
 /// Schedule next job for the specified campaign.
 /// </summary>
 /// <param name="campaignSchemaUId">The unique identifier of campaign schema instance.</param>
 /// <param name="fireTimeConfig">Fire time config for job.</param>
 public void ScheduleJob(Guid campaignSchemaUId, CampaignFireTimeConfig fireTimeConfig)
 {
     try {
         var schemaManager = (CampaignSchemaManager)_userConnection.GetSchemaManager("CampaignSchemaManager");
         CoreCampaignSchema campaignSchema = schemaManager.GetSchemaInstance(campaignSchemaUId);
         ScheduleJob(campaignSchema, fireTimeConfig);
     } catch (Exception ex) {
         string message = CampaignHelper.GetLczStringValue(nameof(CampaignJobDispatcher),
                                                           "ScheduleBySchemaUIdException");
         Logger.ErrorFormat(message, ex, campaignSchemaUId);
         throw;
     }
 }
Beispiel #14
0
        /// <summary>
        /// Returns next fire time for campaign.
        /// When <paramref name="previousScheduledFireTime"/> is null then used
        /// <see cref="DateTime.UtcNow"/> as benchmark point for calculation.
        /// </summary>
        /// <param name="campaignId">Campaign identifier.</param>
        /// <param name="useCurrentUserTimezone">Flag that indicates add current user
        /// timezone offset to next campaign scheduled time(in UTC) or not.</param>
        /// <param name="previousScheduledFireTime">Time of the previous campaign run.
        /// It can be null when need calculate next fire time relatively current time.</param>
        /// <returns>Returns campaign's next run time.</returns>
        public DateTime GetCampaignNextFireTime(Guid campaignId, bool useCurrentUserTimezone,
                                                DateTime?previousScheduledFireTime = null)
        {
            var schemaUid     = GetCampaignSchemaUid(campaignId);
            var benchmarkTime = previousScheduledFireTime ?? new DateTime(CurrentTime.Year, CurrentTime.Month,
                                                                          CurrentTime.Day, CurrentTime.Hour, CurrentTime.Minute, 0, DateTimeKind.Utc);
            var schemaManager = (CampaignSchemaManager)_userConnection.GetSchemaManager("CampaignSchemaManager");
            CoreCampaignSchema campaignSchema = schemaManager.GetSchemaInstance(schemaUid);
            var scheduledUtcFireTime          = GetNextFireTime(campaignSchema, benchmarkTime);

            if (useCurrentUserTimezone)
            {
                return(scheduledUtcFireTime.Time.AddMinutes(UserTimeZoneOffset.TotalMinutes));
            }
            return(scheduledUtcFireTime.Time);
        }
Beispiel #15
0
            internal override CampaignFireTimeConfig Calculate(CoreCampaignSchema schema,
                                                               CampaignScheduledTimeParameters scheduledTimeParameters,
                                                               CampaignFireTimeConfig previousStepCalculatedTime)
            {
                var fireTimeConfig = previousStepCalculatedTime;

                if (scheduledTimeParameters.ScheduledStopModeId == CampaignConsts.CampaingSpecifiedTimeModeId &&
                    previousStepCalculatedTime.Time >= scheduledTimeParameters.ScheduledStopDate)
                {
                    fireTimeConfig = new CampaignFireTimeConfig {
                        Time = new DateTime(scheduledTimeParameters.ScheduledStopDate.Ticks, DateTimeKind.Utc),
                        ExecutionStrategy = CampaignSchemaExecutionStrategy.DefaultPeriod,
                        ScheduledAction   = CampaignScheduledAction.ScheduledStop
                    };
                }
                return(CallNextStep(schema, scheduledTimeParameters, fireTimeConfig));
            }
Beispiel #16
0
 internal override CampaignFireTimeConfig Calculate(CoreCampaignSchema schema,
                                                    CampaignScheduledTimeParameters scheduledTimeParameters,
                                                    CampaignFireTimeConfig previousStepCalculatedTime)
 {
     if (scheduledTimeParameters.CampaignStatusId == CampaignConsts.StoppingCampaignStatusId)
     {
         return(new CampaignFireTimeConfig {
             Time = scheduledTimeParameters.CurrentTime,
             ScheduledAction = CampaignScheduledAction.Stop,
             ExecutionStrategy = CampaignSchemaExecutionStrategy.DefaultPeriod
         });
     }
     if (scheduledTimeParameters.ScheduledStopModeId == CampaignConsts.CampaingSpecifiedTimeModeId &&
         scheduledTimeParameters.CurrentTime >= scheduledTimeParameters.ScheduledStopDate)
     {
         return(new CampaignFireTimeConfig {
             Time = scheduledTimeParameters.ScheduledStopDate,
             ScheduledAction = CampaignScheduledAction.ScheduledStop,
             ExecutionStrategy = CampaignSchemaExecutionStrategy.DefaultPeriod
         });
     }
     return(CallNextStep(schema, scheduledTimeParameters, previousStepCalculatedTime));
 }
Beispiel #17
0
 internal virtual CampaignFireTimeConfig Calculate(CoreCampaignSchema schema,
                                                   CampaignScheduledTimeParameters scheduledTimeParameters,
                                                   CampaignFireTimeConfig previousStepCalculatedTime)
 {
     return(new CampaignFireTimeConfig());
 }