Build Efficient Jobs
This guide shows how to build efficient jobs by minimizing their costs.
The rules below must be followed when creating a new job, otherwise the frequent launch of this scheduled job will trigger errors in a SaaS environment.
Rule 1: Use Scaffoldings
Usercube provides scaffoldings to simplify XML configuration by generating complex XML fragments.
Most jobs are included in job scaffoldings, thus configured in the most optimal way. So start by using scaffoldings to build jobs.
For example, the creation from scratch of a job to perform a complete synchronization for a connector will be tedious. Instead, use Usercube's scaffolding, like in the following example concerning the Microsoft Entra ID (formerly Microsoft Azure AD) connector. Instead of a few dozens of lines, write only the following:
<CreateConnectorSynchroComplete DisplayName_L1="10: Microsoft Entra ID - Synchronization Complete (scaffolding)" Connector="MicrosoftEntraID" JobIdentifier="MicrosoftEntraID_Synchronize_Complete_Scaffolding"/>See more details about this scaffolding.
Rule 2: Compute Only What's Necessary
Execute the tasks on the right entity types
Many tasks can be executed either on all entity types, or on a given list of entity types.
Make sure to configure the tasks so that they are executed only on the relevant entity types, not all of them by default.
For example, instead of using
AllEntityType
set totrue
, write the following:
<ComputeCorrelationKeysTask DisplayName_L1="Directory User - Update the correlation keys" >
<TaskEntityType EntityType="Directory_UserRecord"/> <TaskEntityType EntityType="Directory_User"/> <TaskEntityType EntityType="HR_Person"/>
</ComputeCorrelationKeysTask>
Launch incremental tasks rather than complete
When a task is supposed to be executed on changes only, then there is no use executing the task in complete mode.
Make the relevant tasks incremental by flagging the resources that were recently modified. See how to configure a job to be incremental.
For example, instead of computing the role model as if it had never been computed before, apply only the changes by writing the following:
<ComputeRoleModelTask Identifier="MicrosoftEntraID_Synchronize_Incremental_ComputeRoleModel_WithDirty" DisplayName_L1="Apply the Role Model" Level="6" Dirty="true">
<TaskEntityType EntityType="Directory_User" /></ComputeRoleModelTask>
Launch only the relevant tasks according to the logical chain
Usercube's tasks are all linked together by a logical chain that implies that some tasks are supposed to be executed after some others.
Make sure to understand the tasks' logical chain to launch only the relevant tasks.
For example, there is no use computing expressions or correlations if there was beforehand no change in the database. Thus, there should not be
UpdateEntityPropertyExpressionsTask
orComputeCorrelationKeysTask
without firstSynchronizeTask
orFulfillTask
.
Rule 3: Wait for Recurring Tasks
Inside a recurring job, there is no need including some tasks twice in order to have the whole cycle, because the next execution will complete what has been started.
For example, Usercube's feedback loop uses the tasks for synchronization, computation of the role model, provisioning, then once more synchronization and computation of the role model.
Instead of including any task twice, rather write a job with each task once, schedule a periodic execution of the job, and wait for the next execution to get the whole cycle. For example for the AD:
<Job Identifier="Synchronization_RoleModelComputation_Provisioning" DisplayName_L1="91: Synchronization / RoleModelComputation / Provisioning" Agent="Local">
<ExportTask Identifier="Export_AD" DisplayName_L1="AD - Extract Changes" Agent="Local" Connector="AD" Level="0" OpenIdClient="Job" Connection="ADExportFulfillment" ContinueOnError="true" />
<PrepareSynchronizationTask Identifier="PrepareSynchronization_AD" DisplayName_L1="Synchronization (agent side)" Agent="Local" Connector="AD" Level="1" OpenIdClient="Job" SynchronizationMode="Incremental" Type="ActiveDirectory">
<TaskDependsOnTask ParentTask="Export_AD" /> </PrepareSynchronizationTask>
<SynchronizeTask Identifier="Synchronization_AD" DisplayName_L1="Synchronization (server side)" Connector="AD" Level="2" Type="ActiveDirectory">
<TaskDependsOnTask ParentTask="PrepareSynchronization_AD" /> </SynchronizeTask>
<UpdateEntityPropertyExpressionsTask Identifier="UpdateEntityPropertyExpressions_AD" DisplayName_L1="Update Computed Properties" Level="4">
<TaskEntityType EntityType="AD_Entry" /> ... </UpdateEntityPropertyExpressionsTask>
<ComputeCorrelationKeysTask Identifier="ComputeCorrelationKeys_AD" DisplayName_L1="Compute all Correlations" Level="5">
<TaskEntityType EntityType="AD_Entry" /> ... </ComputeCorrelationKeysTask>
<ComputeRoleModelTask Identifier="ComputeRoleModel_AD" DisplayName_L1="Apply the Role Model" Level="6">
<TaskEntityType EntityType="Directory_User" /> ... </ComputeRoleModelTask>
<GenerateProvisioningOrdersTask Identifier="GenerateProvisioningOrders_AD" DisplayName_L1="Generate Provisioning Orders" Level="7">
<TaskResourceType ResourceType="AD_Entry_NominativeUser" /> ... </GenerateProvisioningOrdersTask>
<FulfillTask Identifier="Fulfill_AD" DisplayName_L1="Provisioning" Agent="Local" Level="8" OpenIdClient="Job" ContinueOnError="true">
<TaskDependsOnTask ParentTask="GenerateProvisioningOrders_AD" />
<TaskResourceType ResourceType="AD_Entry_NominativeUser" /> ... </FulfillTask></Job>