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 parameters
JobDataMap
dataMap
=
context
.
JobDetail
.
JobDataMap
;
//get the datamap from the Quartz job
var
job
=
(
SitecronJob
)
dataMap
[
SitecronConstants
.
ParamNames
.
SitecronJob
];
//get the SitecronJob from the job definition
if
(
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.