Repository navigation
fix: save recurrence changes that keep the same expression - #8
Merged
Merged
Conversation
SetRecurrenceAsync promised to update a recurrence when its data changed, but UpdateAsync only acted on a new cron expression: new data or options with the same expression were silently dropped. JobOptions also compared the retry delays by reference, so a recurrence read from the store almost never equalled the new one. - JobOptions compares and hashes the retry delays by value. - Any change of the expression, data or options updates the recurrence. The job waiting for the next occurrence is reconfigured in place (Job.Reconfigure) and, for a new expression, moved to the new time, instead of a second job being added next to it (which used to run once more on the old schedule). A running job keeps its settings; the next one is created from the updated recurrence. If a runner takes the waiting job meanwhile, the recurrence is still updated. - The EF store saves a job's data and options on update. RecurringJobBuilderTests.SetRecurrenceAsync_ExistingRecurrenceWithSameRule_DoesNotUpdate passed only because of the bug (its stored data and options differed from what the builder produces); it now compares an unchanged recurrence. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Problem
The README says
SetRecurrenceAsyncis "safe to call on every startup — only updates if the expression or data changed", but:RecurringJobBuilder.UpdateAsyncacted only on a new cron expression. New data or options with the same expression were silently dropped: neither the recurrence nor its next job changed.JobOptions.EqualscomparedRetryDelaysInSecondsby reference, so a recurrence read back from the store almost never equalled the new one.Fix
JobOptionscompares and hashes the retry delays by value.Job.Reconfigure) and, for a new expression, moved to the new time. No second job, nothing runs twice or with old settings;Tests
RecurrenceUpdateTests(unit): unchanged recurrence read back from the store writes nothing; data change, options change, expression change, running job, completed job, runner race;JobOptionsvalue equality. 8 of them fail on the old code.StoreJobTestsBase.UpdateAsync_Reconfigured_PersistsDataOptionsAndTime, run on PostgreSQL and SQL Server.RecurringJobBuilderTests.SetRecurrenceAsync_ExistingRecurrenceWithSameRule_DoesNotUpdatepassed only because of the bug: its stored data (anonymous type vsSystem.Object) and options differed from what the builder produces. It now compares a truly unchanged recurrence (..._ExistingRecurrenceUnchanged_DoesNotUpdate), and..._WithSameRuleButOtherOptions_Updatescovers the change.71 unit tests pass on net8.0, net9.0, net10.0; 38 storage tests each on PostgreSQL and SQL Server.
Behaviour change
After changing the expression, the old schedule no longer gets one extra run.
Independent of #7; the two branches merge without conflicts.
🤖 Generated with Claude Code