Files
2026-06-26 10:29:23 +02:00

339 lines
15 KiB
Markdown

# adas-core.Application — Use Case Layer
> The **Application Layer** of the ADAS Core platform.
> Contains application services, use case orchestration, repository contracts, caching abstractions, and domain-specific exceptions. This layer defines **what** the system does, delegating **how** to the Infrastructure layer.
---
## Table of Contents
1. [Overview](#overview)
2. [Responsibilities](#responsibilities)
3. [Project Structure](#project-structure)
4. [Dependencies](#dependencies)
5. [Repository Contracts](#repository-contracts)
6. [Application Services](#application-services)
7. [Caching Abstractions](#caching-abstractions)
8. [Exceptions](#exceptions)
9. [Environment Customizations](#environment-customizations)
10. [Design Rules](#design-rules)
---
## Overview
`adas-core.Application` sits between the **Domain** and **Infrastructure** layers. It orchestrates domain entities into complete use cases, enforces application-level rules, and exposes repository contracts that Infrastructure implements.
Key characteristics:
- **Pure orchestration** — Services coordinate domain objects but contain no persistence logic.
- **Repository contracts** — Interfaces in `Repositories/Interfaces/` define data access contracts; concrete implementations live in `adas-core.Infrastructure`.
- **DTO-less where possible** — Services consume and return domain entities directly when serialization concerns are handled upstream.
- **Pluggable caching** — Abstracted behind `ICacheService` with Redis or in-memory fallbacks.
- **Environment-specific logic** — Calculated observations vary per deployment via the `Customizations` folder.
---
## Responsibilities
| Concern | What this project does |
|---------|----------------------|
| **Use Case Orchestration** | Application services execute high-level workflows (admit patient, record observation, trigger alert, etc.). |
| **Repository Contracts** | Defines `I*` repository interfaces that Infrastructure must satisfy. |
| **Caching Strategy** | Provides `ICacheService`, `ILockProvider`, and `LockManagerService` for distributed or in-memory caching. |
| **External Provider Facade** | `AdasProvider` / `BaseProvider` abstract external integrations so domain logic remains clean. |
| **Real-Time Subscriptions** | `SubscribersService` and grouped subscriber models manage WebSocket client subscriptions. |
| **Calculated Observations** | `CalculatedObservationsService` evaluates patient observations using rules customized per environment. |
| **Scheduled Jobs** | `SchedulerService` coordinates Quartz-based background tasks. |
| **Exception Taxonomy** | Domain-relevant exceptions (`NotFoundException`, `ConflictException`, etc.) for predictable error handling. |
---
## Project Structure
```
adas-core.Application/
├── Repositories/
│ └── Interfaces/ # Repository contracts (~40 interfaces)
│ ├── IMongoRepository.cs
│ ├── IUserRepository.cs
│ ├── IPatientRepository.cs
│ ├── IAdmissionRepository.cs
│ ├── IObservationRepository.cs
│ ├── ITreatmentRepository.cs
│ ├── IAlarmRepository.cs
│ ├── IDeviceRepository.cs
│ ├── ILightBeaconRepository.cs
│ ├── IRelayRepository.cs
│ ├── IPump*Repository.cs
│ ├── IRecordingAlertRepository.cs
│ ├── IConfig*Repository.cs
│ ├── IUnitRepository.cs
│ ├── IDisplay*Repository.cs
│ ├── IAppointmentRepository.cs
│ ├── IPatientCarePlanRepository.cs
│ ├── IMasterListRepository.cs
│ └── ...
├── Services/
│ ├── Interfaces/ # Service contracts (~40 interfaces)
│ │ ├── IAuthService.cs
│ │ ├── IPatientService.cs
│ │ ├── IObservationService.cs
│ │ ├── ICalculatedObservationsService.cs
│ │ ├── ITreatmentService.cs
│ │ ├── IDeviceService.cs
│ │ ├── IAlarmService.cs
│ │ ├── IDisplayService.cs
│ │ ├── IConfigObservationService.cs
│ │ ├── IUnitService.cs
│ │ ├── IAppointmentService.cs
│ │ ├── IPublisherService.cs
│ │ ├── ICacheService.cs
│ │ ├── ILockProvider.cs
│ │ └── ...
│ ├── AuthService.cs
│ ├── PatientService.cs
│ ├── AdmissionService.cs
│ ├── ObservationService.cs
│ ├── CalculatedObservationsService.cs
│ ├── DefaultCalculatedObservations.cs
│ ├── TreatmentService.cs
│ ├── AlarmService.cs
│ ├── DeviceService.cs
│ ├── CameraService.cs
│ ├── Config*Service.cs
│ ├── DisplayService.cs
│ ├── PointOfCareService.cs
│ ├── AppointmentService.cs
│ ├── PatientCarePlanService.cs
│ ├── Archive*Service.cs
│ ├── Recording*Service.cs
│ ├── MasterListService.cs
│ ├── MasterListServiceFactory.cs
│ ├── PermissionService.cs
│ ├── AdminPanelService.cs
│ ├── FileService.cs
│ ├── LocalAuditService.cs
│ ├── SubscribersService.cs
│ ├── SchedulerService.cs
│ └── Caching/
│ ├── CacheService.cs
│ ├── NoCacheService.cs
│ ├── RedisService.cs
│ ├── CacheDispatcher.cs
│ ├── LockManagerService.cs
│ ├── InMemoryLockProvider.cs
│ └── RedisLockProvider.cs
├── Exceptions/
│ ├── APIRequestException.cs
│ ├── BadRequestException.cs
│ ├── ConflictException.cs
│ ├── NotFoundException.cs
│ ├── UnauthorizedException.cs
│ ├── TokenException.cs
│ ├── UnprocessableEntityException.cs
│ └── ...
├── Customizations/ # Environment-specific calculated-observation rules
│ ├── BD/
│ ├── CHUO/
│ ├── H12O/UCIN/
│ ├── HGM/
│ ├── HPAZ/
│ ├── HRYC/
│ ├── HUVH/UCIN/
│ ├── HUVH/UCIA/
│ └── NursePlan/
│ └── CalculatedObservations.cs
├── Providers/
│ ├── BaseProvider.cs
│ └── AdasProvider.cs
└── Subscriptions/
├── SubscribersService.cs
├── WsSuscriber.cs
└── WsSubscriberGrouped.cs
```
---
## Dependencies
### Downstream References
| Project | Role |
|---------|------|
| `adas-core.Domain` | Domain entities, value objects, and business rules consumed by application services. |
### Upstream References (projects that depend on this)
| Project | Reason |
|---------|--------|
| `adas-core` (Host) | Registers application services and invokes them from controllers. |
| `adas-core.Infrastructure` | Implements all repository contracts defined in `Repositories/Interfaces/`. |
| `adas-core.Authentication` | Uses `IAuthService` and user-related service contracts. |
| `adas-core.module.LightBeacons` | Consumes shared application service interfaces. |
| `adas-core.module.ProxyDevices` | Consumes shared application service interfaces. |
| `adas-core.module.Relays` | Consumes shared application service interfaces. |
| `adas-core.Test` | Mocks application service interfaces in unit tests. |
### NuGet Packages
| Package | Version | Purpose |
|---------|---------|---------|
| `AutoMapper` | 16.1.1 | Entity ↔ projection mapping. |
| `MongoDB.Driver` | 3.9.0 | Repository interface type signatures. |
| `Quartz` | 3.18.1 | Scheduling primitives for background jobs. |
| `StackExchange.Redis` | 2.13.17 | Redis caching abstractions. |
| `Microsoft.Extensions.Caching.Memory` | 10.0.8 | In-memory caching fallback. |
| `Microsoft.Extensions.Http` | 10.0.8 | Typed HTTP clients for provider integrations. |
| `Microsoft.IdentityModel.JsonWebTokens` | 8.18.0 | JWT validation helpers for auth services. |
| `Microsoft.CodeAnalysis.CSharp.Scripting` | 5.3.0 | Dynamic expression evaluation for calculated observations. |
| `AuditLogs` | 1.0.59 | Audit trail tagging in use cases. |
---
## Repository Contracts
All repository interfaces reside in `Repositories/Interfaces/`. They are **contracts only** — no implementation. This enforces the Dependency Inversion Principle: Application defines the interface, Infrastructure provides the concrete MongoDB-backed classes.
### Generic Base Contract
```csharp
public interface IMongoRepository<T> where T : class
{
Task<T?> GetByIdAsync(ObjectId id);
Task<IEnumerable<T>> GetAllAsync();
Task<T> InsertAsync(T entity);
Task UpdateAsync(ObjectId id, T entity);
Task DeleteAsync(ObjectId id);
}
```
### Specialized Contracts
Derived interfaces extend `IMongoRepository<T>` or stand alone for aggregate-specific queries:
- `IPatientRepository` — CRUD + admission/discharge history lookups.
- `IObservationRepository` — Inserts with archive triggers, range queries.
- `IPumpStateRepository` — Scoped lifetime; tracks real-time pump telemetry.
- `IAlarmRepository` — Acknowledge, escalate, and history retrieval.
- `IDisplayConfigRepository` — Display layout and card/chart configuration.
> **Rule:** Every repository method name must describe intent, not mechanism (e.g., `GetActiveByUnitAsync` rather than `FindByQuery`).
---
## Application Services
Services in `Services/` encapsulate complete use cases. They are registered as **Singletons** in the DI container unless they hold per-request state.
### Service Categories
| Category | Examples |
|----------|----------|
| **Patient Management** | `PatientService`, `AdmissionService`, `DischargeService`, `PatientCarePlanService` |
| **Observations** | `ObservationService`, `ObservationDemoService`, `CalculatedObservationsService`, `GroupedObservationService` |
| **Clinical** | `TreatmentService`, `MedicineService`, `DiagnosisService` |
| **Devices** | `DeviceService`, `CameraService`, `PumpService` |
| **Alerts** | `AlarmService`, `AlertValuesService` |
| **Configuration** | `ConfigObservationService`, `ConfigPumpsService`, `ConfigUnitsService`, `ServiceConfigService` |
| **Displays** | `DisplayService`, `DisplayConfigService` |
| **System** | `AuthService`, `PermissionService`, `UnitService`, `MasterListService`, `AdminPanelService` |
| **Archival** | `ArchivePatientObservationsService`, `ArchivedPatientService`, `HistoricalConfigChangesService` |
| **Communication** | `SubscribersService`, `PublisherService`, `ClientMessageService` |
### Calculated Observations
`CalculatedObservationsService` evaluates derived metrics (e.g., early warning scores, trend indicators) using `ICalculatedObservations` strategy pattern. Per-environment overrides are loaded from the `Customizations/` folder based on `ASPNETCORE_ENVIRONMENT`.
Example environment mappings:
| Environment | Customization Path |
|-------------|--------------------|
| `H12O` | `Customizations/H12O/UCIN/CalculatedObservations.cs` |
| `HRYCM` | `Customizations/HRYC/CalculatedObservations.cs` |
| `HPAZ` | `Customizations/HPAZ/CalculatedObservations.cs` |
| `HUVH-UCIN` | `Customizations/HUVH/UCIN/CalculatedObservations.cs` |
| `HUVH-UCIA` | `Customizations/HUVH/UCIA/CalculatedObservations.cs` |
| `CHUO` | `Customizations/CHUO/CalculatedObservations.cs` |
| `NursePlan` | `Customizations/NursePlan/CalculatedObservations.cs` |
---
## Caching Abstractions
The caching stack abstracts Redis and in-memory behind common interfaces so services remain cache-agnostic.
| Component | Responsibility |
|-----------|-------------|
| `ICacheService` | Contract for get, set, remove, and sliding/absolute expiration. |
| `CacheService` | Composite dispatcher that routes to Redis or memory. |
| `RedisService` | Concrete Redis implementation using `StackExchange.Redis`. |
| `NoCacheService` | Null-object pattern for disabling cache in test environments. |
| `ILockProvider` | Distributed or in-memory lock acquisition. |
| `LockManagerService` | Orchestrates lock lifecycle (acquire, extend, release). |
| `RedisLockProvider` | Redis-backed distributed locking. |
| `InMemoryLockProvider` | Lightweight semaphore-based locking for single-instance deployments. |
---
## Exceptions
The `Exceptions/` folder defines a predictable error taxonomy used by controllers to map to HTTP status codes.
| Exception | Mapped HTTP Status | Usage |
|-----------|-------------------|-------|
| `BadRequestException` | `400 Bad Request` | Malformed input, validation failure. |
| `UnauthorizedException` | `401 Unauthorized` | Missing or invalid credentials. |
| `ForbbidenException` | `403 Forbidden` | Authenticated but insufficient permissions. |
| `NotFoundException` | `404 Not Found` | Resource does not exist. |
| `ConflictException` | `409 Conflict` | Concurrent modification or duplicate key. |
| `UnprocessableEntityException` | `422 Unprocessable Entity` | Semantic validation failure. |
| `InvalidFormatException` | `400 Bad Request` | Payload format mismatch. |
| `CustomArgumentException` | `400 Bad Request` | Invalid argument supplied. |
| `APIRequestException` | `502 Bad Gateway` | External provider call failure. |
| `TokenException` | `401 Unauthorized` | JWT parsing or validation error. |
---
## Environment Customizations
`Customizations/` contains per-client overrides for `CalculatedObservations`. These are compiled into the assembly conditionally or selected at runtime based on environment.
This avoids branching domain logic and keeps environment-specific rules isolated:
```
Customizations/
├── BD/
├── CHUO/
├── H12O/UCIN/
├── HGM/
├── HPAZ/
├── HRYC/
├── HUVH/UCIN/
├── HUVH/UCIA/
└── NursePlan/
```
> **Rule:** Customizations may only override `ICalculatedObservations`; they must not introduce new repository calls or bypass service contracts.
---
## Design Rules
1. **No Persistence Logic** — Application services never call MongoDB, Redis, or HTTP clients directly. They use injected repository interfaces and provider abstractions.
2. **Dependency Direction** — This project references **only** `adas-core.Domain`. No references to Infrastructure, Authentication, or Modules.
3. **Contracts First** — All repositories and external providers must expose an interface in this project before Infrastructure implements them.
4. **Single Responsibility Per Service** — One service per bounded-context use case; avoid god services.
5. **Environment Agnosticism** — Core services must compile and run without environment-specific customizations. Overrides are opt-in.
6. **Exception-Driven Flow Control** — Use typed exceptions for expected error paths; never throw raw `Exception` or `ApplicationException`.
7. **Thread Safety** — Singleton services must be stateless or use immutable state. Per-request state lives in scoped repositories.
8. **Cache Invalidation Ownership** — The service that writes data is responsible for invalidating related cache keys.
9. **Lazy Evaluation** — Heavy graph traversals use deferred execution until the repository materializes results.
10. **Audit Trail Awareness** — Sensitive mutations (patient admission, alarm acknowledge, config changes) must tag audit metadata before returning.
---
<p align="center">
Back to <a href="../README.md">adas-core Root README</a>
</p>