-
Notifications
You must be signed in to change notification settings - Fork 6
more improvements #26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -104,6 +104,11 @@ public static string EmitSource(List<WorkerInvocationModel> workers) | |||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" // Worker state tracking for observable gauges"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" private static readonly System.Collections.Concurrent.ConcurrentDictionary<string, WorkerState> _workerStates = new();"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" // Cached snapshot for gauge enumeration optimization"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" private static WorkerState[]? _cachedSnapshot;"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" private static int _snapshotVersion;"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" private static int _currentVersion;"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" internal sealed class WorkerState"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" {"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" public string WorkerId { get; set; } = string.Empty;"); | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -114,6 +119,24 @@ public static string EmitSource(List<WorkerInvocationModel> workers) | |||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" public long ConsecutiveFailures { get; set; }"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" }"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" /// <summary>"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" /// Gets a cached snapshot of worker states, only re-allocating when workers are added/removed."); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" /// </summary>"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" private static WorkerState[] GetWorkerStatesSnapshot()"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" {"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" var version = Volatile.Read(ref _currentVersion);"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" var cached = _cachedSnapshot;"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" if (cached != null && _snapshotVersion == version)"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" {"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" return cached;"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" }"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" // Version changed or no cache - create new snapshot"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" var snapshot = _workerStates.Values.ToArray();"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" _cachedSnapshot = snapshot;"); | ||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" _snapshotVersion = version;"); | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+128
to
+136
|
||||||||||||||||||||||||||||||||||||||||
| sb.AppendLine(" var cached = _cachedSnapshot;"); | |
| sb.AppendLine(" if (cached != null && _snapshotVersion == version)"); | |
| sb.AppendLine(" {"); | |
| sb.AppendLine(" return cached;"); | |
| sb.AppendLine(" }"); | |
| sb.AppendLine(" // Version changed or no cache - create new snapshot"); | |
| sb.AppendLine(" var snapshot = _workerStates.Values.ToArray();"); | |
| sb.AppendLine(" _cachedSnapshot = snapshot;"); | |
| sb.AppendLine(" _snapshotVersion = version;"); | |
| sb.AppendLine(" var cached = Volatile.Read(ref _cachedSnapshot);"); | |
| sb.AppendLine(" var cachedVersion = Volatile.Read(ref _snapshotVersion);"); | |
| sb.AppendLine(" if (cached != null && cachedVersion == version)"); | |
| sb.AppendLine(" {"); | |
| sb.AppendLine(" return cached;"); | |
| sb.AppendLine(" }"); | |
| sb.AppendLine(" // Version changed or no cache - create new snapshot"); | |
| sb.AppendLine(" var snapshot = _workerStates.Values.ToArray();"); | |
| sb.AppendLine(" Volatile.Write(ref _cachedSnapshot, snapshot);"); | |
| sb.AppendLine(" Volatile.Write(ref _snapshotVersion, version);"); |
Copilot
AI
Feb 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Signature normalization here may not match the runtime BackgroundWorkerExtensions.FormatTypeName output for nested types: Type.FullName uses + between declaring and nested types, while Roslyn’s FullyQualifiedFormat typically uses .. That would produce a registration.Signature that never matches any generated initializer, and the worker won’t start. Consider normalizing nested type separators consistently on both sides (e.g., replace + with . in FormatTypeName, or adjust generator signature formatting to match Type.FullName).
Copilot
AI
Feb 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
workerMap is a Dictionary, and later you generate initializer method numbers by enumerating workerMap while the signature→method mapping is produced from a different dictionary (signatureToMethod). Since Dictionary enumeration order is not guaranteed by contract, it’s possible for the emitted InitializeWorker_{n} methods to not align with the numbers referenced in _workerInitializers, resulting in the wrong initializer being invoked for a signature (and likely invalid casts at runtime). Use a deterministic ordered sequence (e.g., a List of signatures in insertion order) to drive both the _workerInitializers entries and the emitted InitializeWorker_{n} methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The emitted XML doc says the snapshot is only re-allocated when workers are added/removed, but the generated code invalidates the cache on
DeactivateWorker(a state change, not an add/remove). Either update the comment to match the actual invalidation behavior, or avoid invalidating on deactivation if the goal is strictly “add/remove” (the snapshot contains references, soIsActivechanges are already observable without reallocation).