Skip to content

Commit 70bbd88

Browse files
jschick04NikTilton
authored andcommitted
Updated Load Events to use an immutable array
1 parent 9307605 commit 70bbd88

File tree

8 files changed

+32
-48
lines changed

8 files changed

+32
-48
lines changed

src/EventLogExpert.Eventing/EventResolvers/EventResolverBase.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -599,8 +599,8 @@ private string ResolveDescription(EventRecord eventRecord, ProviderDetails? deta
599599
return FormatDescription(properties, modernEvent?.Description, details.Parameters);
600600
}
601601

602-
// Legacy provider message lookup using indexed dictionary
603-
var legacyMessages = details.GetMessagesByShortId((short)eventRecord.Id);
602+
// Legacy provider message lookup
603+
var legacyMessages = details.GetMessagesByShortId(eventRecord.Id);
604604

605605
if (legacyMessages.Count == 1)
606606
{
@@ -658,8 +658,7 @@ private string ResolveTaskName(EventRecord eventRecord, ProviderDetails? details
658658
return _cache?.GetOrAddValue(taskName) ?? taskName;
659659
}
660660

661-
// Use indexed lookup instead of linear scan with .ToList()
662-
var messagesByShortId = details.GetMessagesByShortId((short)eventRecord.Task);
661+
var messagesByShortId = details.GetMessagesByShortId(eventRecord.Task.Value);
663662

664663
List<MessageModel>? potentialTaskNames = null;
665664

src/EventLogExpert.Eventing/Providers/ProviderDetails.cs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public class ProviderDetails
1010
private IReadOnlyList<EventModel> _events = [];
1111
private IReadOnlyList<MessageModel> _messages = [];
1212
private Dictionary<long, List<EventModel>>? _eventsByIdLookup;
13-
private Dictionary<short, List<MessageModel>>? _messagesByShortIdLookup;
13+
private Dictionary<int, List<MessageModel>>? _messagesByShortIdLookup;
1414

1515
public string ProviderName { get; set; } = string.Empty;
1616

@@ -53,8 +53,10 @@ internal IReadOnlyList<EventModel> GetEventsById(long id)
5353
return _eventsByIdLookup.TryGetValue(id, out var list) ? list : [];
5454
}
5555

56-
/// <summary>Gets messages matching the given ShortId using a pre-built lookup dictionary.</summary>
57-
internal IReadOnlyList<MessageModel> GetMessagesByShortId(short shortId)
56+
/// <summary>Gets messages matching the given ShortId using a pre-built lookup dictionary.
57+
/// The lookup uses int keys to preserve the original implicit promotion semantics
58+
/// when comparing ShortId (short) with event record Id/Task (ushort).</summary>
59+
internal IReadOnlyList<MessageModel> GetMessagesByShortId(int shortId)
5860
{
5961
_messagesByShortIdLookup ??= BuildMessagesByShortIdLookup();
6062

@@ -79,16 +81,18 @@ private Dictionary<long, List<EventModel>> BuildEventsByIdLookup()
7981
return lookup;
8082
}
8183

82-
private Dictionary<short, List<MessageModel>> BuildMessagesByShortIdLookup()
84+
private Dictionary<int, List<MessageModel>> BuildMessagesByShortIdLookup()
8385
{
84-
var lookup = new Dictionary<short, List<MessageModel>>();
86+
var lookup = new Dictionary<int, List<MessageModel>>();
8587

8688
foreach (var m in _messages)
8789
{
88-
if (!lookup.TryGetValue(m.ShortId, out var list))
90+
int key = m.ShortId;
91+
92+
if (!lookup.TryGetValue(key, out var list))
8993
{
9094
list = [];
91-
lookup[m.ShortId] = list;
95+
lookup[key] = list;
9296
}
9397

9498
list.Add(m);

src/EventLogExpert.UI.Tests/Store/EventLog/EventLogEffectsTests.cs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,7 @@ public async Task HandleAddEvent_WhenBufferReachesMaxEvents_ShouldSetFullFlag()
3232
var logData = new EventLogData(Constants.LogNameTestLog, PathType.LogName, []);
3333
var activeLogs = ImmutableDictionary<string, EventLogData>.Empty.Add(Constants.LogNameTestLog, logData);
3434

35-
var (effects, mockDispatcher) = CreateEffects(
36-
false,
37-
activeLogs,
38-
existingBuffer);
35+
var (effects, mockDispatcher) = CreateEffects(false, activeLogs, existingBuffer);
3936

4037
var newEvent = EventUtils.CreateTestEvent(1000, logName: Constants.LogNameTestLog);
4138
var action = new EventLogAction.AddEvent(newEvent);
@@ -145,11 +142,10 @@ public async Task HandleCloseLog_ShouldRemoveLogAndDispatchCloseAction()
145142
public async Task HandleLoadEvents_ShouldFilterAndDispatchUpdateTable()
146143
{
147144
// Arrange
148-
var events = new List<DisplayEventModel>
149-
{
145+
var events = ImmutableArray.Create(
150146
EventUtils.CreateTestEvent(100, level: Constants.EventLevelError),
151147
EventUtils.CreateTestEvent(200, level: Constants.EventLevelInformation)
152-
};
148+
);
153149

154150
var logData = new EventLogData(Constants.LogNameTestLog, PathType.LogName, []);
155151
var (effects, mockDispatcher, _, _, mockFilterService) = CreateEffectsWithServices();

src/EventLogExpert.UI.Tests/Store/EventLog/EventLogStoreTests.cs

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -106,18 +106,14 @@ public void EventLogAction_LoadEvents_ShouldStoreLogDataAndEvents()
106106
// Arrange
107107
var logData = new EventLogData(Constants.LogNameTestLog, PathType.LogName, []);
108108

109-
var events = new List<DisplayEventModel>
110-
{
111-
EventUtils.CreateTestEvent(100),
112-
EventUtils.CreateTestEvent(200)
113-
};
109+
var events = ImmutableArray.Create(EventUtils.CreateTestEvent(100), EventUtils.CreateTestEvent(200));
114110

115111
// Act
116112
var action = new EventLogAction.LoadEvents(logData, events);
117113

118114
// Assert
119115
Assert.Equal(logData, action.LogData);
120-
Assert.Equal(2, action.Events.Count());
116+
Assert.Equal(2, action.Events.Length);
121117
}
122118

123119
[Fact]
@@ -352,12 +348,11 @@ public void LoadEventsAndSelect_ShouldWorkCorrectly()
352348

353349
var logData = state.ActiveLogs[Constants.LogNameTestLog];
354350

355-
var events = new List<DisplayEventModel>
356-
{
351+
var events = ImmutableArray.Create(
357352
EventUtils.CreateTestEvent(100),
358353
EventUtils.CreateTestEvent(200),
359354
EventUtils.CreateTestEvent(300)
360-
};
355+
);
361356

362357
// Act - Load events
363358
state = EventLogReducers.ReduceLoadEvents(state, new EventLogAction.LoadEvents(logData, events));
@@ -574,11 +569,7 @@ public void ReduceLoadEvents_ShouldUpdateLogWithEvents()
574569
ActiveLogs = ImmutableDictionary<string, EventLogData>.Empty.Add(Constants.LogNameTestLog, logData)
575570
};
576571

577-
var events = new List<DisplayEventModel>
578-
{
579-
EventUtils.CreateTestEvent(100),
580-
EventUtils.CreateTestEvent(200)
581-
};
572+
var events = ImmutableArray.Create(EventUtils.CreateTestEvent(100), EventUtils.CreateTestEvent(200));
582573

583574
var action = new EventLogAction.LoadEvents(logData, events);
584575

@@ -600,22 +591,19 @@ public void ReduceLoadEvents_ShouldIsolateStateFromOriginalList()
600591
ActiveLogs = ImmutableDictionary<string, EventLogData>.Empty.Add(Constants.LogNameTestLog, logData)
601592
};
602593

603-
var events = new List<DisplayEventModel>
604-
{
605-
EventUtils.CreateTestEvent(100),
606-
EventUtils.CreateTestEvent(200)
607-
};
594+
var events = ImmutableArray.Create(EventUtils.CreateTestEvent(100), EventUtils.CreateTestEvent(200));
608595

609596
var action = new EventLogAction.LoadEvents(logData, events);
610597

611598
// Act
612599
var newState = EventLogReducers.ReduceLoadEvents(state, action);
613600

614-
// Mutate the original list after state was created
615-
events.Add(EventUtils.CreateTestEvent(300));
601+
// ImmutableArray is inherently isolated — creating a new one doesn't affect the state
602+
var extendedEvents = events.Add(EventUtils.CreateTestEvent(300));
616603

617-
// Assert - state should not reflect the mutation
604+
// Assert - state should not reflect the extension
618605
Assert.Equal(2, newState.ActiveLogs[Constants.LogNameTestLog].Events.Count);
606+
Assert.Equal(3, extendedEvents.Length);
619607
}
620608

621609
[Fact]

src/EventLogExpert.UI/FilterMethods.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,7 @@ public static IReadOnlyList<DisplayEventModel> SortEvents(
7878

7979
internal static Comparison<DisplayEventModel> GetComparer(ColumnName? orderBy, bool isDescending)
8080
{
81-
// To reverse sort direction we swap operands (a,b) rather than negating the
82-
// comparison result, because Compare/CompareTo may return arbitrary negative
83-
// values (not just -1) and multiplying by -1 can overflow int.MinValue.
81+
// To reverse sort direction we swap operands (a,b)
8482
Comparison<DisplayEventModel> comparer = orderBy switch
8583
{
8684
ColumnName.Level => (a, b) => WithTieBreaker(string.Compare(a.Level, b.Level, StringComparison.Ordinal), a, b),
@@ -106,11 +104,10 @@ internal static Comparison<DisplayEventModel> GetComparer(ColumnName? orderBy, b
106104
return isDescending ? (a, b) => comparer(b, a) : comparer;
107105
}
108106

109-
/// <summary>Falls back to RecordId, then OwningLog and Id to guarantee a total order for List.Sort stability.</summary>
110107
private static int WithTieBreaker(int primaryResult, DisplayEventModel a, DisplayEventModel b) =>
111108
primaryResult != 0 ? primaryResult : FallbackTieBreaker(Nullable.Compare(a.RecordId, b.RecordId), a, b);
112109

113-
/// <summary>Ensures distinct events never compare as equal so List.Sort (unstable) produces deterministic results.</summary>
110+
/// <summary>Falls back to RecordId, then OwningLog (for combined logs) to guarantee a total order for List.Sort stability.</summary>
114111
private static int FallbackTieBreaker(int recordIdResult, DisplayEventModel a, DisplayEventModel b) =>
115112
recordIdResult != 0 ? recordIdResult : string.Compare(a.OwningLog, b.OwningLog, StringComparison.Ordinal);
116113

src/EventLogExpert.UI/Store/EventLog/EventLogAction.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public sealed record CloseAll;
2020

2121
public sealed record CloseLog(EventLogId LogId, string LogName);
2222

23-
public sealed record LoadEvents(EventLogData LogData, IReadOnlyList<DisplayEventModel> Events);
23+
public sealed record LoadEvents(EventLogData LogData, ImmutableArray<DisplayEventModel> Events);
2424

2525
public sealed record LoadNewEvents;
2626

src/EventLogExpert.UI/Store/EventLog/EventLogEffects.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ await Parallel.ForEachAsync(
200200
dispatcher.Dispatch(
201201
new EventLogAction.LoadEvents(
202202
logData,
203-
events.OrderByDescending(e => e.RecordId).ToList()));
203+
[.. events.OrderByDescending(e => e.RecordId)]));
204204

205205
dispatcher.Dispatch(new StatusBarAction.SetEventsLoading(activityId, 0, 0));
206206

src/EventLogExpert.UI/Store/EventLog/EventLogReducers.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public static EventLogState ReduceLoadEvents(EventLogState state, EventLogAction
5353
{
5454
ActiveLogs = newLogsCollection.Add(
5555
action.LogData.Name,
56-
action.LogData with { Events = action.Events.ToImmutableArray() })
56+
action.LogData with { Events = action.Events })
5757
};
5858
}
5959

0 commit comments

Comments
 (0)