Skip to content

Bypass custom logic on import, and end every run with its total time - #29

Merged
imranakram merged 4 commits into
masterfrom
feature/bypass-custom-logic
Oct 9, 2026
Merged

imranakram merged 4 commits into
masterfrom
feature/bypass-custom-logic

Conversation

@imranakram

@imranakram imranakram commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator

Adds the option to import without running custom business logic, as asked in #16, and ends every run with its total time.

Bypassing custom logic

Three optional attributes on <ShuffleDefinition>, all off by default:

<ShuffleDefinition BypassSyncLogic="true" BypassAsyncLogic="true" BypassFlows="true">
Attribute Skips Sent as
BypassSyncLogic Synchronous plugins and real-time workflows BypassBusinessLogicExecution = CustomSync
BypassAsyncLogic Asynchronous plugins and background workflows BypassBusinessLogicExecution = CustomAsync
BypassFlows Power Automate flows triggered by Dataverse SuppressCallbackRegistrationExpanderJob = true
  • The setting is on the definition, not per block. Bypass is a decision about the whole load, and one switch means no block can be forgotten. A per-block override can be added later without breaking anything.
  • Every write in every data block carries the parameters: batched and single creates and updates, upserts, deletes, state and owner changes (including the deferred pass) and N:N associations. BypassLogicService wraps the organization service for the data blocks, so the Xrm.Utils.Core helpers that call the service directly are covered too, and each request inside an ExecuteMultiple gets the parameters. Solution blocks keep the plain service.
  • Older on-premises servers: 9.0 and 9.1 only know BypassCustomPluginExecution, which covers sync logic; older versions can't bypass at all. A definition is often shared between online and on-premises, so what a server can't bypass runs as usual: the import logs a warning (WARNING: This server (9.1.0.0) cannot bypass async plugins and workflows or Power Automate flows. They run as usual during this import.) and carries on. The Builder tooltips say the same.
  • Privilege: the user needs prvBypassCustomBusinessLogic. Without it, the first write fails with Dataverse's own error.
  • Builder: three checkboxes with tooltips on the ShuffleDefinition node.
  • Log: one line at the start, for example Bypassing custom logic: sync, async, flows (BypassBusinessLogicExecution=CustomSync,CustomAsync, SuppressCallbackRegistrationExpanderJob=True).

Measured: about 15,000 records into a fresh environment took 1 h 54 min with the previous release (one request per record, logic running). With batches of 250 and bypass on, it took 2 minutes.

Total run time

Every import and export now ends with a line in the log, the Runner and the pipeline output:

Import finished in 1 min 58 s: 14970 created, 0 updated, 0 skipped, 0 deleted, 0 failed
Export finished in 4.2 s: 2 records

Tests

  • Layer 1: BypassLogicServiceTests (which requests get the parameters and which don't, the parameter mapping and warnings per server version) and RunDurationTests.
  • Layer 3: BypassLogicImportTests runs whole definitions: every write of every block carries the parameters; a definition without the attributes sends none; the deferred state pass; the legacy parameter on each ExecuteMultiple request on 9.1; the warning and completed import on 9.1 and 8.2. A round-trip test checks the run-time line in the log and in what the listener hears.

All 304 tests pass in Debug and Release. The README has a "Bypassing custom logic" section, and all three nuspecs have release notes.

Fixes #16

…assFlows

Three optional attributes on <ShuffleDefinition> import without running
synchronous plugins and workflows, asynchronous ones, or Power Automate
flows. Every write in every data block carries the parameters Dataverse
reads (BypassBusinessLogicExecution, SuppressCallbackRegistrationExpanderJob):
batched and single creates and updates, upserts, deletes, state and owner
changes including the deferred pass, and N:N associations.

BypassLogicService wraps the organization service for the data blocks, so
the Xrm.Utils.Core helpers that call the service directly are covered too,
and each request inside an ExecuteMultiple gets the parameters. Solution
blocks keep the plain service.

On-premises 9.0 and 9.1 only know BypassCustomPluginExecution, which covers
sync logic; asking them for more stops the import before any write, rather
than import with logic the definition said to skip.

The Builder gets three checkboxes on the ShuffleDefinition node.
The only timing so far was the raw milliseconds of the QuickImport log
section. Both runs now end with a line people can read, sent through the
same channel as the other progress lines, so it reaches the log file, the
Runner and the pipeline tasks:

  Import finished in 1 min 58 s: 14970 created, 0 updated, 0 skipped, 0 deleted, 0 failed
  Export finished in 4.2 s: 2 records
A definition is often shared between online and on-premises environments.
On-premises 9.0 and 9.1 can only bypass sync logic, and older servers
nothing, so asking for async logic or flows used to stop the import there.
Now the server bypasses what it can, the rest runs as usual, and the run
says so in the log, the Runner and the pipeline output:

  WARNING: This server (9.1.0.0) cannot bypass async plugins and workflows
  or Power Automate flows. They run as usual during this import.

The bypass line in the log names only what is actually bypassed. The
Builder tooltips, the schema documentation and the README describe it.
…om-logic

# Conflicts:
#	XTB/ShuffleDeployer.nuspec
#	XTB/ShuffleRunner.nuspec
@imranakram
imranakram merged commit a0bf1d5 into master Oct 9, 2026
2 checks passed
@imranakram
imranakram deleted the feature/bypass-custom-logic branch October 9, 2026 15:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bypass custom Dataverse logic

1 participant