Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Gordon Saxby 1461 posts 1883 karma points
    Jan 10, 2023 @ 12:24
    Gordon Saxby
    0

    Use RecurringHostedServiceBase to run at a specific time

    Looking to use RecurringHostedServiceBase to run a task at a specific time each day, but that doesn't appear to be an option?

    https://docs.umbraco.com/v/10.x-lts/umbraco-cms/reference/scheduling

    Is it simply a case of running it frequently (?) and checking to see if it's the right time before continuing?

  • Marc Goodson 2157 posts 14431 karma points MVP 9x c-trib
    Jan 12, 2023 @ 23:36
    Marc Goodson
    0

    Hi Gordon

    There are two settings that you pass into the base recurring task, one called

    DelayBeforeWeStart

    And another called

    HowOftenWeRepeat

    So the DelayBeforeWeStart is a time span from when the task is registered when it first runs..

    And HowOftenWeRepeat more obviously the time span in between each running of the task..

    ... So since these two values are set in code, if you wanted the task to run everyday at the same time.... You'd set the DelayBeforeWeStart value to be the time span between 'Now' and the time you want it to run...

    Which will be different depending on whenever the site restarts...

    ... If that makes sense.?

    Regards

    Marc

  • Gordon Saxby 1461 posts 1883 karma points
    Jan 13, 2023 @ 12:46
    Gordon Saxby
    0

    Ah, OK.

    So, HowOftenWeRepeat would be

    private static TimeSpan HowOftenWeRepeat => TimeSpan.FromDays(1);
    

    How do I calculate and then pass the value for DelayBeforeWeStart? Not so much calculate it, but pass it to "base" in the constructor? The run at time is defined in appSettings.

    private static TimeSpan HowOftenWeRepeat => TimeSpan.FromDays(1);
    private static TimeSpan DelayBeforeWeStart => TimeSpan.FromSeconds(?);
    
    public ScheduledUpdates(
        IRuntimeState runtimeState, 
        ILogger<ScheduledUpdates> logger,
        IConfiguration config) : base(logger, HowOftenWeRepeat, DelayBeforeWeStart)
    {
        _runtimeState = runtimeState;
        _logger = logger;
        _config = config;
    }
    
  • Marc Goodson 2157 posts 14431 karma points MVP 9x c-trib
    Jan 13, 2023 @ 15:29
    Marc Goodson
    0

    Hi Gordon

    So would you be able to set

    DelayBeforeWeStart => GetDelayBeforeWeStart();

    and have that function return the number of seconds?

    and that function would have something like this in?

    eg to run at eleven thirty in the evening:

    var nowTime = DateTime.Now;
            var nextRunTime = new DateTime(nowTime.Year, nowTime.Month, nowTime.Day, 23, 30, 0);
            if (nextRunTime < nowTime)
            {
                nextRunTime = nextRunTime.AddDays(1);
            }
            var timeTilNextRunTime = (nextRunTime - nowTime).TotalSeconds;
    

    sorry I am guessing a bit!

    regards

    Marc

  • Gordon Saxby 1461 posts 1883 karma points
    Jan 16, 2023 @ 14:54
    Gordon Saxby
    100

    The solution was to use the IOptions pattern to allow for getting the settings from appSettings.

    So, I now have this:

    private readonly IRuntimeState _runtimeState;
    private readonly ILogger<ScheduledUpdates> _logger;
    private readonly IReviewsApi _reviewsApi;
    
    public ScheduledUpdates(
        IOptions<ScheduledUpdatesSettings> scheduledUpdatesSettings,
        ICronTabParser cronTabParser,
        IRuntimeState runtimeState, 
        ILogger<ScheduledUpdates> logger,
        IReviewsApi reviewsApi) : base(logger, scheduledUpdatesSettings.Value.Period, scheduledUpdatesSettings.Value.GetNotificationDelay(cronTabParser, DateTime.Now, DefaultDelay))
    {
        _runtimeState = runtimeState;
        _logger = logger;
        _reviewsApi = reviewsApi;
    }
    

    With this for the Settings:

    internal class ScheduledUpdatesSettings
    {
        internal const string StaticPeriod = "1.00:00:00"; //TimeSpan.FromHours(24);
    
        public string RunAtTime { get; set; } = "0 6 * * *";
    
        [DefaultValue(StaticPeriod)]
        public TimeSpan Period { get; set; } = TimeSpan.Parse(StaticPeriod);
    }
    

    And this in an IComposer

    builder.Services.Configure<ScheduledUpdatesSettings>(options => builder.Config.GetSection("MySettings").Bind(options));
    builder.Services.AddHostedService<ScheduledUpdates>();
    

    So, it defaults to run at 6am each day, but that can be (is) overriden by a value in appSettings

      "MySettings": {
        "RunAtTime": "0 8 * * *",
    
  • Thomas 319 posts 606 karma points c-trib
    Jun 13, 2023 @ 13:53
    Thomas
    0

    Hi

    Where did you define GetNotificationDelay? :)

  • Chris Spanellis 45 posts 191 karma points
    Aug 29, 2023 @ 18:30
    Chris Spanellis
    0

    How is your RunAtTime expression being used?

  • Thomas 319 posts 606 karma points c-trib
    Sep 19, 2023 @ 14:16
    Thomas
    0

    Hi

    Can you explain more on this line:

    base(logger, scheduledUpdatesSettings.Value.Period, scheduledUpdatesSettings.Value.GetNotificationDelay(cronTabParser, DateTime.Now, DefaultDelay))
    

    I'm not sure where this is coming from

    scheduledUpdatesSettings.Value.GetNotificationDelay(cronTabParser, DateTime.Now, DefaultDelay))
    

    trying to have a task running from a cron value set ind the appsettings :)

    Thank! :)

  • Thomas 319 posts 606 karma points c-trib
    Sep 19, 2023 @ 15:05
    Thomas
    0

    I have tried to make a function that returns the TimeSpan

     public static TimeSpan CronToTimeSpan(ICronTabParser cronTabParser, string cron)
        {
            return cronTabParser.GetNextOccurrence(cron, DateTime.Now).TimeOfDay;
        }
    

    And then used it in the base:

     base(logger, TimeSpan.FromSeconds(10), CronHelper.CronToTimeSpan(cronTabParser, platformSettings.Value.ScheduleTasks.Nemtilmeld))
    

    But it's never triggert.

Please Sign in or register to post replies

Write your reply to:

Draft