Files
Beyhan Oğur d5f52cc3d3 first commit
2026-09-03 04:45:36 +03:00

15 KiB
Raw Permalink Blame History

Engine Lifecycle Management

**Referenced Files in This Document** - [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs) - [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs) - [Program.cs](file://ClassicAssist.Avalonia/Program.cs) - [Engine.cs](file://ClassicAssist.Shared/Engine.cs) - [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs) - [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs) - [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs) - [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)

Table of Contents

  1. Introduction
  2. Project Structure
  3. Core Components
  4. Architecture Overview
  5. Detailed Component Analysis
  6. Dependency Analysis
  7. Performance Considerations
  8. Troubleshooting Guide
  9. Conclusion

Introduction

This document explains the lifecycle management of the Engine class in ClassicAssist.Avalonia, focusing on its role as the central orchestrator for application startup, subsystem initialization, and graceful shutdown. It also documents the event-driven communication model that coordinates network handlers, macro system, agents, and UI updates; the plugin loading mechanism used to discover and initialize extensions; and the thread management strategy for asynchronous operations and cross-thread UI updates. Finally, it provides examples of custom engine extension points and demonstrates how to integrate new features into the engine lifecycle.

Project Structure

The Avalonia-based entry point initializes the UI framework and then starts the Engine, which is responsible for bootstrapping core services, loading plugins, and managing runtime events. The shared Engine implementation defines the common lifecycle hooks and abstractions for dispatching work across threads and UI invocations.

graph TB
Program["Program.cs<br/>Entry point"] --> App["App.axaml.cs<br/>Application bootstrap"]
App --> EngineAvalonia["Engine.cs (Avalonia)<br/>Orchestrates startup/shutdown"]
EngineAvalonia --> EngineShared["Engine.cs (Shared)<br/>Lifecycle hooks & contracts"]
EngineAvalonia --> Dispatcher["AvaloniaDispatcher.cs<br/>IDispatcher impl"]
EngineAvalonia --> UIInvoker["AvaloniaUIInvoker.cs<br/>IUIInvoker impl"]

Diagram sources

Section sources

Core Components

  • Engine (Avalonia): Orchestrates application startup, initializes subsystems, loads plugins, and manages shutdown.
  • Engine (Shared): Defines lifecycle hooks and contracts for platform-specific implementations.
  • IDispatcher: Abstraction for scheduling work on a specific thread or context.
  • IUIInvoker: Abstraction for invoking UI updates safely from background threads.
  • AvaloniaDispatcher: Concrete dispatcher backed by Avalonia’s threading model.
  • AvaloniaUIInvoker: Concrete UI invoker that marshals calls onto the UI thread.

Key responsibilities:

  • Startup sequence: create services, configure logging, load configuration, initialize networking, macros, agents, and UI components.
  • Event-driven coordination: publish and subscribe to engine events to decouple subsystems.
  • Plugin discovery and initialization: scan assemblies, instantiate extensions, and register them with the engine.
  • Thread management: ensure background tasks run off the UI thread and UI updates are dispatched back to the UI thread.
  • Graceful shutdown: stop network loops, cancel timers, flush logs, release resources, and close UI windows.

Section sources

Architecture Overview

The Engine acts as the central coordinator. It uses an event bus to communicate between components such as network handlers, macro system, agents, and UI. Subsystems register event handlers during initialization and react to engine events like Start, Stop, Connected, Disconnected, MacroExecuted, AgentStateChanged, etc.

sequenceDiagram
participant Main as "Program"
participant App as "App"
participant Eng as "Engine (Avalonia)"
participant Net as "Network Handler"
participant Mac as "Macro System"
participant Ag as "Agents"
participant UI as "UI Layer"
Main->>App : Initialize UI framework
App->>Eng : Create and start Engine
Eng->>Eng : Load configuration
Eng->>Eng : Discover and load plugins
Eng->>Net : Initialize network stack
Eng->>Mac : Initialize macro engine
Eng->>Ag : Initialize agent managers
Eng->>UI : Initialize UI components
Eng-->>Net : Event : Started
Eng-->>Mac : Event : Started
Eng-->>Ag : Event : Started
Eng-->>UI : Event : Started
Net-->>Eng : Event : Connected
Eng-->>UI : Dispatch UI update via IUIInvoker
Mac-->>Eng : Event : MacroExecuted
Eng-->>Ag : Publish event to agents
Ag-->>Eng : Event : StateChanged
Eng-->>UI : Update UI state
Eng->>Eng : Shutdown requested
Eng-->>Net : Event : Stopping
Eng-->>Mac : Event : Stopping
Eng-->>Ag : Event : Stopping
Eng-->>UI : Close windows and release resources
Eng-->>Main : Exit

Diagram sources

Detailed Component Analysis

Engine Lifecycle Orchestration

The Engine lifecycle follows a clear sequence:

  • Pre-start: parse arguments, set up logging, load profiles/configuration.
  • Start: initialize subsystems (network, macros, agents), load plugins, start event loop.
  • Running: handle events from subsystems, coordinate cross-thread UI updates, manage timers and queues.
  • Shutdown: signal stopping to all subsystems, wait for completion, release resources, exit cleanly.
flowchart TD
Start(["Engine.Start"]) --> PreStart["Pre-start: config, logging, profile"]
PreStart --> InitSubsystems["Initialize subsystems<br/>Network, Macros, Agents"]
InitSubsystems --> LoadPlugins["Discover and load plugins"]
LoadPlugins --> StartEvents["Start event loop and listeners"]
StartEvents --> Running["Running: process events"]
Running --> ShutdownRequested{"Shutdown requested?"}
ShutdownRequested --> |No| Running
ShutdownRequested --> |Yes| SignalStop["Signal Stop to subsystems"]
SignalStop --> Cleanup["Cleanup resources and UI"]
Cleanup --> End(["Engine.Stop complete"])

Diagram sources

Section sources

Event-Driven Communication Model

The Engine exposes events that subsystems can subscribe to. Typical events include:

  • Application-level: Started, Stopping, Stopped
  • Network-level: Connected, Disconnected, PacketReceived
  • Macro-level: MacroExecuted, MacroError
  • Agent-level: AgentStateChanged, AgentActionPerformed
  • UI-level: UpdateRequested, WindowClosed

Subsystems publish events through the Engine’s event bus. For example, when the network handler connects, it raises a Connected event; the Engine publishes this to subscribers, including UI components that update status indicators.

classDiagram
class Engine {
+Event Started
+Event Stopping
+Event Stopped
+Event Connected
+Event Disconnected
+Event MacroExecuted
+Event AgentStateChanged
+Publish(event, data)
+Subscribe(event, handler)
}
class NetworkHandler {
+Connect()
+Disconnect()
+OnConnected()
+OnDisconnected()
}
class MacroSystem {
+Execute(macro)
+OnError(error)
}
class Agents {
+HandleStateChange(state)
}
class UIUpdater {
+UpdateStatus(status)
+RefreshViews()
}
Engine <.. NetworkHandler : "publishes Connected/Disconnected"
Engine <.. MacroSystem : "publishes MacroExecuted/MacroError"
Engine <.. Agents : "publishes AgentStateChanged"
Engine <.. UIUpdater : "publishes UI updates"

Diagram sources

Section sources

Plugin Loading Mechanism

Plugin discovery and initialization follow these steps:

  • Scan configured directories for assemblies.
  • Identify types implementing known extension interfaces or attributes.
  • Instantiate plugin instances and call their Initialize method.
  • Register plugin-provided commands, filters, agents, or UI tabs with the Engine.
flowchart TD
Scan["Scan assembly directories"] --> Identify["Identify plugin types"]
Identify --> Instantiate["Instantiate plugin instances"]
Instantiate --> Initialize["Call Initialize(pluginContext)"]
Initialize --> Register["Register commands/filters/agents/UI"]
Register --> Ready["Plugins ready"]

Diagram sources

Section sources

Thread Management Strategy

Cross-thread concerns are handled via:

  • IDispatcher: schedules work on a target thread or context.
  • IUIInvoker: marshals UI updates onto the UI thread.
  • Background workers: network processing, macro execution, and agent logic run off the UI thread.
sequenceDiagram
participant BG as "Background Task"
participant Eng as "Engine"
participant Disp as "IDispatcher"
participant UIInv as "IUIInvoker"
participant UI as "UI Thread"
BG->>Eng : Request UI update
Eng->>UIInv : Invoke(updateCallback)
UIInv->>Disp : ScheduleOnUIThread(callback)
Disp-->>UI : Execute callback on UI thread
UI-->>UIInv : Completed
UIInv-->>Eng : Acknowledge
Eng-->>BG : Continue processing

Diagram sources

Section sources

Custom Engine Extension Points

To integrate new features into the engine lifecycle:

  • Implement a plugin type recognized by the loader.
  • Provide an Initialize(context) method to register your feature.
  • Subscribe to relevant Engine events to react to lifecycle changes.
  • Use IUIInvoker for any UI updates from background threads.
  • Ensure your feature cleans up resources in response to Stopping events.

Example integration steps:

  • Add your assembly to the plugin directory.
  • Define a class implementing the expected interface or attribute.
  • In Initialize, register commands, filters, agents, or UI tabs.
  • Subscribe to Engine events for Connected/Disconnected, MacroExecuted, AgentStateChanged.
  • On Stopping, cancel timers, dispose resources, and detach event handlers.

Section sources

Dependency Analysis

The Engine depends on shared contracts and platform-specific implementations:

  • Shared contracts: IDispatcher, IUIInvoker, Engine base behavior.
  • Platform implementations: AvaloniaDispatcher, AvaloniaUIInvoker.
  • Subsystems: Network, Macros, Agents, UI.
graph TB
EngineAvalonia["Engine.cs (Avalonia)"] --> EngineShared["Engine.cs (Shared)"]
EngineAvalonia --> IDisp["IDispatcher.cs"]
EngineAvalonia --> IUI["IUIInvoker.cs"]
EngineAvalonia --> AvalDisp["AvaloniaDispatcher.cs"]
EngineAvalonia --> AvalUI["AvaloniaUIInvoker.cs"]
EngineAvalonia --> Subsystems["Network, Macros, Agents, UI"]

Diagram sources

Section sources

Performance Considerations

  • Avoid heavy work on the UI thread; always use IUIInvoker for UI updates.
  • Batch UI updates where possible to reduce redraw overhead.
  • Use efficient event subscriptions; unsubscribe during shutdown to prevent leaks.
  • Prefer asynchronous operations for network and file I/O.
  • Limit plugin scanning frequency; cache discovered plugins when appropriate.

[No sources needed since this section provides general guidance]

Troubleshooting Guide

Common issues and resolutions:

  • UI not updating: ensure updates are invoked via IUIInvoker and scheduled on the UI thread using IDispatcher.
  • Plugins not loading: verify plugin assemblies are in the correct directory and implement the expected interfaces/attributes.
  • Events not firing: confirm subscriptions occur after Engine.Start and unsubscriptions occur before Engine.Stop.
  • Resource leaks: check that background tasks are cancelled and resources disposed during Stopping.

Section sources

Conclusion

The Engine in ClassicAssist.Avalonia serves as the central orchestrator for application lifecycle, coordinating subsystem initialization, event-driven communication, plugin loading, and graceful shutdown. By adhering to the provided extension points and thread management strategies, developers can integrate new features seamlessly while maintaining responsiveness and stability.

[No sources needed since this section summarizes without analyzing specific files]