@@ -84,6 +84,12 @@ type ProcessedFieldsToRemoveType = {
8484 notUpdateableFields : string [ ] ;
8585} ;
8686
87+ type DmlExecutionSettingsType = {
88+ alwaysUseRest : boolean ;
89+ bulkThreshold : number ;
90+ restApiBatchSizeOverride ?: number ;
91+ } ;
92+
8793const { parseQuery, composeQuery } = CjsDependencyAdapters . getSoqlParser ( ) ;
8894
8995/**
@@ -3471,14 +3477,16 @@ export default class MigrationJobTask implements ISFdmuRunCustomAddonTask {
34713477 return [ ] ;
34723478 }
34733479
3480+ const dmlSettings = this . _resolveDmlExecutionSettings ( operation ) ;
3481+ const effectiveScriptObject = this . _createEffectiveScriptObject ( dmlSettings . restApiBatchSizeOverride ) ;
34743482 const connection = await this . _getConnectionAsync ( org ) ;
34753483 const engine = ApiEngineFactory . createEngine ( {
34763484 connection,
34773485 sObjectName,
34783486 amountToProcess : records . length ,
3479- bulkThreshold : this . job . script . bulkThreshold ,
3480- alwaysUseRest : this . job . script . alwaysUseRestApiToUpdateRecords ,
3481- forceBulk : operation === OPERATION . HardDelete ,
3487+ bulkThreshold : dmlSettings . bulkThreshold ,
3488+ alwaysUseRest : dmlSettings . alwaysUseRest ,
3489+ forceBulk : operation === OPERATION . HardDelete && ! dmlSettings . alwaysUseRest ,
34823490 bulkApiVersion : this . job . script . bulkApiVersion ,
34833491 } ) ;
34843492 const apiVersion = this . _resolveApiVersion ( connection ) ;
@@ -3497,7 +3505,9 @@ export default class MigrationJobTask implements ISFdmuRunCustomAddonTask {
34973505 operation
34983506 ) } engine=${ engine . getEngineName ( ) } apiVersion=${ apiVersion } count=${ records . length } allOrNone=${ String (
34993507 this . job . script . allOrNone
3500- ) } updateRecordId=${ String ( updateRecordId ) } finalAttempt=${ String ( isFinalDmlAttempt ) } `
3508+ ) } updateRecordId=${ String ( updateRecordId ) } finalAttempt=${ String ( isFinalDmlAttempt ) } alwaysUseRest=${ String (
3509+ dmlSettings . alwaysUseRest
3510+ ) } bulkThreshold=${ dmlSettings . bulkThreshold } restBatchOverride=${ dmlSettings . restApiBatchSizeOverride ?? 'none' } `
35013511 ) ;
35023512
35033513 const executor = new ApiEngineExecutor ( {
@@ -3507,7 +3517,7 @@ export default class MigrationJobTask implements ISFdmuRunCustomAddonTask {
35073517 updateRecordId,
35083518 logger : this . _getLogger ( ) ,
35093519 script : this . job . script ,
3510- scriptObject : this . scriptObject ,
3520+ scriptObject : effectiveScriptObject ,
35113521 isFinalDmlAttempt,
35123522 } ) ;
35133523 let processed : Array < Record < string , unknown > > ;
@@ -3522,7 +3532,7 @@ export default class MigrationJobTask implements ISFdmuRunCustomAddonTask {
35223532 connection,
35233533 sObjectName,
35243534 amountToProcess : records . length ,
3525- bulkThreshold : this . job . script . bulkThreshold ,
3535+ bulkThreshold : dmlSettings . bulkThreshold ,
35263536 alwaysUseRest : true ,
35273537 forceBulk : false ,
35283538 bulkApiVersion : this . job . script . bulkApiVersion ,
@@ -3554,7 +3564,7 @@ export default class MigrationJobTask implements ISFdmuRunCustomAddonTask {
35543564 updateRecordId,
35553565 logger : this . _getLogger ( ) ,
35563566 script : this . job . script ,
3557- scriptObject : this . scriptObject ,
3567+ scriptObject : effectiveScriptObject ,
35583568 isFinalDmlAttempt,
35593569 } ) ;
35603570 processed = await restExecutor . executeCrudAsync ( ) ;
@@ -3569,6 +3579,68 @@ export default class MigrationJobTask implements ISFdmuRunCustomAddonTask {
35693579 return processed ;
35703580 }
35713581
3582+ /**
3583+ * Resolves effective DML engine settings for the current object and operation.
3584+ *
3585+ * @param operation - Operation to execute.
3586+ * @returns Effective DML settings.
3587+ */
3588+ private _resolveDmlExecutionSettings ( operation : OPERATION ) : DmlExecutionSettingsType {
3589+ const script = this . job . script ;
3590+ const object = this . scriptObject ;
3591+ const isDeleteOperation = this . _isDeleteLikeOperation ( operation ) ;
3592+ let alwaysUseRest = script . alwaysUseRestApiToUpdateRecords || object . alwaysUseRestApi ;
3593+ let bulkThreshold = script . bulkThreshold ;
3594+ let restApiBatchSizeOverride : number | undefined ;
3595+
3596+ if ( object . respectOrderByOnDeleteRecords && isDeleteOperation ) {
3597+ alwaysUseRest = true ;
3598+ restApiBatchSizeOverride = 1 ;
3599+ }
3600+
3601+ if ( ! alwaysUseRest && ( object . alwaysUseBulkApi || object . alwaysUseBulkApiToUpdateRecords ) ) {
3602+ bulkThreshold = 0 ;
3603+ }
3604+
3605+ return {
3606+ alwaysUseRest,
3607+ bulkThreshold,
3608+ restApiBatchSizeOverride,
3609+ } ;
3610+ }
3611+
3612+ /**
3613+ * Returns true when the operation is delete-like.
3614+ *
3615+ * @param operation - Operation to inspect.
3616+ * @returns True when delete-like.
3617+ */
3618+ private _isDeleteLikeOperation ( operation : OPERATION ) : boolean {
3619+ void this ;
3620+ return (
3621+ operation === OPERATION . Delete ||
3622+ operation === OPERATION . DeleteHierarchy ||
3623+ operation === OPERATION . DeleteSource ||
3624+ operation === OPERATION . HardDelete
3625+ ) ;
3626+ }
3627+
3628+ /**
3629+ * Creates a script-object view with an optional REST batch-size override.
3630+ *
3631+ * @param restApiBatchSizeOverride - Optional REST batch-size override.
3632+ * @returns Effective script object for API executor options.
3633+ */
3634+ private _createEffectiveScriptObject ( restApiBatchSizeOverride ?: number ) : ScriptObject {
3635+ if ( ! restApiBatchSizeOverride || this . scriptObject . restApiBatchSize === restApiBatchSizeOverride ) {
3636+ return this . scriptObject ;
3637+ }
3638+
3639+ const clone = Object . assign ( new ScriptObject ( ) , this . scriptObject ) ;
3640+ clone . restApiBatchSize = restApiBatchSizeOverride ;
3641+ return clone ;
3642+ }
3643+
35723644 /**
35733645 * Returns true when hard delete should retry via REST API.
35743646 *
0 commit comments