Adding a Preview publishing target to the the Sitecore Publishing Service

Publishing speed out of the box has never been a strong point in Sitecore. A full site publish is akin to watching paint dry if your master database is even lightly used. Not only that, but any subsequent publish will be blocked by the first operation until it completes in its entirety. Not ideal but what can we do?

Step up the Sitecore Publishing Service (SPS), a separate site built on .NET Core designed to rapidly publish items via calls that go directly to the Sitecore databases.

If you’ve already decided that publishing is too slow and gone down the route of employing the Publishing Service, then bravo, good choice. If not what are you waiting for?!

The Publishing Service only ships with a default publish target – “Internet” (the web database). It’s therefore down to you to configure any custom targets such as Preview even if these are already set up in Sitecore.

Assumptions 

I’m going to assume you’ve already:

  • Installed and configured all the prerequisites, the Publishing Service and the Sitecore module package. If you get stuck, Stephen has a very nice guide here http://www.stephenpope.co.uk/publishing) – admittedly for v2.0 but pretty much all of the same info applies to v3 and 4)
  • Installed the .NET Core Windows Hosting  Bundle
  • Set up the IIS Site
  • Added a host entry to your hosts file
  • Set up your core, master and web connection strings in SPS config
  • Successfully published to the web database though the Sitecore UI

Configuring a new publishing target

The default publishing targets are configured in the file below relative to the installation folder:

 /config/sitecore/publishing/sc.publishing.xml

If you open this you’ll see a <Targets> node where the publish target configuration is stored. However the /config/sitecore folder contains the default files provided by Sitecore and as sc.publishing.xml forms part of that it should not be modified.

As with a traditional Sitecore site, rather than edit the default files provided we will patch the configuration we need on top in a separate patch file. 
For our purposes we will call this sc.preview.xml but you could call this sc.targets.xml or anything else you desire as long as it has a “sc” prefix. Where we choose to locate this patch file has an effect on when it is loaded.

Configuration files are loaded from the folder structure in the following order:
1) Files are loaded from /config/sitecore/
2) Files are loaded from /config/global/ (if it exists)
3) Files are loaded from /config/{environment}/ (if it exists)

Using the patch file below as a guide, for now drop the file in the /config/global/ folder. This will ensure it is always loaded in each type of environment:

<Settings>
    <Sitecore>
        <Publishing>
            <Services>
                <DefaultConnectionFactory>
                    <Options>
                        <Connections>
                            <Preview>
                                <Type>Sitecore.Framework.Publishing.Data.AdoNet.SqlDatabaseConnection, Sitecore.Framework.Publishing.Data</Type>
                                <LifeTime>Transient</LifeTime>
                                <Options>
                                    <ConnectionString>${Sitecore:Publishing:ConnectionStrings:Preview}</ConnectionString>
                                    <DefaultCommandTimeout>120</DefaultCommandTimeout>
                                    <Behaviours>
                                        <backend>sql-backend-default</backend>
                                        <api>sql-api-default</api>
                                    </Behaviours>
                                </Options>
                            </Preview>
                        </Connections>
                    </Options>
                </DefaultConnectionFactory>
                <StoreFactory>
                    <Options>
                        <Stores>
                            <Targets>
                                <Preview>
                                    <Type>Sitecore.Framework.Publishing.Data.TargetStore, Sitecore.Framework.Publishing.Data</Type>
                                    <ConnectionName>Preview</ConnectionName>
                                    <FeaturesListName>TargetStoreFeatures</FeaturesListName>
                                    <Id><!-- Your Preview target item Guid goes here--></Id>
                                    <ScDatabase>preview</ScDatabase>
                                </Preview>
                            </Targets>
                        </Stores>
                    </Options>
                </StoreFactory>
            </Services>
        </Publishing>
    </Sitecore>
</Settings>

As you can see from the XML, we set up a Connection element, a Target element which references this connection and specifies the Publishing target item itself in Sitecore.

Ensure you replace the comment in the XML below:

<Id><!-- Your Preview target item Guid goes here--></Id>

With the appropriate GUID from your Publish target:

Connection strings

As part of setting up the SPS you should find the /config/global/sc.connectionstrings.json file already present and populated. All you need to do is add the bolded preview line below and update the connection string appropriately:

 {
  "Sitecore": {
    "Publishing": {
      "ConnectionStrings": {
        "core": "user id=user;password=password;data source=(local)\SQLEXPRESS;database=SitecoreCore;MultipleActiveResultSets=True;ConnectRetryCount=15;ConnectRetryInterval=1",
        "master": "user id=user;password=password;data source=(local)\SQLEXPRESS;database=SitecoreMaster;MultipleActiveResultSets=True;ConnectRetryCount=15;ConnectRetryInterval=1",
        "web": "user id=user;password=password;data source=(local)\SQLEXPRESS;database=SitecoreWeb;MultipleActiveResultSets=True;ConnectRetryCount=15;ConnectRetryInterval=1",
        "preview": "user id=user;password=password;data source=(local)\SQLEXPRESS;database=SitecorePreview;MultipleActiveResultSets=True;ConnectRetryCount=15;ConnectRetryInterval=1"
      }
    }
  }
} 

Alternatively you can issue a command to the Publishing Host executable which will write the connection string line for you:

Sitecore.Framework.Publishing.Host configuration setconnectionstring preview id=user;password=password;data source=(local)\SQLEXPRESS;database=SitecorePreview; 

If you use a Json or INI file for your connection string configuration, carry out the equivalent change.

Multiple Active Results Sets (MARS)

Multiple Active Result Sets (MARS) is a feature that works with SQL Server to allow the execution of multiple batches on a single connection. SPS requires the use of MARS – The setting has to form part of your connection strings or you will get an error:

System.InvalidOperationException: The connection does not support MultipleActiveResultSets. 

If you’re adding the Preview connection strings manually, ensure the following is present as part of the connection:

MultipleActiveResultSets=True 

If you’re using the setconnectionstring command line approach it will get added automatically.

Upgrade the schema

Now the connection strings are hooked up we need to ensure the Preview database contains the necessary schema for the Publishing Service to function. Drop to a command line and execute the line:

Sitecore.Framework.Publishing.Host.exe schema upgrade --force 

This should result in something similar to the following output:

Schema Upgrade  
Upgrading all databases to version [ 2 ]  
Database: [ localhost\SitecorePreview ] … COMPLETE [ v0 => v2 ]  
Database: [ localhost\SitecoreCore ] … SKIPPED (Already v2) 
Database: [ localhost\SitecoreMaster ] … SKIPPED (Already v2)   
Database: [ localhost\SitecoreWeb ] … SKIPPED (Already v2)

Testing the service

We can now fire up the Publishing Service from the console which allows us to see debug messages and more verbose logging than in production mode. To run in development mode we run the following command from the installation folder with the environment flag:

Sitecore.Framework.Publishing.Host.exe --environment development

Since were using the development environment, our XML config changes must exist in the /config/development or the /config/global folder or they will not be incorporated. When the service loads, the list of registered targets are output to the console. If all is well and the config has patched correctly you should see your new Preview target output as per the screenshot:

Happy days!

If all looks good, now is the time to head back into Sitecore and attempt to publish some content to the Preview database.

Ditch dev and go into prod!

If you managed to successfully publish in development mode, now is the time to ensure you can run in production mode in IIS. Ensure you have the sc.preview.xml config file located in either /config/production or the /config/global subfolder for it to take effect. Since we made changes to the SPS configuration, you must restart the application pool for the modifications to be recognised.

Check the service status

Next up you’ll want to check the service is running properly with your changes. Navigate to the following URL in a browser to ensure the service is up and running:

http://<your host>/api/publishing/operations/status

If all is ok you should see a response similar to this:

{ "status": 0 } 

Repeat the publish you did earlier and check the Publishing Service logs to ensure that the service published the item correctly.

Now bask as the Content Editors buy you many gifts for their new found ability to publish to Preview in super fast time 😉

Troubleshooting

If you encounter problems or the service won’t start, the first thing to check are the logs stored in the \logs subfolder of the application folder.

1. Error: "Could not resolve stores: 'Preview' of type target"

The error message above indicates your configuration has not been patched in correctly; check the file is present in the correct environment folder with the “sc.” prefix. For troubleshooting purposes you could take a backup of /config/sitecore/publishing/sc.publishing.xml and temporarily edit the original file with your configuration to help narrow down the issue. If the config works its probably a patching issue. Don’t forget to restart the changes after any configuration change!

2. System.AggregateException: One or more errors occurred. ---> System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
 Parameter name: No connection was registered with name 'Preview'

This means that the XML in your config patch is not quite right. The target configured must match the name of the connection XML so double check for typos in your patch file.

Leave a Reply

Your email address will not be published. Required fields are marked *