23

I have a request from a customer to publish (some) content at a very specific time. The content will be generated up front (can be day before, we don't actually know) and will get publish restrictions to make sure it is not published before the actual time.

I am aware that there is a publish agent that can do this publish, but the problem is that the agent will run every x minutes and if set in minutes the minimum we can set is "1" (and actually client would rather have seconds).

But.. I don't want to set the publish agent interval to 1 minute as I have a strong feeling that this will not benefit the performance of the site. Especially knowing that this "specific time" will only happen 2 to 4 times a year.

Any ideas on how I can achieve a very punctual (occasional) publish without affecting the site's performance?

  • Although many answers are very valuable, and looking forward to trying SiteCron, I picked the Hangfire solution for now as that was one of the few solutions where I could really set the job at any time in code – Gatogordo Nov 14 '16 at 19:53
7

You could use HangFire. Not only does it supports cron based schedules like SiteCron, but it also features delayed jobs (among other things like a job dashboard, automatic retries, IoC support, support for logging frameworks). Delayed jobs are jobs that will run in the future at an (almost) exact given time.

// Delayed job example
var jobId = BackgroundJob.Schedule(() => Console.WriteLine("Delayed!"), TimeSpan.FromDays(7));

To publish an item at an exact time, you'll need to let Hangfire know. You can use the item:saved event for this. When it's an item to be published automatically, pass it to Hangfire like this:

var jobId = BackgroundJob.Schedule(() => Custom.Publish(itemId), publishDate);

With this in place, your item will get published almost instantly. Default interval to check for scheduled jobs is 15 seconds, but it can be changed.

There is still one caveat, though. What if the editor changes the publish date? As I see it, you have two options to handle this:

  • In the Publish method, check the item's publish date again and see if it's eligible to get published.
  • Save the jobId in a field of the item (or somewhere with a reference to the item ID). In the item:saved event, run BackgroundJob.Delete(jobId); before you schedule it.
  • The problem with schedulers outside of Sitecore is that I don't know when they need to be fired. An editor will create an item with a publish date, anytime, and I need to be able to get it on the site on that time exactly (well, with as little delay as possible). – Gatogordo Nov 3 '16 at 17:22
  • Changed my answer based on your comment. The item will now get published almost instantly. – Thomas D Nov 4 '16 at 8:44
17

You could use SiteCron to do this job. SiteCron is a scheduling module based on Quartz.NET Job Scheduler. SiteCron can be used to create simple or complex schedules to execute jobs. This functionality is implemented using Quartz’s CronTrigger.

“Quartz.NET is a pure .NET library written in C# and is a port of very popular open source Java job scheduling framework, Quartz.”

Cron has been around for a long time and is known for its powerful scheduling capabilities. CronTrigger in Quartz is based on the scheduling capabilities of cron and uses “cron expressions” to execute the jobs. Cron expressions specify the condition to fire the job such as execute this job at 8AM each day.

The current implementation of SiteCron only uses CronTrigger functionality of Quartz, which is more useful than the SimpleTrigger. It lets you have a job-firing schedule that recurs based on calendar type scenarios rather than on the exactly specified intervals of SimpleTrigger. The interval based jobs can be run using Sitecore agents.

CronTrigger lets you fire jobs based on schedules such as:

Fire job every friday at 9PM Fire job every day at 8AM from monday to thursday Fire job every 3 minutes from 2PM to 4PM Fire job at 3 pm on monday and wednesday

Here are some useful links: https://www.akshaysura.com/video/sitecron-demo/

https://www.akshaysura.com/2015/06/23/sitecron-sitecore-module-for-your-everyday-scheduling-needs/

https://www.akshaysura.com/2015/06/25/smart-and-incremental-publish-using-sitecron-for-sitecore/

  • Can I use this when I don't know at what time the publish will be (it's something the editor will enter)?. Or could we create a sitecron job (to run once) on the fly when a certain "event" is triggered? – Gatogordo Nov 2 '16 at 14:54
  • Gatogordo, you would have to know the time you would want it to be published. There are examples provided to specify the frequency. You could also add your own custom SiteCron job to it, even if its PowerShell based. I am working on an update where based on a publish restriction, it will automatically add a SiteCron job to publish that item at a specific time. – ASura Nov 2 '16 at 14:58
  • That would be cool - if possible keep it open so that we can extend it (adding jobs from within a save event - or other) – Gatogordo Nov 2 '16 at 15:28
  • 1
    You have to worry about "publishing latency", since the publishing job may take some time if you publish too many items. This should be less of an issue with the Publishing Service in 8.2 though. – jammykam Nov 2 '16 at 17:32
15

I spent some time looking into this recently and we decided to use the following module (built by the Hedgehog guys) and it works really well for us so far for scheduling publishing:

https://marketplace.sitecore.net/Modules/S/Sitecore_Scheduled_Publish.aspx?sc_lang=en

It supports the following:

  • Scheduled Publish
  • Scheduled Unpublish
  • Editing of the schedule
  • Validation / Warnings etc
  • Publish options for modes, children, targets etc
  • Notifications on publish to content authors (+ an email set in the settings if you wish)
  • Lots more too

When you install it you get some nice new buttons under the publishing tab:

enter image description here

You can then click to scheduled a publish like so:

enter image description here

And view/edit/cancel existing ones:

enter image description here

Documentation can be found here:

https://github.com/HedgehogDevelopment/SCScheduledPublishing/tree/master/Documentation

We've had no issues with this so far and it seems to work well.

7

I'm going to say you can't do it with traditional Sitecore publishing (but happy to be corrected).

The reason being with the best will in the world you can't guarantee 'to the second publishing'; Sitecore is a massive framework and multiple users could be publishing different content at the same time you have no control over the order it will be published in, plus general latency of shifting data between master and web databases will differ depending on how busy the site is.

A possible custom solution

That said what perhaps you could do something like:

Use one of the publishing frameworks to publish at a suitable schedule, set your publish date for the item so it publishes ahead of when you want it displayed.

Add a custom publish date field which controls when the page is visible on the web db, check this as the page renders, if the time has passed, show the page; if it's still before the correct time then temp redirect to the home page.

  • 1
    Don't forget, if you use the custom method mentioned here, you need to deal with Html Caching to ensure your content shows up. – Sergeant Sitecore Nov 2 '16 at 14:03
  • Steve, that is not true. You can guarantee to the second publishing. Check out the SiteCron module based on Quartz.net – ASura Nov 2 '16 at 14:47
  • I will check it out, does this guarantee a publish will have happened by an exact to the second time? Or that it will kick off a publish at an exact time? I certainly prefer the idea of a job for this sort of thing – Steve Newstead Nov 2 '16 at 14:58
  • I don't believe the custom method mentioend will work with multiple versions of an item either, e.g. you want a page with updated information at a given time. It would only work for new items. – jammykam Nov 2 '16 at 17:31
  • @jammykam - true story – Steve Newstead Nov 2 '16 at 17:34
7

We handle publishing items to the minute/second by creating an additional field called "LiveDate". What's great about the LiveDate enhancement is that content can get loaded into the site for the future and will only display on the site once the LiveDate criteria is met.

Obviously this takes a little more development to setup correctly, because you need to have logic in place to check the live date to ensure it's met before content displays on the site. Also it can complicate Html Caching, because typically publishing items to the web database triggers the cache to clear. But with a LiveDate a publish wouldn't occur because the content already exists in the web database. To solve that issue, you can use the HtmlCache Clear task to wipe the cache on a timed interval. Or you could alter the Html Cache settings to also expire the cache on a specific interval.

Obviously if your content needs to be appear at a very specific time, caching the component would present problems still in this scenario. And it might make sense to avoid using caching on the component.

  • 3
    What happens when you have multiple versions of an item, and you want the new version of a page to be Live with updated info at a certain time? – jammykam Nov 2 '16 at 17:29
  • I see your point, and its a great point. Using a "Live Date" doesn't really support you changing the value (ie. Having a Version 1 of an item with a date in the past, and then Version 2 with a date in the future. it would just hide the content in that scenario. Where if you were just relying on the PublishDate, that wouldn't be an issue because you'd just schedule version 2 to publish in the future and until it publishes, version 1 would stay visible. – Dylan Young Nov 3 '16 at 2:29
4

I have created a blog post on this if helps anyone: http://sitecoreblog.tools4geeks.com/Blog/33/Sitecore-publish-at-specific-time

We faced exact same problem. We don't want to run publish agent on every x number of minutes which triggers cache clear and index rebuild. So, this is what we have done.

  1. On item save, we check if item has publishing restrictions set.

  2. If item has publishing restrictions. We create two scheduling tasks one for start date time and other for end date time.

  3. This scheduled tasks will be triggered every one minute.

  4. The schedule tasks will trigger the publish only on specific time which was set in the publishing restrictions.

  5. Delete the scheduled task on successful run.

Hope it will help someone.

3

You could use the in-built Sitecore Task Scheduling, this would let you configure an exact time (aka Schedule) for the publish to take place.

The only development required would be to create a custom class with a publish method that called the publish through the Sitecore API.

Information on how to trigger a publish programatically can be found at http://patrickdelancy.com/2015/01/compare-contrast-ways-programmatically-publish-sitecore-items/#.WBsBgfqLRhE or https://briancaos.wordpress.com/2011/01/14/create-and-publish-items-in-sitecore/

See this page for information on how to create a Sitecore Scheduled Task http://www.degdigital.com/insights/how-to-create-sitecore-scheduled-task/

2

Aside from all the options already outlined here I suggest the Automated Publisher module available on market place here

With it you can create an item an use the publish restrictions to set when it should be published from and to. With that in place it will create a task which will take care of publishing and unpublishing as per the configurations. I've used myself and recommend

1

Another option is to create a custom admin page as 'schedule-publish.aspx' which you can call from standard windows task scheduler.

Step 1: Create your admin page or publish page.

You just need to drop few lines of code on the Page_Load method

protected void Page_Load(object sender, EventArgs e)
    {
      try
        {
            Database dbSource = Sitecore.Configuration.Factory.GetDatabase("master");
            Database dbTarget = Sitecore.Configuration.Factory.GetDatabase("web");

            Language[] dbLanguages = dbSource.Languages;

            Database[] dbTargets = new Database[] { dbTarget };

            PublishManager.PublishSmart(dbSource, dbTargets, dbLanguages);
        }
        catch (Exception ex)
        {
            Sitecore.Diagnostics.Log.Error(ex.Message,ex,this);
        }
    }

Step 2 : Set up windows task following this post

During schedule task setup, following arguments can be used

In start program > PowerShell.exe

In additional parameters > Invoke-WebRequest -Uri http://myserver/sitecore/admin/schedule-publish.aspx -Method GET

For more details, read blog post

  • The problem with schedulers outside of Sitecore is that I don't know when they need to be fired. An editor will create an item with a publish date, anytime, and I need to be able to get it on the site on that time exactly (well, with as little delay as possible). – Gatogordo Nov 3 '16 at 17:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.