Template Engine: add composed member addressing (path-qualified canonical names), override granularity per entity type, semantic validation (call targets, arg types), graph acyclicity enforcement, revision hashes for flattened configs. Deployment Manager: add deployment ID + idempotency, per-instance operation lock covering all mutating commands, state transition matrix, site-side apply atomicity (all-or-nothing), artifact version compatibility policy. Site Runtime: add script trust model (forbidden APIs, execution timeout, constrained compilation), concurrency/serialization rules (Instance Actor serializes mutations), site-wide stream backpressure (per-subscriber buffering, fire-and-forget publish). Communication: add application-level correlation IDs for protocol safety beyond Akka.NET transport guarantees. External System Gateway: add 408/429 as transient errors, CachedCall idempotency note, dedicated dispatcher for blocking I/O isolation. Health Monitoring: add monotonic sequence numbers to prevent stale report overwrites. Security: require LDAPS/StartTLS for LDAP connections. Central UI: add failover behavior (SignalR reconnect, JWT survives, shared Data Protection keys, load balancer readiness). Cluster Infrastructure: add down-if-alone=on for safe singleton ownership. Site Event Logging: clarify active-node-only logging (no replication), add 1GB storage cap with oldest-first purge. Host: add readiness gating (health check endpoint, no traffic until operational). Commons: add message contract versioning policy (additive-only evolution). Configuration Database: add optimistic concurrency on deployment status records.
152 lines
9.4 KiB
Markdown
152 lines
9.4 KiB
Markdown
# Component: Commons
|
|
|
|
## Purpose
|
|
|
|
The Commons component provides the shared foundation of data types, interfaces, enums, message contracts, data transfer objects, and persistence-ignorant domain entity classes used across all other ScadaLink components. It ensures consistent type definitions for cross-component communication, data access, and eliminates duplication of common abstractions.
|
|
|
|
## Location
|
|
|
|
Referenced by all component libraries and the Host.
|
|
|
|
## Responsibilities
|
|
|
|
- Define shared data types (enums, value objects, result types) used across multiple components.
|
|
- Define **persistence-ignorant domain entity classes** (POCOs) representing all configuration database entities. These classes have no dependency on Entity Framework or any persistence framework — EF mapping is handled entirely by the Configuration Database component via Fluent API.
|
|
- Define **per-component repository interfaces** that consuming components use for data access. Repository implementations are owned by the Configuration Database component.
|
|
- Define protocol abstraction interfaces for the Data Connection Layer.
|
|
- Define cross-component message contracts and DTOs for deployment, health, communication, instance lifecycle, and other inter-component data flows.
|
|
- Contain **no business logic** — only data structures, interfaces, and enums.
|
|
- Maintain **minimal dependencies** — only core .NET libraries; no Akka.NET, no ASP.NET, no Entity Framework.
|
|
|
|
---
|
|
|
|
## Requirements
|
|
|
|
### REQ-COM-1: Shared Data Type System
|
|
|
|
Commons must define shared primitive and utility types used across multiple components, including but not limited to:
|
|
|
|
- **`DataType` enum**: Enumerates the data types supported by the system (e.g., Boolean, Int32, Float, Double, String, DateTime, Binary).
|
|
- **`RetryPolicy`**: A record or immutable class describing retry behavior (max retries, fixed delay between retries).
|
|
- **`Result<T>`**: A discriminated result type that represents either a success value or an error, enabling consistent error handling across component boundaries without exceptions.
|
|
- **`InstanceState` enum**: Enabled, Disabled.
|
|
- **`DeploymentStatus` enum**: Pending, InProgress, Success, Failed.
|
|
- **`AlarmState` enum**: Active, Normal.
|
|
- **`AlarmTriggerType` enum**: ValueMatch, RangeViolation, RateOfChange.
|
|
- **`ConnectionHealth` enum**: Connected, Disconnected, Connecting, Error.
|
|
|
|
Types defined here must be immutable and thread-safe.
|
|
|
|
### REQ-COM-2: Protocol Abstraction
|
|
|
|
Commons must define the protocol abstraction interfaces that the Data Connection Layer implements and other components consume:
|
|
|
|
- **`IDataConnection`**: The common interface for reading, writing, and subscribing to device data regardless of the underlying protocol (OPC UA, custom legacy, etc.).
|
|
- **Related types**: Tag identifiers, read/write results, subscription callbacks, connection status enums, and quality codes.
|
|
|
|
These interfaces must not reference any specific protocol implementation.
|
|
|
|
### REQ-COM-3: Domain Entity Classes (POCOs)
|
|
|
|
Commons must define persistence-ignorant POCO entity classes for all configuration database entities. These classes:
|
|
|
|
- Are plain C# classes with properties — no EF attributes, no base classes from EF, no navigation property annotations.
|
|
- May include navigation properties (e.g., `Template.Attributes` as `ICollection<TemplateAttribute>`) defined as plain collections. The Configuration Database component configures the relationships via Fluent API.
|
|
- May include constructors that enforce invariants (e.g., required fields).
|
|
- Must have **no dependency** on Entity Framework Core or any persistence library.
|
|
|
|
Entity classes are organized by domain area:
|
|
|
|
- **Template & Modeling**: `Template`, `TemplateAttribute`, `TemplateAlarm`, `TemplateScript`, `TemplateComposition`, `Instance`, `InstanceAttributeOverride`, `InstanceConnectionBinding`, `Area`.
|
|
- **Shared Scripts**: `SharedScript`.
|
|
- **Sites & Data Connections**: `Site`, `DataConnection`, `SiteDataConnectionAssignment`.
|
|
- **External Systems & Database Connections**: `ExternalSystemDefinition`, `ExternalSystemMethod`, `DatabaseConnectionDefinition`.
|
|
- **Notifications**: `NotificationList`, `NotificationRecipient`, `SmtpConfiguration`.
|
|
- **Inbound API**: `ApiKey`, `ApiMethod`.
|
|
- **Security**: `LdapGroupMapping`, `SiteScopeRule`.
|
|
- **Deployment**: `DeploymentRecord`, `SystemArtifactDeploymentRecord`.
|
|
- **Audit**: `AuditLogEntry`.
|
|
|
|
### REQ-COM-4: Per-Component Repository Interfaces
|
|
|
|
Commons must define repository interfaces that consuming components use for data access. Each interface is tailored to the data needs of its consuming component:
|
|
|
|
- `ITemplateEngineRepository` — Templates, attributes, alarms, scripts, compositions, instances, overrides, connection bindings, areas.
|
|
- `IDeploymentManagerRepository` — Deployment records, deployed configuration snapshots, system-wide artifact deployment records.
|
|
- `ISecurityRepository` — LDAP group mappings, site scoping rules.
|
|
- `IInboundApiRepository` — API keys, API method definitions.
|
|
- `IExternalSystemRepository` — External system definitions, method definitions, database connection definitions.
|
|
- `INotificationRepository` — Notification lists, recipients, SMTP configuration.
|
|
- `ICentralUiRepository` — Read-oriented queries spanning multiple domain areas for display purposes.
|
|
|
|
All repository interfaces must:
|
|
- Accept and return the POCO entity classes defined in Commons.
|
|
- Include a `SaveChangesAsync()` method (or equivalent) to support unit-of-work commit.
|
|
- Have **no dependency** on Entity Framework Core — they are pure interfaces.
|
|
|
|
Implementations of these interfaces are owned by the Configuration Database component.
|
|
|
|
### REQ-COM-4a: Cross-Cutting Service Interfaces
|
|
|
|
Commons must define service interfaces for cross-cutting concerns that multiple components consume:
|
|
|
|
- **`IAuditService`**: Provides a single method for components to log audit entries: `LogAsync(user, action, entityType, entityId, entityName, afterState)`. The implementation (owned by the Audit Logging component) serializes the state as JSON and adds the audit entry to the current unit-of-work transaction. Defined in Commons so any central component can call it without depending on the Audit Logging component directly.
|
|
|
|
### REQ-COM-5: Cross-Component Message Contracts
|
|
|
|
Commons must define the shared DTOs and message contracts used for inter-component communication, including:
|
|
|
|
- **Deployment DTOs**: Configuration snapshots, deployment commands, deployment status, validation results.
|
|
- **Instance Lifecycle DTOs**: Disable, enable, delete commands and responses.
|
|
- **Health DTOs**: Health check results, site status reports, heartbeat messages. Includes script error rates and alarm evaluation error rates.
|
|
- **Communication DTOs**: Site identity, connection state, routing metadata.
|
|
- **Attribute Stream DTOs**: Attribute value change messages (instance name, attribute path, value, quality, timestamp) and alarm state change messages (instance name, alarm name, state, priority, timestamp) for the site-wide Akka stream.
|
|
- **Debug View DTOs**: Subscribe/unsubscribe requests, initial snapshot, stream filter criteria.
|
|
- **Script Execution DTOs**: Script call requests (with recursion depth), return values, error results.
|
|
- **System-Wide Artifact DTOs**: Shared script packages, external system definitions, database connection definitions, notification list definitions.
|
|
|
|
All message types must be `record` types or immutable classes suitable for use as Akka.NET messages (though Commons itself must not depend on Akka.NET).
|
|
|
|
### REQ-COM-5a: Message Contract Versioning
|
|
|
|
Since the system supports cross-site artifact version skew (sites may temporarily run different versions), message contracts must follow **additive-only evolution rules**:
|
|
|
|
- New fields may be added with default values. Existing fields must not be removed or have their types changed.
|
|
- Serialization must tolerate unknown fields (forward compatibility) and missing optional fields (backward compatibility).
|
|
- Breaking changes require a new message type and a coordinated deployment to all nodes.
|
|
- The Akka.NET serialization binding configuration (in the Host component) must explicitly map message types to serializers to prevent accidental binary serialization.
|
|
|
|
### REQ-COM-6: No Business Logic
|
|
|
|
Commons must contain only:
|
|
|
|
- Data structures (records, classes, structs)
|
|
- Interfaces
|
|
- Enums
|
|
- Constants
|
|
|
|
It must **not** contain any business logic, service implementations, actor definitions, or orchestration code. Any method bodies must be limited to trivial data-access logic (e.g., factory methods, validation of invariants in constructors).
|
|
|
|
### REQ-COM-7: Minimal Dependencies
|
|
|
|
Commons must depend only on core .NET libraries (`System.*`, `Microsoft.Extensions.Primitives` if needed). It must **not** reference:
|
|
|
|
- Akka.NET or any Akka.* packages
|
|
- ASP.NET Core or any Microsoft.AspNetCore.* packages
|
|
- Entity Framework Core or any Microsoft.EntityFrameworkCore.* packages
|
|
- Any third-party libraries requiring paid licenses
|
|
|
|
This ensures Commons can be referenced by all components without introducing transitive dependency conflicts.
|
|
|
|
---
|
|
|
|
## Dependencies
|
|
|
|
- **None** — only core .NET SDK.
|
|
|
|
## Interactions
|
|
|
|
- **All component libraries**: Reference Commons for shared types, interfaces, entity classes, and contracts.
|
|
- **Configuration Database**: Implements the repository interfaces defined in Commons. Maps the POCO entity classes to the database via EF Core Fluent API.
|
|
- **Host**: References Commons transitively through the component libraries.
|