Initial commit: EngineeringSync v1.0.0
Vollständige Implementierung des EngineeringSync-Middleware-Tools: - Windows Service (Kestrel :5050) mit FileSystemWatcher + SignalR - WPF Tray-App mit PendingChanges- und Projektverwaltungs-Fenster - Setup-Wizard (8-Schritte-Installer) - SQLite/EF Core Datenschicht (WAL-Modus) - SHA-256-basiertes Debouncing (2s Fenster) - Backup-System mit konfigurierbarer Aufbewahrung Bugfixes & Verbesserungen: - BUG-1: AppDbContext OnConfiguring invertierte Bedingung behoben - BUG-2: Event-Handler-Leak in TrayApp (Fenster-Singleton-Pattern) - BUG-3: ProjectConfigChanged SignalR-Signal in allen CRUD-Endpoints - BUG-5: Rename-Sync löscht alte Datei im Simulations-Ordner - BUG-6: Doppeltes Dispose von SignalR verhindert - BUG-7: Registry-Deinstallation nur EngineeringSync-Eintrag entfernt - S1: Path-Traversal-Schutz via SafeCombine() im SyncManager - E1: FSW Buffer 64KB + automatischer Re-Scan bei Overflow - E2: Retry-Logik (3x) für gesperrte Dateien mit exponentiellem Backoff - E4: Channel.Writer.TryComplete() beim Shutdown - C2: HubMethodNames-Konstanten statt Magic Strings - E3: Pagination in Changes-API (page/pageSize Query-Parameter) - A1: Fire-and-Forget mit try/catch + Logging Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
155
AGENTS.md
Normal file
155
AGENTS.md
Normal file
@@ -0,0 +1,155 @@
|
||||
# AGENTS.md
|
||||
|
||||
## Build, Test & Run Commands
|
||||
|
||||
```bash
|
||||
# Build entire solution
|
||||
dotnet build EngineeringSync.slnx
|
||||
|
||||
# Run the background service (dev mode)
|
||||
dotnet run --project EngineeringSync.Service
|
||||
|
||||
# Run the WPF tray app
|
||||
dotnet run --project EngineeringSync.TrayApp
|
||||
|
||||
# Run all tests
|
||||
dotnet test
|
||||
|
||||
# Run a single test project
|
||||
dotnet test EngineeringSync.Tests --filter "FullyQualifiedName~WatcherServiceTests"
|
||||
|
||||
# Run tests with verbose output
|
||||
dotnet test --verbosity normal
|
||||
|
||||
# Build Release
|
||||
dotnet build EngineeringSync.slnx -c Release
|
||||
|
||||
# Install as Windows Service (production)
|
||||
sc create EngineeringSync binPath="<path>\EngineeringSync.Service.exe"
|
||||
|
||||
# Build installer (requires Inno Setup 6)
|
||||
.\installer\build-installer.ps1
|
||||
```
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
### General Principles
|
||||
- Use C# 12+ features (file-scoped namespaces, collection expressions, primary constructors)
|
||||
- Use `[ObservableProperty]` and `[RelayCommand]` attributes from CommunityToolkit.Mvvm
|
||||
- Prefer source generators over boilerplate code
|
||||
|
||||
### Imports
|
||||
- Sort by: System namespaces first, then Microsoft, then third-party, then project-specific
|
||||
- Use file-scoped namespaces: `namespace EngineeringSync.Domain.Entities;`
|
||||
- Global using statements in each project for common types
|
||||
|
||||
### Types & Collections
|
||||
- Use collection expressions `[]` instead of `new List<T>()` where possible
|
||||
- Use `IReadOnlyList<T>` for parameters that should not be modified
|
||||
- Use `Guid` for all ID types
|
||||
- Use `DateTime.UtcNow` for timestamps, convert to local time in UI layer only
|
||||
|
||||
### Naming Conventions
|
||||
- **Classes/Interfaces:** PascalCase (e.g., `WatcherService`, `IApiClient`)
|
||||
- **Methods:** PascalCase (e.g., `StartWatchingAsync`)
|
||||
- **Private fields:** camelCase (e.g., `_watchers`, `_channel`)
|
||||
- **Properties:** PascalCase (e.g., `IsActive`, `EngineeringPath`)
|
||||
- **Parameters:** camelCase (e.g., `project`, `stoppingToken`)
|
||||
- **Constants:** PascalCase (e.g., `DefaultTimeout`)
|
||||
|
||||
### Records vs Classes
|
||||
- Use `record` for DTOs and API models
|
||||
- Use `class` for entities with mutable properties
|
||||
|
||||
### Error Handling
|
||||
- Use `try/catch` with specific exception types
|
||||
- Log exceptions with context using `ILogger` (use structured logging: `logger.LogError(ex, "Message {Param}", param)`)
|
||||
- In ViewModels, catch exceptions and set `StatusMessage` for user feedback
|
||||
|
||||
### Async/Await
|
||||
- Always use `Async` suffix for async methods
|
||||
- Pass `CancellationToken` to all cancellable operations
|
||||
- Use `await using` for `IDisposable` resources that implement `IAsyncDisposable`
|
||||
|
||||
### Entity Framework Core
|
||||
- Use `IDbContextFactory<AppDbContext>` for scoped DbContext in background services
|
||||
- Use `await using var db = await dbFactory.CreateDbContextAsync(ct);`
|
||||
- Configure SQLite with WAL mode for better concurrency
|
||||
|
||||
### WPF / MVVM
|
||||
- ViewModels inherit from `ObservableObject` (CommunityToolkit.Mvvm)
|
||||
- Use `[ObservableProperty]` for properties that need change notification
|
||||
- Use `[RelayCommand]` for commands
|
||||
- Use `partial class` for generated properties
|
||||
|
||||
### Dependency Injection
|
||||
- Constructor injection with primary constructors:
|
||||
```csharp
|
||||
public sealed class WatcherService(
|
||||
IDbContextFactory<AppDbContext> dbFactory,
|
||||
IHubContext<NotificationHub> hub,
|
||||
ILogger<WatcherService> logger) : BackgroundService
|
||||
```
|
||||
|
||||
### File Organization
|
||||
```
|
||||
EngineeringSync.Domain/ - Entities, Enums, Interfaces
|
||||
EngineeringSync.Infrastructure/ - EF Core, DbContext, Migrations
|
||||
EngineeringSync.Service/ - API, Hubs, Background Services
|
||||
EngineeringSync.TrayApp/ - WPF Views, ViewModels, Services
|
||||
EngineeringSync.Setup/ - Installer wizard
|
||||
```
|
||||
|
||||
### Key Patterns
|
||||
|
||||
**FileSystemWatcher Debouncing:** Events flow into a `Channel<FileEvent>`, consumer groups by `(ProjectId, RelativePath)` within 2000ms window, SHA-256 confirms actual changes.
|
||||
|
||||
**SignalR Notifications:** `NotificationHub` at `/notifications` broadcasts `ReceiveChangeNotification(projectId, projectName, count)` to all clients.
|
||||
|
||||
**Backup before sync:** Use timestamped naming `{filename}_{yyyyMMdd_HHmmss}.bak`.
|
||||
|
||||
### Service API Endpoints
|
||||
- `GET/POST/PUT/DELETE /api/projects` - Project CRUD
|
||||
- `GET /api/changes/{projectId}` - Get pending changes
|
||||
- `GET /api/changes/{projectId}/history` - Get synced/ignored changes
|
||||
- `POST /api/sync` - Sync selected changes
|
||||
- `POST /api/ignore` - Ignore selected changes
|
||||
|
||||
### Database
|
||||
- SQLite with WAL mode
|
||||
- Entities: `ProjectConfig`, `FileRevision`, `PendingChange`
|
||||
- `ProjectConfig.FileExtensions` is comma-separated (e.g., ".jt,.cojt,.xml")
|
||||
|
||||
## Solution Structure
|
||||
|
||||
```
|
||||
EngineeringSync.slnx
|
||||
├── EngineeringSync.Domain/ (Class Library, net10.0) - Entities, Enums, Interfaces
|
||||
├── EngineeringSync.Infrastructure/ (Class Library, net10.0) - EF Core, DbContext
|
||||
├── EngineeringSync.Service/ (Worker Service, net10.0) - Kestrel on :5050, SignalR hub
|
||||
├── EngineeringSync.TrayApp/ (WPF App, net10.0-windows) - System tray + UI windows
|
||||
├── EngineeringSync.Setup/ (WPF App, net10.0-windows) - Setup wizard + Installer
|
||||
└── installer/
|
||||
├── setup.iss - Inno Setup Script
|
||||
└── build-installer.ps1 - Build + Publish + ISCC Pipeline
|
||||
```
|
||||
|
||||
## Tech Stack
|
||||
|
||||
- **Framework:** .NET 10
|
||||
- **Service:** Worker Service (Windows Service) + ASP.NET Core Minimal API + SignalR
|
||||
- **Client:** WPF (.NET 10-Windows) with `H.NotifyIcon.Wpf` + `CommunityToolkit.Mvvm`
|
||||
- **Database:** SQLite via EF Core 10 (WAL mode)
|
||||
- **File Watching:** `System.IO.FileSystemWatcher` + `System.Threading.Channels` (debouncing)
|
||||
|
||||
## Key Architecture
|
||||
|
||||
- **ProjectConfig in DB:** Managed via TrayApp UI, stored in SQLite. User adds/edits/deletes projects with folder browser dialogs. CRUD operations go through Service API, which dynamically starts/stops watchers.
|
||||
- **FileSystemWatcher Debouncing:** Events (Created, Changed, Renamed, Deleted) pushed into `Channel<FileEvent>`. Consumer groups events by `(ProjectId, RelativePath)` within 2000ms sliding window. SHA-256 hashing against `FileRevision` confirms actual changes before writing a `PendingChange`.
|
||||
- **SignalR Hub:** `NotificationHub` at `/notifications` broadcasts `ReceiveChangeNotification(projectId, projectName, count)` and `ProjectConfigChanged()`.
|
||||
|
||||
## Notes
|
||||
- Domain project has no dependencies (pure entities/enums)
|
||||
- Infrastructure depends on Domain
|
||||
- Service depends on Domain + Infrastructure
|
||||
- TrayApp depends on Domain + Service (via HTTP client)
|
||||
Reference in New Issue
Block a user