Skip to content

Tidy tenant-aware Quartz job factory - #9126

Merged
sfmskywalker merged 1 commit into
mainfrom
cursor/tidy-tenant-aware-quartz-factory-d1c1
Oct 29, 2026
Merged

sfmskywalker merged 1 commit into
mainfrom
cursor/tidy-tenant-aware-quartz-factory-d1c1

Conversation

@sfmskywalker

@sfmskywalker sfmskywalker commented Oct 29, 2026 •

Copy link
Copy Markdown
Member

Small follow-up to #9121:

  1. One shared helper now reads TenantId from trigger data, then job data, for both the factory and the Execute guard.
  2. Workflow-job EnsureScheduledTenant guard tests also assert that no retry is scheduled and that no job or trigger is deleted.
  3. CS9107 is gone: TenantAwareJobFactory uses a regular constructor instead of a primary constructor that captured IServiceProvider twice. Behaviour is unchanged.

The synchronous tenant lookup stays on the scheduler thread. No timeout or cache was added.

Open in Web Open in Cursor 

Summary by CodeRabbit

  • Bug Fixes
    • Scheduled jobs now determine the tenant from trigger data first, then fall back to job data. This helps ensure jobs run in the tenant specified by their scheduling information. When tenant lookup fails, job execution continues to avoid scheduling retries or removing or unscheduling triggers.

Share one TenantId reader between the factory and the Execute guard,
assert that workflow guard failures do not retry or delete, and replace
the primary constructor that produced CS9107.

Co-authored-by: Sipke Schoorstra <sipkeschoorstra@outlook.com>
@sfmskywalker sfmskywalker added area:runtime Quality loop area: runtime bug Something isn't working elsa 3 This issue is specific to Elsa 3 prio low Is not on the roadmap for the near-future labels Oct 29, 2026 — with Cursor
@sfmskywalker

Copy link
Copy Markdown
Member Author

@elsa-workflows-bot review

@sfmskywalker

Copy link
Copy Markdown
Member Author

@greptileai

@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 45e8e8e0-e85a-4b34-9bda-8a2e51b1d51e
Commits

Reviewing files that changed from the base of the PR and between 0cceb5a and 8d1a809.

Files selected for processing: 4
  • extensions/src/scheduling/Elsa.Scheduling.Quartz/Extensions/JobExecutionExtensions.cs
  • extensions/src/scheduling/Elsa.Scheduling.Quartz/Services/TenantAwareJobFactory.cs
  • extensions/test/modules/scheduling/Elsa.Scheduling.Quartz.UnitTests/Jobs/ResumeWorkflowJobTests.cs
  • extensions/test/modules/scheduling/Elsa.Scheduling.Quartz.UnitTests/Jobs/RunWorkflowJobTests.cs

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

Walkthrough

The change adds a shared reader for scheduled tenant IDs and uses it in tenant checks and job creation. The reader checks trigger data before job data. Tests assert that tenant error paths do not modify scheduler triggers or jobs.

Changes: Quartz tenant resolution

Layer / File(s) Summary
Shared tenant ID resolution
extensions/src/scheduling/Elsa.Scheduling.Quartz/Extensions/JobExecutionExtensions.cs, extensions/src/scheduling/Elsa.Scheduling.Quartz/Services/TenantAwareJobFactory.cs
EnsureScheduledTenant and TenantAwareJobFactory use the shared tenant ID reader. The reader checks trigger data before job data and no longer checks MergedJobDataMap.
Tenant error test assertions
extensions/test/modules/scheduling/Elsa.Scheduling.Quartz.UnitTests/Jobs/ResumeWorkflowJobTests.cs, extensions/test/modules/scheduling/Elsa.Scheduling.Quartz.UnitTests/Jobs/RunWorkflowJobTests.cs
Tests assert that the specified tenant error paths do not schedule retries, delete jobs, or unschedule triggers.

Priority: Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Refactor

Possibly related issues

  • elsa-workflows/elsa-core#9120 — The issue describes Quartz timers and Cron triggers firing only for the default tenant. This change reads tenant IDs from trigger data or job data, but the provided summary does not confirm it resolves every reported symptom.

Possibly related PRs

  • elsa-workflows/elsa-core#9121 — This PR introduced TenantAwareJobFactory and EnsureScheduledTenant, which this change updates to use shared tenant ID extraction.

Suggested reviewers: elsa-workflows-review-bot

Merge Risk: Minimal · up to 8d1a8

This tidy-up shares one tenant ID reader between the job factory and the execute guard and adds test assertions. It does not change behavior for tenant IDs supplied through trigger or job data. Merging carries no concrete risk.

Pre-merge checks: Passed 3 · Failed 2

Failed Failed checks: 2 warnings

Check name Status Explanation Resolution
Description check Warning The description explains the main changes and constraints, but it omits most required template sections, including Purpose, Scope, Problem, Solution, Verification, Expected outcome, Screenshots/Record… Update the description to use the repository template. Add a Purpose summary, select the primary Scope, describe the Problem and Solution, provide verification steps and expected results, address Screenshots/Recordings as applicable, and co…
Docstring Coverage Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documenta… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 3 passed
Check name Status Explanation
Title check Passed The title clearly and concisely identifies the main change to the tenant-aware Quartz job factory.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description explains the main changes and constraints, but it omits most required template sections, including Purpose, Scope, Problem, Solution, Verification, Expected outcome, Screenshots/Recordings, and Checklist.

Resolution

Update the description to use the repository template. Add a Purpose summary, select the primary Scope, describe the Problem and Solution, provide verification steps and expected results, address Screenshots/Recordings as applicable, and complete the Checklist.

Full details: Docstring Coverage

Explanation

Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 3 functions across 4 files.

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@elsa-3-lead elsa-3-lead Bot added this to the 3.11 milestone Oct 29, 2026
@greptile-apps

greptile-apps Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] Safe to merge within the reviewed scope; no actionable findings remain.

Summary

This PR shares tenant-ID lookup between the Quartz job factory and the execution guard, replaces the factory’s primary constructor with an explicit constructor, and strengthens rejection tests to check that retries, job deletion, and trigger removal do not occur.

No actionable issues were found. Focused before-and-after checks passed all 66 tests on both revisions, including 24 additional tenant-selection contract cases. A separate comparison of the two workflow-job test classes passed all 33 tests on both revisions using the strengthened assertions.

The tested behavior preserves trigger-over-job tenant precedence, fallback for missing or invalid tenant values, tenant-scoped job construction, and rejection before workflow execution or scheduler side effects. Safe to merge within the reviewed scope.

  • Quartz jobs use one shared lookup for their scheduled tenant.

Reviews (1) · Last reviewed commit: "refactor(scheduling): tidy tenant-aware ..." · Reviewed by Greptile

@elsa-workflows-review-bot elsa-workflows-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Elsa 3 Code Review: APPROVE + HIGH @ 8d1a809

Code Review, Round 1/6

Scope: follow-up to #9121. One shared TenantId reader for TenantAwareJobFactory and EnsureScheduledTenant, a regular constructor in place of the primary constructor (CS9107), and stronger guard tests.

Correctness

  • ReadScheduledTenantId(triggerData, jobData) keeps the same order as before: trigger data first, then job data. The factory and the Execute guard now can't drift apart.
  • The guard no longer falls back to MergedJobDataMap. Quartz builds that map from the job detail's map plus the trigger's map, so the two direct lookups already cover it. Same behaviour, one less path.
  • The factory's lookup now also accepts a non-TryGetString string value and tolerates a null map. That is a little more lenient than before and matches what the guard already did. No regression.
  • The explicit constructor stores IServiceProvider once. Lookup, push and retry behaviour in InstantiateJob and TenantLookupFailedJob are unchanged.

Tests

  • The RunWorkflowJob and ResumeWorkflowJob guard tests now check that no retry is scheduled and that no job or trigger is deleted or unscheduled. These are the right checks for a fail-loudly guard.
  • The existing TenantAwareJobFactory and module-path tests cover the shared reader through the factory.

Non-blocking

  • ReadScheduledTenantId(this IJobExecutionContext) is a new public extension on a public class. Both callers are in this assembly, so internal would be enough and would keep the public API from growing. Optional.

Bots

  • Greptile: 5/5, no actionable findings. No inline bot threads.

CI

All checks on 8d1a8090 are green: ubuntu-latest (compile + test), CodeQL, GitGuardian and CLA. run-affected-tests was skipped by selection, and ubuntu-latest ran the full suite.

Nothing actionable remains.

— Code Review (Elsa 3), via Elsa Review

@sfmskywalker
sfmskywalker merged commit 24fb910 into main Oct 29, 2026
17 checks passed
@sfmskywalker
sfmskywalker deleted the cursor/tidy-tenant-aware-quartz-factory-d1c1 branch October 29, 2026 19:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:runtime Quality loop area: runtime bug Something isn't working elsa 3 This issue is specific to Elsa 3 prio low Is not on the roadmap for the near-future

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants