Skip to content

Conversation

robversluis
Copy link

##Summary
Adds a workflow "Execution priority" setting (high/medium/low) that maps to Bull job priority so urgent executions run first under load.

##Changes

Backend (packages/cli/src/workflow-runner.ts): Map workflow.settings.queuePriority to Bull job option priority when enqueuing via scalingService.addJob(). Mapping: high=1, medium=50, low=100. If unset, fallback to previous behavior using realtime (50 when true, else 100). Uses a type guard (no assertions) and robust fallback to avoid passing undefined to Bull.
Frontend (packages/frontend/editor-ui/src/components/WorkflowSettings.vue): Add "Execution priority" select bound to workflowSettings.queuePriority. Disabled in read-only env or without update permissions.
Types: Add optional queuePriority to IWorkflowSettings in backend (packages/workflow/src/interfaces.ts) and frontend (packages/frontend/editor-ui/src/Interface.ts).
i18n: Add English keys in packages/frontend/@n8n/i18n/src/locales/en.json for label, placeholder, and options (low/medium/high).
Tests (packages/cli/src/tests/workflow-runner.test.ts): Verify mapping and fallback behavior.
Behavior

Lower numeric Bull priority runs sooner (1 is highest). Ordering is per-queue; concurrency/delays/retries still apply. Default remains effectively "Medium" when unset via realtime fallback.

##Notes
Minimal, non-disruptive change reusing existing queue infrastructure and settings patterns. Future follow-ups: docs entry for the setting; translations for other locales; optional e2e test under load.

…p to Bull job priority; add UI + i18n; tests
feat(queue): add workflow execution priority (high/medium/low)
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 issues found across 6 files

React with 👍 or 👎 to teach cubic. You can also tag @cubic-dev-ai to give feedback, ask questions, or re-run the review.

@@ -381,7 +381,20 @@ export class WorkflowRunner {
let job: Job;
let lifecycleHooks: ExecutionLifecycleHooks;
try {
job = await this.scalingService.addJob(jobData, { priority: realtime ? 50 : 100 });
// Determine numeric Bull priority. Lower numbers are higher priority.
const qp = data.workflowData?.settings?.queuePriority as
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rule violated: Prefer Typeguards over Type casting

Avoid as for type narrowing; use a variable type annotation or a type guard for queuePriority.

(Based on your team's feedback about avoiding as casts and aligning local variable types with existing API types, prefer type guards or type annotations over assertions.)

Prompt for AI agents
Address the following comment on packages/cli/src/workflow-runner.ts at line 385:

<comment>Avoid `as` for type narrowing; use a variable type annotation or a type guard for `queuePriority`.

(Based on your team&#39;s feedback about avoiding `as` casts and aligning local variable types with existing API types, prefer type guards or type annotations over assertions.)</comment>

<file context>
@@ -381,7 +381,20 @@ export class WorkflowRunner {
 		try {
-			job = await this.scalingService.addJob(jobData, { priority: realtime ? 50 : 100 });
+			// Determine numeric Bull priority. Lower numbers are higher priority.
+			const qp = data.workflowData?.settings?.queuePriority as
+				| &#39;low&#39;
+				| &#39;medium&#39;
</file context>

@@ -568,6 +568,8 @@ export interface IWorkflowSettings extends IWorkflowSettingsWorkflow {
callerIds?: string;
callerPolicy?: WorkflowSettings.CallerPolicy;
executionOrder: NonNullable<IWorkflowSettingsWorkflow['executionOrder']>;
/** Optional queue execution priority for queued workflow runs */
queuePriority?: 'low' | 'medium' | 'high';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

queuePriority is already defined on IWorkflowSettingsWorkflow (from n8n-workflow); redeclaring it here is redundant and risks divergence if the base changes. Remove the redeclaration and rely on the inherited property.

(Based on your team's feedback about aligning local types with existing API/library types to avoid redundant declarations.)

Prompt for AI agents
Address the following comment on packages/frontend/editor-ui/src/Interface.ts at line 572:

<comment>queuePriority is already defined on IWorkflowSettingsWorkflow (from n8n-workflow); redeclaring it here is redundant and risks divergence if the base changes. Remove the redeclaration and rely on the inherited property.

(Based on your team&#39;s feedback about aligning local types with existing API/library types to avoid redundant declarations.)</comment>

<file context>
@@ -568,6 +568,8 @@ export interface IWorkflowSettings extends IWorkflowSettingsWorkflow {
 	callerPolicy?: WorkflowSettings.CallerPolicy;
 	executionOrder: NonNullable&lt;IWorkflowSettingsWorkflow[&#39;executionOrder&#39;]&gt;;
+	/** Optional queue execution priority for queued workflow runs */
+	queuePriority?: &#39;low&#39; | &#39;medium&#39; | &#39;high&#39;;
 }
 
</file context>

medium: 50,
low: 100,
};
const computedPriority = qp ? priorityMap[qp] : realtime ? 50 : 100;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

computedPriority may become undefined when queuePriority is an unexpected string, causing addJob() to assert on invalid priority; validate qp against priorityMap before indexing to preserve the realtime fallback.

(Based on previous feedback about avoiding 'as' assertions and using type guards to validate values before narrowing.)

Prompt for AI agents
Address the following comment on packages/cli/src/workflow-runner.ts at line 395:

<comment>computedPriority may become undefined when queuePriority is an unexpected string, causing addJob() to assert on invalid priority; validate qp against priorityMap before indexing to preserve the realtime fallback.

(Based on previous feedback about avoiding &#39;as&#39; assertions and using type guards to validate values before narrowing.)</comment>

<file context>
@@ -381,7 +381,20 @@ export class WorkflowRunner {
+				medium: 50,
+				low: 100,
+			};
+			const computedPriority = qp ? priorityMap[qp] : realtime ? 50 : 100;
+
+			job = await this.scalingService.addJob(jobData, { priority: computedPriority });
</file context>

@@ -464,6 +478,9 @@ onMounted(async () => {
if (workflowSettingsData.executionOrder === undefined) {
workflowSettingsData.executionOrder = 'v0';
}
if (workflowSettingsData.queuePriority === undefined) {
workflowSettingsData.queuePriority = 'medium';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defaulting queuePriority to 'medium' in the UI overrides backend fallback behavior on save (e.g., workflows with realtime=false would shift from 100/low to 50/medium). Leave it undefined until users choose a value.

Prompt for AI agents
Address the following comment on packages/frontend/editor-ui/src/components/WorkflowSettings.vue at line 482:

<comment>Defaulting queuePriority to &#39;medium&#39; in the UI overrides backend fallback behavior on save (e.g., workflows with realtime=false would shift from 100/low to 50/medium). Leave it undefined until users choose a value.</comment>

<file context>
@@ -464,6 +478,9 @@ onMounted(async () =&gt; {
 		workflowSettingsData.executionOrder = &#39;v0&#39;;
 	}
+	if (workflowSettingsData.queuePriority === undefined) {
+		workflowSettingsData.queuePriority = &#39;medium&#39;;
+	}
 
</file context>

@n8n-assistant n8n-assistant bot added community Authored by a community member core Enhancement outside /nodes-base and /editor-ui in linear Issue or PR has been created in Linear for internal review labels Sep 1, 2025
@Joffcom
Copy link
Member

Joffcom commented Sep 1, 2025

Hey @robversluis,

Thank you for your contribution. We appreciate the time and effort you’ve taken to submit this pull request.

Before we can proceed, please ensure the following:
• Tests are included for any new functionality, logic changes or bug fixes.
• The PR aligns with our contribution guidelines.

Regarding new nodes:
We no longer accept new nodes directly into the core codebase. Instead, we encourage contributors to follow our Community Node Submission Guide to publish nodes independently.

If your node integrates with an AI service that you own or represent, please email nodes@n8n.io and we will be happy to discuss the best approach.

About review timelines:
This PR has been added to our internal tracker as "GHC-4157". While we plan to review it, we are currently unable to provide an exact timeframe. Our goal is to begin reviews within a month, but this may change depending on team priorities. We will reach out when the review begins.

Thank you again for contributing to n8n.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
community Authored by a community member core Enhancement outside /nodes-base and /editor-ui in linear Issue or PR has been created in Linear for internal review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants