Conversation
…Registry.cs, MiniCronTests.EventInvocationOutsideLock.cs Co-authored-by: jeanlrnt <63308635+jeanlrnt@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Refactor event invocation in WriteLock to prevent deadlocks
Refactor: Invoke JobRegistry events outside WriteLock to prevent blocking and deadlocks
Jan 2, 2026
jeanlrnt
approved these changes
Jan 2, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
This PR refactors JobRegistry to invoke lifecycle events (JobAdded, JobRemoved, JobUpdated) outside the WriteLock, preventing slow event handlers from blocking registry operations and eliminating deadlock risk when handlers call back into the registry.
Key Changes:
- Event invocation moved outside WriteLock with exception handling
- Event data captured inside lock, then events invoked after lock release
- Updated XML documentation to reflect new "invoked after lock released" behavior
- Added 8 comprehensive concurrency tests verifying non-blocking behavior
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
| src/MiniCron.Core/Services/JobRegistry.cs | Refactored ScheduleJob, RemoveJob, and UpdateSchedule to prepare event args inside lock but invoke events outside; updated XML docs to clarify events are raised after lock release |
| src/MiniCron.Tests/MiniCronTests.EventInvocationOutsideLock.cs | Added comprehensive test suite verifying events don't block concurrent reads, exception handling, safe re-entrance, and correct event args |
Owner
|
@copilot apply changes based on the comments in this thread |
…variables, and redundant null checks Co-authored-by: jeanlrnt <63308635+jeanlrnt@users.noreply.github.com>
jeanlrnt
approved these changes
Jan 2, 2026
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.
✅ Refactoring Complete: Move Event Invocation Outside WriteLock
Summary
Successfully refactored
JobRegistry.csto invoke lifecycle events (JobAdded,JobRemoved,JobUpdated) outside the WriteLock, preventing blocking of the scheduler and reducing deadlock risk.Changes Completed
ScheduleJob(string, Func<IServiceProvider, CancellationToken, Task>)to invokeJobAddedoutside WriteLockScheduleJob(string, Func<IServiceProvider, CancellationToken, Task>, TimeSpan?)to invokeJobAddedoutside WriteLockRemoveJob(Guid)to invokeJobRemovedoutside WriteLockUpdateSchedule(Guid, string)to invokeJobUpdatedoutside WriteLockLatest Changes (PR Review Feedback)
Test Improvements:
GetAwaiter().GetResult()to avoid unobserved exceptionsgetJobsTaskvariables by properly awaiting them withTask.WhenAll()Code Quality Improvements:
RemoveJob(removedJob != nullcheck)UpdateSchedule(updatedJob != null && existingJob != nullchecks)Testing Results
✅ All 155 tests passing (147 original + 8 new tests)
New test coverage in
MiniCronTests.EventInvocationOutsideLock.cs:JobRegistry_JobAdded_InvokedOutsideLock_AllowsConcurrentReads- Verifies JobAdded event doesn't block GetJobs()JobRegistry_JobRemoved_InvokedOutsideLock_AllowsConcurrentReads- Verifies JobRemoved event doesn't block GetJobs()JobRegistry_JobUpdated_InvokedOutsideLock_AllowsConcurrentReads- Verifies JobUpdated event doesn't block GetJobs()JobRegistry_EventHandler_Exception_DoesNotPreventOperation- Exception handling works correctlyJobRegistry_EventHandler_CanCallBackIntoRegistry_NoDeadlock- Safe re-entrance verifiedJobRegistry_JobAdded_EventArgs_ContainCorrectJobInfo- Event args validationJobRegistry_JobUpdated_EventArgs_ContainBothJobs- Event args validation for updatesJobRegistry_NoEventSubscribers_NoEventInvocation- Operations work without subscribersBenefits Achieved
✅ Performance: Slow event listeners no longer block the entire scheduling system
✅ Reliability: Significantly reduced deadlock risk when event handlers interact with JobRegistry
✅ Concurrency:
GetJobs()calls can proceed immediately without waiting for event handlers✅ Safety: Event handlers can safely call back into JobRegistry (tested and verified)
Security Summary
✅ CodeQL analysis completed - No vulnerabilities found
✅ No new security risks introduced
✅ Exception handling properly maintained
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.