Skip to content

Filter slice rework: extract Filtering library, slice UI by feature, migrate to command facades#527

Merged
jschick04 merged 95 commits into
mainfrom
jschick/filter-slicing-pr1
May 18, 2026
Merged

Filter slice rework: extract Filtering library, slice UI by feature, migrate to command facades#527
jschick04 merged 95 commits into
mainfrom
jschick/filter-slicing-pr1

Conversation

@jschick04
Copy link
Copy Markdown
Collaborator

@jschick04 jschick04 commented May 17, 2026

Summary

Foundational rework of the filter system across the EventLogExpert solution. Three primary outcomes:

  1. Filtering library extraction. New EventLogExpert.Filtering library replaces the embedded UI-coupled filter implementation with a hand-rolled parse/lower/emit pipeline (Dynamic.LINQ dropped from production). Domain types (Filter, BasicFilter, SavedFilter, FilterComparison, etc.) live in a clean-architecture inner ring with no UI / Fluxor / MAUI dependencies. Folder topology: Basic/, Common/, EventData/, Parsing/, Lowering/, Emit/, Runtime/, Persistence/, Drafts/, DependencyInjection/.

  2. UI slice migration to command facades. Per-slice Fluxor action dispatch reorganized behind host-facing command facades (IEventLogCommands, IFilterPaneCommands, IFilterGroupCommands, ILogTableCommands, IFilterCacheCommands). Internal actions / reducers / effects demoted to internal sealed, with a single RegisterUiLibrary() composition-root extension as the public DI entry point. InternalsVisibleTo from EventLogExpert.UI to the MAUI head dropped (only test assemblies retain IVT).

  3. Per-slice preference ports + service relocations. Six per-slice I*PreferencesProvider interfaces (replacing one monolithic IPreferencesProvider); 16 application/update services moved from MauiProgram.cs into RegisterUiLibrary() so the UI library owns its service registrations.

Scope (by area)

Filtering library (EventLogExpert.Filtering)

  • Hand-rolled FilterParser (Parsing/) + AST FilterCompiler (FilterCompiler.cs) + closure emitter (Emit/Emitter.cs) + AND-chain UserId peephole (Lowering/); Dynamic.LINQ removed from production paths.
  • BasicFilter decomposer + FilterComparison cascade (renamed from BasicFilterCondition). EventFilter renamed to Filter (runtime type) with the legacy name reserved for the persisted shape.
  • EventLogData POCO hoisted into EventLogExpert.Eventing (cross-asm consumer); EventPropertyValuesCache renamed from EventPropertyItemsCache.
  • AddEventLogFiltering() registrar (currently a no-op for future expansion; IFilterService stays in the UI layer due to its EventLogData/EventLogId cycle with the EventLog Fluxor slice).
  • Sub-folder reorganization puts top-level files into Basic//Common//EventData//Parsing//Runtime/ per VSA; BasicFilterDecomposer demoted to internal.

UI slice migration (EventLogExpert.UI)

  • Command facades: IEventLogCommands (open/close/reload), IFilterPaneCommands (apply/clear), IFilterGroupCommands (CRUD + import/export), ILogTableCommands (columns/highlights), IFilterCacheCommands (recent/favorite filters). Each slice''s actions demoted to internal sealed.
  • Service demotion: 14 UI service impls (DebugLogService, SettingsService, etc.) moved behind RegisterUiLibrary; DatabaseService + DebugLogService further demoted with IVT grant to EventLogExpert.UI.IntegrationTests for the integration tests that need them.
  • ILogReloadCoordinator registered as an interface over the Fluxor-managed Effects instance (the host bridge between DatabaseService and the EventLog slice without exposing Effects directly).
  • Per-slice preference ports: IEventLogPreferencesProvider, IFilterPanePreferencesProvider, IFilterGroupPreferencesProvider, ILogTablePreferencesProvider, IFilterCachePreferencesProvider, IDetailsPanePreferencesProvider. MAUI head''s PreferencesProvider implements all six.

Naming polish (slice-aware action / property names)

  • FilterCache.*CompletedAction -> *SuccessAction (matches the success-path terminology used elsewhere).
  • EventLog.SetFiltersAction -> ApplyFilterAction (matches intent: this is a user-initiated apply, not a generic set).
  • EventLog.AddEventBufferedAction -> EventBufferedAction (state-notification, not user intent).
  • EventPropertyItems -> EventPropertyValues (the cache stores values, not items).
  • FilterGroup actions disambiguated from FilterPane siblings: SetGroupFilterAction, RemoveGroupFilterAction, ToggleGroupFilterExcludedAction, etc. (the Group qualifier matters because both slices have parallel Set*Filter* actions).
  • FilterLoading slice renamed to FilterProgress (slice folder + namespace + state + action).

Concurrency hardening (EventLog HandleApplyFilter)

  • Split HandleApplyFilter into ReloadLogsWithXmlAsync (close-and-reopen-with-XML path) and ApplyFilterAndPublishAsync (filter-only path); both bump _filterGeneration so a newer dispatch supersedes the older.
  • _closeAllGeneration counter distinct from _filterGeneration: HandleCloseAll bumps _closeAllGeneration, and ReloadLogsWithXmlAsync checks ONLY that counter before its reopen loop -- a racing newer ApplyFilter (which only bumps _filterGeneration) must NOT cancel an in-flight reload.
  • _closeAllGeneration snapshot captured BEFORE reading ActiveLogs (avoids TOCTOU where a CloseAll between the read and capture would pin a stale snapshot to the new generation).
  • Per-iteration revalidation in the reopen loop; mid-loop supersession dispatches CloseLogAction for already-reopened logs as cleanup + clears _pendingSelectionRestore entries to prevent stale selection restore on a later manual reopen.
  • HandleCloseAll now takes the required IDispatcher parameter (Fluxor 6.9.0 mandates this signature for [EffectMethod(typeof(...))] -- a runtime registration error otherwise).
  • Stale comments + test method names referring to the old FilterLoading / SetFilters / FilterModelTests identifiers updated.

Review-cycle fixes (14 commits across 5 GitHub Copilot review rounds)

  • PascalCase locals matching the type name (var Filter = new Filter(...)) renamed to camelCase across EffectsTests.cs (10 sites) and FilterExtensionsTests.cs (6 sites).
  • Test method names aligned with renamed actions (16 sites across EffectsTests, FilterGroupStoreTests, EventLogStoreTests, FilterProgressStoreTests).
  • Unused using EventLogExpert.Filtering; directives removed from DebugLogProjection, IFilterService, FilterService; redundant self-namespace using removed from FilterParser.
  • 3 public actions demoted to internal (LoadGroupsSuccessAction, LoadColumnsCompletedAction, SetFilterProgressAction); FilterProgress.Reducers class also demoted to internal (CS0051 cascade from the action demotion).
  • 5 components had unused [Inject] private IDispatcher Dispatcher properties removed after facade migration (FilterGroupModal, FilterGroup, FilterRow, LogTabBar, LogTablePane).
  • DI smoke test (UiServiceCollectionExtensionsTests) extended from 6 to 23 InlineData entries covering all command facades, UI capabilities, application services, and update/deployment services moved into RegisterUiLibrary.
  • AddEventLogFiltering registrar gained ArgumentNullException.ThrowIfNull(services) + standalone XML doc summary (was referencing planning notation D6/D9).
  • FilterModelTests class in SavedFilterTests.cs renamed to SavedFilterTests to match file name.

Decision log (key calls made along the way)

Verification

  • dotnet build EventLogExpert.slnx: 0 warnings, 0 errors.
  • dotnet test EventLogExpert.slnx: 2,632 tests pass (2 skipped -- pre-existing platform-gated Eventing integration tests). Breakdown:
    • EventLogExpert.Eventing.Tests: 288
    • EventLogExpert.Eventing.IntegrationTests: 334 + 2 skipped
    • EventLogExpert.Filtering.Tests: 603
    • EventLogExpert.Components.Tests: 150
    • EventLogExpert.EventDbTool.Tests: 8
    • EventLogExpert.EventDbTool.IntegrationTests: 38
    • EventLogExpert.UI.Tests: 1087
    • EventLogExpert.UI.IntegrationTests: 124

Notes for reviewer

  • The 90-commit history is preserved end-to-end (no squash). Each commit is logically scoped, individually buildable, and individually testable; the review-cycle fix commits at the end are the smallest and most surgical.
  • Both EventLogExpert.UI -> EventLogExpert.UI.Tests and -> EventLogExpert.UI.IntegrationTests IVT grants remain (tests need internal access). The MAUI head''s IVT grant from EventLogExpert.UI was dropped.
  • Filtering library has its own Tests project with IVT grant; no cross-asm internals leakage to UI.
  • The HandleApplyFilter concurrency fix history (rounds 2-5) introduced two subtle bugs that subsequent rounds caught; the final state (commit 692f802) is the validated one with 3 new race-condition unit tests.

jschick04 and others added 30 commits May 14, 2026 15:27
Extract LogTablePane.BuildActiveHighlightFilters to a dedicated HighlightFilterSelector that takes the full FilterPaneState. The selector intentionally consults only Filters, leaving IsEnabled (the Ctrl+H 'Show All Events' toggle) untouched, so highlight cues survive when the visibility-filter pipeline is suspended.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jschick04 jschick04 changed the title Filter library extraction through FilterComparison cascade (PR-1 of 3) Filter slice rework: extract Filtering library, slice UI by feature, migrate to command facades May 17, 2026
Copilot AI review requested due to automatic review settings May 18, 2026 04:51
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

jschick04 added 2 commits May 18, 2026 10:40
…s, MergeSorted, MatchesFilters, MatchesDateFilter, and AddFilterGroup
@jschick04 jschick04 merged commit cd7a6f4 into main May 18, 2026
6 checks passed
@jschick04 jschick04 deleted the jschick/filter-slicing-pr1 branch May 18, 2026 15:45
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.

3 participants