Skip to content

Fix PreviousFireTimeUtc reset to null on restart with OverWriteExistingData (#1834)#2957

Merged
lahma merged 1 commit into
3.xfrom
fix/1834-preserve-prev-fire-time-3x
Mar 29, 2026
Merged

Fix PreviousFireTimeUtc reset to null on restart with OverWriteExistingData (#1834)#2957
lahma merged 1 commit into
3.xfrom
fix/1834-preserve-prev-fire-time-3x

Conversation

@lahma

@lahma lahma commented Mar 29, 2026

Copy link
Copy Markdown
Member

Summary

  • Fix PreviousFireTimeUtc being reset to null in the database when a trigger is re-stored with replaceExisting=true (e.g., on application restart with OverWriteExistingData=true, the default)
  • When StoreTrigger updates an existing trigger and the new trigger's PreviousFireTimeUtc is null, preserve the value from the existing database trigger
  • Add two unit tests: one verifying preservation when replacing, one verifying no override when the new trigger already has PreviousFireTimeUtc set

Fixes #1834

Test plan

  • StoreTrigger_PreservesPreviousFireTimeUtc_WhenReplacingExistingTrigger -- verifies the existing trigger's PreviousFireTimeUtc is carried forward
  • StoreTrigger_DoesNotOverridePreviousFireTimeUtc_WhenNewTriggerAlreadyHasIt -- verifies that an explicitly set value on the new trigger is not overwritten
  • Full unit test suite passes (1024 passed, 0 failed)

🤖 Generated with Claude Code

@lahma lahma added the port-main Requires porting to main branch label Mar 29, 2026
…ngData=true (#1834)

When OverWriteExistingData is true (the default), restarting the application
would overwrite PREV_FIRE_TIME in the database with null from the freshly
constructed trigger object. This caused context.PreviousFireTimeUtc to always
be null on the first execution after a restart.

The fix preserves PreviousFireTimeUtc from the existing database trigger when
the replacement trigger's PreviousFireTimeUtc is null, which is the common
case during application restart.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@lahma
lahma force-pushed the fix/1834-preserve-prev-fire-time-3x branch from 5f28af7 to 4ad0d97 Compare March 29, 2026 18:03
@sonarqubecloud

Copy link
Copy Markdown

Copilot AI 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.

Pull request overview

Fixes an ADO JobStore persistence issue where PreviousFireTimeUtc could be reset to null in the database when triggers are re-stored with replaceExisting=true (commonly on restart with OverWriteExistingData=true), which then surfaces as context.PreviousFireTimeUtc == null.

Changes:

  • Preserve PreviousFireTimeUtc when updating an existing trigger if the incoming trigger has PreviousFireTimeUtc == null.
  • Add unit tests covering preservation behavior and ensuring explicitly-set values aren’t overridden.
  • Add a test helper to invoke the protected StoreTrigger path directly.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/Quartz/Impl/AdoJobStore/JobStoreSupport.cs Preserves PreviousFireTimeUtc during trigger replacement by reading the existing trigger before updating.
src/Quartz.Tests.Unit/Impl/AdoJobStore/JobStoreSupportTest.cs Adds tests for the new preservation behavior and a helper to call StoreTrigger.

Comment on lines +1170 to +1175
// Preserve PreviousFireTimeUtc from the existing trigger when replacing,
// so that context.PreviousFireTimeUtc is not lost on application restart (#1834)
if (newTrigger.GetPreviousFireTimeUtc() is null)
{
IOperableTrigger? existingTrig = await Delegate.SelectTrigger(conn, newTrigger.Key, cancellationToken).ConfigureAwait(false);
var prevFireTime = existingTrig?.GetPreviousFireTimeUtc();

Copilot AI Mar 29, 2026

Copy link

Choose a reason for hiding this comment

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

This adds an extra SelectTrigger call when replacing an existing trigger whose PreviousFireTimeUtc is null. SelectTrigger is relatively heavy (loads JobDataMap, schedule details, and may read BLOB triggers), so OverWriteExistingData=true restarts can incur an additional full trigger read per trigger. Consider preserving PREV_FIRE_TIME at the SQL update level instead (e.g., update PREV_FIRE_TIME = COALESCE(@triggerPreviousFireTime, PREV_FIRE_TIME) in SqlUpdateTrigger/SqlUpdateTriggerSkipData) so the existing value is kept without loading the entire trigger from the DB.

Copilot uses AI. Check for mistakes.
@lahma
lahma merged commit e3e620e into 3.x Mar 29, 2026
19 checks passed
@lahma
lahma deleted the fix/1834-preserve-prev-fire-time-3x branch March 29, 2026 18:33
lahma added a commit that referenced this pull request Mar 29, 2026
…ngData (#1834)

When StoreTrigger replaces an existing trigger (e.g., on restart with
OverWriteExistingData=true), the new trigger's PreviousFireTimeUtc is
null. Now preserves the value from the existing DB trigger via
Delegate.SelectTrigger before updating.

Port of 3.x PR #2957.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@lahma lahma removed the port-main Requires porting to main branch label Mar 29, 2026
lahma added a commit that referenced this pull request Mar 29, 2026
…ngData (#1834) (#2959)

When StoreTrigger replaces an existing trigger (e.g., on restart with
OverWriteExistingData=true), the new trigger's PreviousFireTimeUtc is
null. Now preserves the value from the existing DB trigger via
Delegate.SelectTrigger before updating.

Port of 3.x PR #2957.

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
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.

2 participants