-
Notifications
You must be signed in to change notification settings - Fork 36
Expose the execution engine module from the SDK #4015
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
2155ff7
Expose the execution engine module from the SDK
xIrusux bb6b9ae
Automatic frontend build
xIrusux 6294607
Merge remote-tracking branch 'origin/2026.x' into feature/expose-exec…
xIrusux 83b7d6e
Complete the execution-engine SDK surface and document it
xIrusux 9cbbd74
Automatic frontend build
xIrusux 6beeb1c
Trim the execution-engine SDK barrel to what a job needs
xIrusux 6028c4f
Automatic frontend build
xIrusux File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| /** | ||
| * This source file is available under the terms of the | ||
| * Pimcore Open Core License (POCL) | ||
| * Full copyright and license information is available in | ||
| * LICENSE.md which is distributed with this source code. | ||
| * | ||
| * @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com) | ||
| * @license Pimcore Open Core License (POCL) | ||
| */ | ||
|
|
||
| if (module.hot !== undefined) { | ||
| module.hot.accept() | ||
| } | ||
|
|
||
| export type { ExecutionEngine } from '@Pimcore/modules/execution-engine/services/execution-engine' | ||
| export { useExecutionEngine } from '@Pimcore/modules/execution-engine/hooks/use-execution-engine' | ||
|
|
||
| export { JobStatus } from '@Pimcore/modules/execution-engine/jobs/abstact-job' | ||
| export type { JobInterface, JobRunOptions } from '@Pimcore/modules/execution-engine/jobs/job-interface' | ||
|
|
||
| export { MessageBusJobHandler } from '@Pimcore/modules/execution-engine/message-handlers/message-bus-job/message-bus-job-handler' | ||
| export type { | ||
| JobCompletionData, | ||
| MessageBusJob, | ||
| MessageBusJobHandlerOptions | ||
| } from '@Pimcore/modules/execution-engine/message-handlers/message-bus-job/message-bus-job-handler-types' | ||
| export type { JobButtonCustomizationContext } from '@Pimcore/modules/execution-engine/message-handlers/message-bus-job/message-bus-job-notification' | ||
|
|
||
| export { | ||
| PROGRESS_NO_UPDATE, | ||
| type ProgressCalculator, | ||
| type ProgressCalculatorContext, | ||
| type ProgressResult | ||
| } from '@Pimcore/modules/execution-engine/message-handlers/message-bus-job/progress-calculator/progress-calculator.interface' | ||
| export { StepCompletionCalculator } from '@Pimcore/modules/execution-engine/message-handlers/message-bus-job/progress-calculator/step-completion-calculator' | ||
| export type { StepTracker, StepTrackerState } from '@Pimcore/modules/execution-engine/message-handlers/message-bus-job/step-tracker/step-tracker.interface' | ||
|
|
||
| export { JobRehydrationRegistry } from '@Pimcore/modules/execution-engine/services/job-rehydration-registry' | ||
| export type { JobRunList, RehydratableJob } from '@Pimcore/modules/execution-engine/services/job-rehydration-registry' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file renamed
BIN
+4.27 MB
build-dist/build-bcccad9cab40.zip → build-dist/build-50d19e526ddc.zip
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
doc/04_Extending/02_Plugin_Development_Examples/20_Run_a_Background_Job.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| --- | ||
| title: How to Run a Background Job | ||
| --- | ||
|
|
||
| # How to Run a Background Job | ||
|
|
||
| ## Overview | ||
| Start a long-running operation from your plugin, show it in the running-jobs panel with progress, retry and error details, and keep it there across page reloads. | ||
|
|
||
| ## Details | ||
| Pimcore Studio runs long operations through the Generic Execution Engine. The frontend never polls your endpoint: the backend publishes progress and the terminal state over Mercure to the user's private topic, and the `execution-engine` module renders those updates in the jobs panel. Both sides have to follow a small contract. | ||
|
|
||
| ### Backend | ||
| - Start the job with `JobExecutionAgentInterface::startJobExecution($job, $userId, Config::CONTEXT_CONTINUE_ON_ERROR->value)` (or `CONTEXT_STOP_ON_ERROR`). Only runs in one of these two Studio execution contexts, owned by the current user, are listed by the running-jobs endpoint and can be rehydrated after a reload. | ||
| - Return the run id from your controller as `201 { "jobRunId": <int> }`. | ||
| - Publish progress from your step handlers with `HandlerProgressTrait::updateProgress()`. | ||
| - Add a `JobRunStateChangedEvent` subscriber filtered on your job name that publishes `Finished` to `UserTopicServiceInterface::getUserTopic($ownerId)` for `FINISHED`, and calls `EventSubscriberServiceInterface::handleFinishedWithErrors()` for `FINISHED_WITH_ERRORS`. `FAILED` is already published by Studio's `FailureSubscriber` for the two Studio contexts. | ||
|
|
||
| ### Frontend | ||
| - Implement `JobInterface`. Declare `static readonly jobNames` with your backend job name(s) and `static rehydrate(jobRuns)`; both `run()` and `rehydrate()` build the same `MessageBusJobHandler`. | ||
| - Register the class in your module's `onInit()` on the `JobRehydrationRegistry` service. `ExecutionEngine.runJob()` throws for a job whose names are not registered. | ||
| - Run it with `useExecutionEngine().runJob(new MyJob(...))`. `runJob()` resolves once the request is dispatched and the handler registered, not when the job ends; put completion side effects in `onJobCompletion`. | ||
| - Pass `StepCompletionCalculator` as `progressCalculator` when each backend step completes as a unit. For any other progress shape implement `ProgressCalculator`; `calculateProgress()` returns a number (0–100), `null` (indeterminate) or `PROGRESS_NO_UPDATE` (leave the bar as is). | ||
|
|
||
| ```typescript | ||
| import { t } from 'i18next' | ||
| import { store } from '@pimcore/studio-ui-bundle/app' | ||
| import { | ||
| MessageBusJobHandler, | ||
| StepCompletionCalculator, | ||
| type JobCompletionData, | ||
| type JobInterface, | ||
| type JobRunList, | ||
| type JobRunOptions, | ||
| type RehydratableJob | ||
| } from '@pimcore/studio-ui-bundle/modules/execution-engine' | ||
| import { api } from '../my-api-slice-enhanced' | ||
|
|
||
| export class MyJob implements JobInterface { | ||
| static readonly jobNames = ['my_bundle_job'] as const | ||
|
|
||
| static rehydrate ([jobRun]: JobRunList): MessageBusJobHandler { | ||
| return MyJob.buildHandler({ jobRunId: jobRun.id }) | ||
| } | ||
|
|
||
| private static buildHandler (options: { jobRunId: number, onRetry?: () => Promise<void> }): MessageBusJobHandler { | ||
| return new MessageBusJobHandler({ | ||
| jobRunId: options.jobRunId, | ||
| title: t('my-bundle.job-title'), | ||
| progressCalculator: new StepCompletionCalculator(), | ||
| onRetry: options.onRetry, | ||
| onJobCompletion: async (data: JobCompletionData): Promise<void> => { | ||
| if (data.isFinished) { | ||
| store.dispatch(api.util.invalidateTags(['MyData'])) | ||
| } | ||
| } | ||
| }) | ||
| } | ||
|
|
||
| async run (options: JobRunOptions): Promise<void> { | ||
| const response = await store.dispatch(api.endpoints.myBundleStartJob.initiate({})) | ||
| const jobRunId = response.data?.jobRunId | ||
|
|
||
| if (jobRunId === undefined) { | ||
| return | ||
| } | ||
|
|
||
| options.messageBus.registerHandler(MyJob.buildHandler({ | ||
| jobRunId, | ||
| onRetry: async () => { await this.run(options) } | ||
| })) | ||
| } | ||
| } | ||
|
|
||
| void (MyJob satisfies RehydratableJob) | ||
| ``` | ||
|
|
||
| ```typescript | ||
| // in your module's onInit() | ||
| import { container } from '@pimcore/studio-ui-bundle' | ||
| import { serviceIds } from '@pimcore/studio-ui-bundle/app' | ||
| import { type JobRehydrationRegistry } from '@pimcore/studio-ui-bundle/modules/execution-engine' | ||
|
|
||
| container | ||
| .get<JobRehydrationRegistry>(serviceIds['ExecutionEngine/JobRehydrationRegistry']) | ||
| .register(MyJob) | ||
| ``` | ||
|
|
||
| ## Code Example on GitHub | ||
| > A complete in-repo example is the bulk import job: [bulk-import-job.ts](https://github.com/pimcore/studio-ui-bundle/blob/2026.x/assets/js/src/core/modules/bulk-import/jobs/bulk-import-job.ts), registered in [bulk-import/index.ts](https://github.com/pimcore/studio-ui-bundle/blob/2026.x/assets/js/src/core/modules/bulk-import/index.ts). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.