Akshay Sura - Partner
21 Sep 2018
In this video, I am going to walk you through how to use the SiteCron module to run Sitecore Commerce Engine Minions. Sitecore jobs along with Sitecore Commerce Minions run on an interval basis. If you need a way to accurately run your Minions based on CRON expressions or at a specific date and time, you would need to use SiteCron. Here is some code:
using System ;using System . Collections . Generic ;using System . Threading . Tasks ;using System . Web . Http . OData ;using Konabos . Minions . RunMinion . Commands ;using Microsoft . AspNetCore . Mvc ;using Newtonsoft . Json . Linq ;using Sitecore . Commerce . Core ;using Sitecore . Commerce . Core . Commands ; namespace Konabos . Minions . RunMinion . Controllers{public class CommandsController : CommerceController{private readonly EntitySerializerCommand _entitySerializerCommand ; public CommandsController ( IServiceProvider serviceProvider , CommerceEnvironment globalEnvironment , EntitySerializerCommand entitySerializerCommand ): base ( serviceProvider , globalEnvironment ){this . _entitySerializerCommand = entitySerializerCommand ;} [ HttpPut ][ Route ( "RunMinionNow()" )]public async Task < IActionResult > RunMinionNow ( [ FromBody ] ODataActionParameters value ){CommandsController commandsController = this ;if (! commandsController . ModelState . IsValid || value == null )return ( IActionResult ) new BadRequestObjectResult ( commandsController . ModelState );if ( value . ContainsKey ( "minionFullName" ) && value . ContainsKey ( "environmentName" )){var minionFullName = value [ "minionFullName" ]. ToString ();var environmentName = value [ "environmentName" ]. ToString ();if ((! string . IsNullOrEmpty ( minionFullName != null ? minionFullName . ToString () : ( string ) null )) && (! string . IsNullOrEmpty ( environmentName != null ? environmentName . ToString () : ( string ) null ))){ List < Policy > policies = new List < Policy >();if ( value . ContainsKey ( "policies" )){JArray jarray = ( JArray ) value [ "policies" ];if ( jarray != null ){foreach ( object obj in jarray ){string serializedEntity = obj . ToString (). Replace ( "" @odata . type ": " #Sitecore.Commerce.Core.RunMinionPolicy"", ""$type": "Sitecore.Commerce.Core.RunMinionPolicy, Sitecore.Commerce.Core"");policies . Add ( await commandsController . _entitySerializerCommand . Deserialize < Policy >( commandsController . CurrentContext , serializedEntity ));}}} RunMinionNowCommand command = commandsController . Command < RunMinionNowCommand >();var resutlt = await command . Process ( commandsController . CurrentContext , minionFullName , environmentName , policies );return ( IActionResult ) new ObjectResult (( object ) command );}}return ( IActionResult ) new BadRequestObjectResult (( object ) value );}}}using System ;using System . Collections . Generic ;using System . Threading . Tasks ;using Sitecore . Commerce . Core ;using Sitecore . Commerce . Core . Commands ;using Sitecore . Framework . Pipelines ; namespace Konabos . Minions . RunMinion . Commands{public class RunMinionNowCommand : CommerceCommand{ private readonly IRunMinionPipeline _runMinionPipeline ;private readonly GetEnvironmentCommand _getEnvironment ; public RunMinionNowCommand ( IRunMinionPipeline runMinionPipeline , IServiceProvider serviceProvider , GetEnvironmentCommand getEnvironmentPipeline ): base ( serviceProvider ){this . _runMinionPipeline = runMinionPipeline ;this . _getEnvironment = getEnvironmentPipeline ;} public virtual async Task < RunMinionNowCommand > Process ( CommerceContext commerceContext , string minionFullName , string environmentName , IList < Policy > policies ){RunMinionNowCommand runMinionNowCommand = this ;//var result = this._runMinionPipeline.Run(new RunMinionArgument(minionFullName)); //return Task.FromResult(result.IsCompleted); using ( CommandActivity . Start ( commerceContext , ( CommerceCommand ) runMinionNowCommand )){if ( policies == null )policies = ( IList < Policy >) new List < Policy >();CommerceEnvironment commerceEnvironment = await this . _getEnvironment . Process ( commerceContext , environmentName ) ?? commerceContext . Environment ;CommercePipelineExecutionContextOptions pipelineContextOptions = commerceContext . GetPipelineContextOptions ();pipelineContextOptions . CommerceContext . Environment = commerceEnvironment ;IRunMinionPipeline runMinionPipeline = this . _runMinionPipeline ;RunMinionArgument runMinionArgument = new RunMinionArgument ( minionFullName );runMinionArgument . Policies = policies ;CommercePipelineExecutionContextOptions executionContextOptions = pipelineContextOptions ;int num = await runMinionPipeline . Run ( runMinionArgument , ( IPipelineExecutionContextOptions ) executionContextOptions ) ? 1 : 0 ;}return runMinionNowCommand ; }}}// --------------------------------------------------------------------------------------------------------------------// <copyright file="ConfigureServiceApiBlock.cs" company="Sitecore Corporation">// Copyright (c) Sitecore Corporation 1999-2017// </copyright>// -------------------------------------------------------------------------------------------------------------------- namespace Sitecore . Commerce . Plugin . Sample{using System . Threading . Tasks ; using Microsoft . AspNetCore . OData . Builder ; using Sitecore . Commerce . Core ;using Sitecore . Commerce . Core . Commands ;using Sitecore . Framework . Conditions ;using Sitecore . Framework . Pipelines ; /// <summary>/// Defines a block which configures the OData model/// </summary>/// <seealso>/// <cref>/// Sitecore.Framework.Pipelines.PipelineBlock{Microsoft.AspNetCore.OData.Builder.ODataConventionModelBuilder,/// Microsoft.AspNetCore.OData.Builder.ODataConventionModelBuilder,/// Sitecore.Commerce.Core.CommercePipelineExecutionContext}/// </cref>/// </seealso>[ PipelineDisplayName ( "FeatureRunMinionConfigureServiceApiBlock" )]public class ConfigureServiceApiBlock : PipelineBlock < ODataConventionModelBuilder , ODataConventionModelBuilder , CommercePipelineExecutionContext >{/// <summary>/// The execute./// </summary>/// <param name="modelBuilder">/// The argument./// </param>/// <param name="context">/// The context./// </param>/// <returns>/// The <see cref="ODataConventionModelBuilder"/>./// </returns>public override Task < ODataConventionModelBuilder > Run ( ODataConventionModelBuilder modelBuilder , CommercePipelineExecutionContext context ){Condition . Requires ( modelBuilder ). IsNotNull ( $ "{this.Name}: The argument cannot be null." ); ActionConfiguration actionConfiguration2 = modelBuilder . Action ( "RunMinionNow" );actionConfiguration2 . Parameter <string> ( "minionFullName" );actionConfiguration2 . Parameter <string> ( "environmentName" );actionConfiguration2 . ReturnsFromEntitySet < CommerceCommand >( "Commands" ); return Task . FromResult ( modelBuilder );}}}using System ;using Quartz ;using Sitecore . Commerce . Engine . Connect ;using Sitecore . Commerce . ServiceProxy ;using Sitecore . Diagnostics ;using Sitecron . Core . Jobs ;using Sitecron . SitecronSettings ; namespace Feature . Konabos . Loyalty . Website . SiteCron{public class RunMinionNow : IJob //Inherit from IJob interface from Quartz{public void Execute ( IJobExecutionContext context ){try{//get job parametersJobDataMap dataMap = context . JobDetail . JobDataMap ; //get the datamap from the Quartz jobvar job = ( SitecronJob ) dataMap [ SitecronConstants . ParamNames . SitecronJob ]; //get the SitecronJob from the job definitionif ( job == null )throw new Exception ( "Unable to load SiteCron Job Definition" ); Log . Info ( string . Format ( "Executing RunMinionsNow: {0} {1}" , job . MinionFullName , job . EnvironmentName ), this ); var container = EngineConnectUtility . GetShopsContainer ();Proxy . DoCommand ( container . RunMinionNow ( job . MinionFullName , job . EnvironmentName ));}catch ( Exception ex ){Log . Error ( "Sitecron: Commerce.RunMinionNow: ERROR something went wrong - " + ex . Message , ex , this );}}}}If you have any questions or concerns, please get in touch with me. (@akshaysura13 on Twitter or on Slack).
Links:

Akshay is a nine-time Sitecore MVP and a two-time Kontent.ai. In addition to his work as a solution architect, Akshay is also one of the founders of SUGCON North America 2015, SUGCON India 2018 & 2019, Unofficial Sitecore Training, and Sitecore Slack.
Akshay founded and continues to run the Sitecore Hackathon. As one of the founding partners of Konabos Consulting, Akshay will continue to work with clients to lead projects and mentor their existing teams.