Unified Reaction Automation Design
Date: 2026-05-10
Status: Approved (conversation-level), pending file review gate
1. Goal
Thiết kế lại automation theo hướng reaction engine thống nhất:
- telemetry từ thiết bị là trigger đầu vào
- hệ thống đánh giá điều kiện trên một hoặc nhiều nguồn telemetry
- khi điều kiện khớp, hệ thống thực hiện một hoặc nhiều reaction
alertchỉ là một loại action trong automation, không còn là subsystem cấu hình riêng
Mục tiêu sản phẩm:
- user cấu hình rule trên màn
Automation - một rule có thể đọc telemetry từ nhiều device khác nhau
- một rule có thể tạo alert, bật/tắt nhiều thiết bị, hoặc kết hợp cả hai
- rule chỉ trigger khi state chuyển pha, không spam action ở mọi gói telemetry
- rule có thể chạy recovery actions khi điều kiện quay về bình thường
2. Scope
In scope
- thay mô hình
automation rulehiện tại từ1 condition + 1 actionsangn conditions + n actions - hỗ trợ
ANDhoặcORở cấp rule - hỗ trợ source telemetry từ nhiều device khác nhau trong cùng organization
- hỗ trợ
trigger actionsvàrecovery actions - thêm action type
alert - đánh giá rule dựa trên
latest endpoint snapshotcòn hiệu lực - thêm runtime state để hỗ trợ edge-triggering và cooldown
- xây màn authoring/list/detail/execution history cho automation rules
- loại
alert-configkhỏi feature scope mới
Out of scope
- expression logic có ngoặc như
(A and B) or C - scheduler/time-based automation
- cross-organization automation
- priority engine hoặc conflict resolution nâng cao giữa nhiều rules
- migration dữ liệu từ
alert-config - action types ngoài
alertvàdevice_command
3. Current State
Repo hiện có 3 mảnh tách rời:
telemetryđã lưu telemetry và đang tự check threshold để tạo alertautomationđã có endpoint-based rule engine nhưng mới hỗ trợ1 condition + 1 actionalert-configđang giữ cấu hình threshold ở scopeorganization,pond,device
Điểm không còn phù hợp với hướng sản phẩm mới:
alertđang là một flow riêng thay vì một reaction type- runtime evaluation hiện gắn với event của một source endpoint, chưa hỗ trợ multi-device snapshot evaluation
- rule model hiện còn gắn
farmId, trong khi yêu cầu mới chỉ cần cùngorganization - UI automation hiện mới là khung cơ bản, chưa phải màn authoring thực thụ
4. Decisions Already Locked In
Các quyết định đã được chốt trong buổi brainstorming:
Alertkhông còn là subsystem cấu hình riêng; nó là một action type trong automationalert-configbị loại khỏi feature scope mới- User cấu hình feature ở một màn
Automationmới, không gộp vàoAlertConfig - Rule là
edge-triggered: chỉ chạy khi state chuyển từnormal -> triggered - Rule có
recovery actionskhi state chuyển từtriggered -> normal - Bản đầu chỉ làm scope cấu hình theo
device-level telemetry sources, không làm inheritanceorganization/pond/device - Một rule hỗ trợ
n actions, và action list có thể trộnalertvớidevice command - Một rule hỗ trợ nhiều conditions với
ANDhoặcOR - Conditions có thể lấy từ nhiều devices khác nhau
- Multi-device evaluation dùng
latest snapshotmiễn còn trongfreshness window freshness windowlà hằng số toàn hệ thống, không cho user chỉnh- Mọi source/target devices trong rule phải cùng
organization - Rule có
cooldownmặc định do hệ thống set, user có thể sửa - Nếu nhiều rules cùng điều khiển một target endpoint, lệnh chạy sau thắng
5. Options Considered
Option A: Mở rộng automation hiện tại thành reaction engine thống nhất
Giữ module automation làm trung tâm, nhưng reshape data model, DTO, engine, và UI để support:
- multi-condition
- multi-action
- trigger/recovery phases
- alert action
- runtime state
Pros
- khớp trực tiếp với mental model sản phẩm
- tận dụng được endpoint model, dispatch path, và execution audit hiện có
- giảm số subsystem runtime song song
Cons
- cần đổi shape entity/API đáng kể
- cần bỏ tư duy
farm-scoped single-event ruleđang có
Option B: Tạo module reaction mới đứng cạnh automation
Giữ automation cũ cho device command, thêm module khác để orchestration alert và multi-source evaluation.
Pros
- ít đụng entity cũ hơn trong ngắn hạn
Cons
- tạo hai engine chồng chéo
- UI/user model là một hệ thống nhưng backend lại là hai hệ thống
- khó maintain về lâu dài
Option C: Giữ rule model cũ, thêm lớp composite service bên ngoài
Chỉ vá xung quanh engine hiện tại để mô phỏng multi-condition/multi-action.
Pros
- sửa ít code nhất lúc đầu
Cons
- runtime behavior sẽ nhanh chóng rối
- khó audit, khó test, khó mở rộng
- không giải quyết tận gốc state machine và snapshot evaluation
6. Selected Design
Chọn Option A: biến automation thành reaction engine thống nhất của toàn hệ thống.
Nguyên tắc cốt lõi:
- telemetry ingestion chỉ ingest và phát tín hiệu reevaluate
- automation là nơi duy nhất quyết định hệ thống sẽ “phản ứng” thế nào
alertlà action type chứ không phải config subsystem riêng- rule scope là
organization, không cònfarm - evaluation dựa trên
latest endpoint snapshotcộng với runtime state bền vững
7. Domain Architecture
7.1. Rule Scope
Rule thuộc về một organization.
Rule không bị ràng bởi farmId hay pondId. Một rule có thể:
- lấy source A ở khu vực này
- lấy source B ở khu vực khác
- điều khiển target C ở khu vực khác nữa
Miễn là tất cả entities cùng organization và user có quyền author rule.
Điều này thay thế assumption cũ trong automation hiện tại là mọi source/target phải cùng farm.
7.2. Conditions
Mỗi rule có:
conditionOperator:AND | ORconditions[]
Mỗi condition gồm:
sourceDeviceEndpointIdoperator:<,<=,>,>=,=,!=thresholdValuesequenceOrder
Condition luôn đánh giá trên latest value của endpoint nguồn, không đọc trực tiếp từ raw telemetry field nữa. Mapping từ raw telemetry sang endpoint value tiếp tục đi qua endpoint normalizer hiện có.
7.3. Actions
Mỗi rule có hai nhóm action:
triggerActions[]recoveryActions[]
Action bản đầu hỗ trợ hai loại:
alertdevice_command
Mỗi action có:
typephase:trigger | recoverysequenceOrderisEnabledpayload
Payload theo type:
alertseverity:info | warning | criticaltitleTemplatemessageTemplate
device_commandtargetDeviceEndpointIdtargetValue
Thiết kế payload-based này cho phép sau này thêm webhook, ticket, notification-only mà không phải đổi shape rule tổng thể.
7.4. Runtime State
Mỗi rule cần một runtime state bền vững:
currentState:normal | triggeredlastEvaluatedAtlastStateChangedAtlastTriggerExecutionAtlastRecoveryExecutionAtlastEvaluationSummary
lastEvaluationSummary là JSON snapshot gọn phục vụ audit/debug:
- condition results theo từng source
- aggregate result
- freshness failures nếu có
7.5. Latest Snapshot Model
Để evaluate multi-device rules, hệ thống cần latest value theo endpoint.
Thiết kế thêm automation_endpoint_latest_values với key theo deviceInstanceEndpointId.
Mỗi row gồm:
deviceInstanceEndpointIdorganizationIdvalueobservedAtsourceTelemetryIdupdatedAt
Redis cache có thể được thêm sau để tăng tốc, nhưng DB row này là source of truth của phase đầu.
8. Data Model Changes
8.1. automation_rules
Reshape bảng hiện tại:
- giữ:
idorganizationIdnamedescriptionstatuscooldownSecondscreatedByupdatedBycreatedAtupdatedAt
- bỏ:
farmIdtriggerMode
- thêm:
conditionOperator
Mặc định:
status = draftcooldownSeconds = 300
300s là default hệ thống cho phase đầu. User có thể override theo rule.
8.2. automation_rule_conditions
Giữ bảng riêng, nhưng semantics đổi thành many conditions per rule.
Fields:
idruleIdsourceDeviceEndpointIdoperatorthresholdValuesequenceOrder
Không cần thêm phase ở condition vì trigger/recovery được quyết định bằng state transition của toàn rule, không phải bởi condition set riêng.
8.3. automation_rule_actions
Bảng hiện tại phải được reshape từ single target action sang polymorphic action row.
Fields:
idruleIdphase:trigger | recoveryactionType:alert | device_commandsequenceOrderisEnabledpayloadjsonb
Không giữ targetDeviceEndpointId và targetValue ở top-level cột chung nữa, vì alert không có các field đó. Chúng được chuyển vào payload của device_command.
8.4. automation_rule_runtime_states
Thêm bảng mới:
idruleIdcurrentStatelastEvaluatedAtlastStateChangedAtlastTriggerExecutionAtlastRecoveryExecutionAtlastEvaluationSummarycreatedAtupdatedAt
Mỗi rule có tối đa một row state.
8.5. automation_endpoint_latest_values
Thêm bảng mới:
iddeviceInstanceEndpointIdorganizationIdvalueobservedAtsourceTelemetryIdcreatedAtupdatedAt
Mục đích:
- lấy snapshot cho multi-device evaluation
- kiểm tra freshness
- tạo audit trail tối thiểu cho evaluation input
8.6. automation_rule_executions
Bảng execution hiện có được giữ lại nhưng mở rộng semantics thành phase execution envelope.
Một execution record cần lưu:
ruleIdphasetriggeredAtstatus:succeeded | partial_failed | failed | skippedevaluationSnapshotactionResultsfailureReason
Không cần tạo command ledger mới trong spec này; phase đầu chỉ cần execution envelope đủ để audit reaction behavior. Nếu reliability core được mở rộng tiếp, command ledger có thể được thêm như phase riêng.
9. Runtime Flow
9.1. Telemetry Ingestion
TelemetryService tiếp tục:
- validate source device
- persist telemetry
- normalize raw payload thành endpoint events
- update
automation_endpoint_latest_values - yêu cầu automation reevaluate các rules liên quan
TelemetryService không còn tự check threshold để tạo alert nữa.
9.2. Rule Re-evaluation Trigger
Mỗi endpoint event mới là một tín hiệu để reevaluate các active rules có tham chiếu tới endpoint đó trong conditions.
Flow:
- tìm rules active có ít nhất một condition trỏ tới endpoint mới cập nhật
- load toàn bộ conditions của từng rule
- lấy latest snapshot của mọi source endpoints cần thiết
- nếu có source quá cũ so với
freshness window, mark condition đó làstale
9.3. Freshness Policy
freshness window là hằng số toàn hệ thống:
300 seconds
Condition chỉ được evaluate khi latest snapshot của source còn trong cửa sổ này.
Hành vi:
- với
AND: nếu một condition stale, aggregate result làfalse - với
OR: stale condition không tự tạotrue; rule chỉtruenếu có ít nhất một condition evaluatetruetừ dữ liệu fresh
Mọi stale reason phải được ghi vào lastEvaluationSummary.
9.4. State Transition
Aggregate evaluation của rule cho ra một boolean isTriggered.
State machine:
normal + false => stay normalnormal + true => transition to triggered, chạytriggerActionstriggered + true => stay triggeredtriggered + false => transition to normal, chạyrecoveryActions
Đây là cơ chế edge-triggered mà user đã chốt.
9.5. Cooldown
Cooldown mặc định:
300 seconds
Cooldown chỉ áp dụng cho phase tương ứng:
- chặn
triggerActionsnếu vừa trigger quá gần - chặn
recoveryActionsnếu vừa recovery quá gần
Cooldown không thay state transition logic. Nó chỉ chặn re-execution của cùng phase trong khoảng thời gian ngắn bất thường.
9.6. Action Execution
Actions trong mỗi phase chạy tuần tự theo sequenceOrder.
Quy tắc:
- nếu một action fail, engine vẫn chạy action sau
- action result được ghi riêng cho từng action
- execution tổng thể có thể là:
succeededpartial_failedfailedskipped
9.7. Conflict Behavior
Nếu nhiều rules gửi command tới cùng target endpoint:
- runtime không chặn
- không làm priority engine
- command chạy sau thắng
Audit phải phản ánh rõ command nào được gửi ở thời điểm nào để hỗ trợ debug sau này.
10. Alert And Device Command Behavior
10.1. Alert Action
alert action tái sử dụng luồng tạo alert/notification hiện có của devices module.
Nó phải tạo ra cùng loại user-visible artifact mà hệ thống đang dùng cho alert hiện nay:
- severity
- title
- message
- data context
Payload template có thể render các biến:
{{ruleName}}{{phase}}{{source.<endpointId>.value}}{{source.<endpointId>.observedAt}}
Bản đầu không cần template engine quá phức tạp; string interpolation đủ dùng.
10.2. Device Command Action
device_command action tiếp tục dùng dispatch path hiện có của device endpoint control.
Trước khi dispatch, engine phải kiểm tra:
- target endpoint tồn tại
- target endpoint
isEnabled - target endpoint
isWritable - target device thuộc cùng organization
- target device không ở trạng thái retired hoặc maintenance nếu hệ thống hiện đã có check tương tự
10.3. Recovery Action Semantics
Recovery actions không bị suy diễn tự động từ trigger actions.
User phải cấu hình rõ:
- trigger phase làm gì
- recovery phase làm gì
Ví dụ:
- trigger:
- tạo critical alert
- bật quạt 1
- bật quạt 2
- recovery:
- tạo info alert
- tắt quạt 1
- tắt quạt 2
11. API Design
11.1. Rule DTO Shape
Create/update DTO cần đổi sang aggregate shape:
type RuleConditionDto = {
sourceDeviceEndpointId: string;
operator: '<' | '<=' | '>' | '>=' | '=' | '!=';
thresholdValue: number | boolean | string;
sequenceOrder: number;
};
type AlertActionPayloadDto = {
severity: 'info' | 'warning' | 'critical';
titleTemplate: string;
messageTemplate: string;
};
type DeviceCommandActionPayloadDto = {
targetDeviceEndpointId: string;
targetValue: number | boolean | string;
};
type RuleActionDto = {
actionType: 'alert' | 'device_command';
sequenceOrder: number;
isEnabled: boolean;
payload: AlertActionPayloadDto | DeviceCommandActionPayloadDto;
};
type CreateReactionRuleDto = {
name: string;
description?: string;
conditionOperator: 'AND' | 'OR';
cooldownSeconds?: number;
conditions: RuleConditionDto[];
triggerActions: RuleActionDto[];
recoveryActions: RuleActionDto[];
};
11.2. Endpoints
GET /api/v1/automation/rulesGET /api/v1/automation/rules/:idPOST /api/v1/automation/rulesPUT /api/v1/automation/rules/:idPOST /api/v1/automation/rules/:id/activatePOST /api/v1/automation/rules/:id/pauseGET /api/v1/automation/rules/:id/executions
List response nên include:
- summary thông tin rule
- condition count
- trigger action count
- recovery action count
- current runtime state
- last executed at
11.3. Validation Rules
Backend validation phải enforce:
- conditions không được rỗng
- trigger actions có thể rỗng nếu user chỉ muốn recovery-only?
Khôngcho phase đầu - recovery actions được phép rỗng
- mọi source endpoints phải readable
- mọi target endpoints trong
device_commandphải writable - mọi source/target devices phải cùng organization của rule
alertaction không được mang payload củadevice_commandvà ngược lại
Bản đầu chốt thêm:
triggerActionsphải có ít nhất một actionrecoveryActionscó thể rỗng
12. Frontend Design
12.1. Screen Strategy
Tạo màn Automation Rules thực thụ, không dùng màn AlertConfig.
Màn cần có:
- list rules
- create/edit wizard
- rule detail
- execution history
12.2. Authoring Flow
Wizard 5 bước:
- Rule info
- Conditions
- Trigger actions
- Recovery actions
- Review and activate
Lý do dùng wizard:
- rule shape đủ phức tạp
- conditions và actions là nested collections
- cần review toàn rule trước khi activate
12.3. UX Constraints
UI phải giúp user:
- thêm nhiều conditions từ nhiều devices
- chọn
ANDhoặcOR - thêm nhiều actions theo thứ tự
- phân biệt rõ
triggervớirecovery - preview human-readable text của rule trước khi lưu
Màn list cần hiển thị:
- rule name
- status
- condition summary
- trigger/recovery action counts
- last state
- last execution time
13. Permissions
Permissions có thể tiếp tục nằm dưới namespace automation.
Phase đầu cần đủ các quyền:
automation:read:*automation:create:*automation:update:*automation:activate:*automation:pause:*
Nếu repo hiện chưa có namespace này đầy đủ, implementation phải thêm cho đồng bộ thay vì reuse sai namespace của device.
14. Error Handling And Audit
Hệ thống phải ghi được:
- condition nào stale
- source nào thiếu latest snapshot
- action nào fail
- target nào bị reject vì không writable hoặc khác organization
- phase nào đã chạy
- state transition nào xảy ra
Không được fail toàn rule chỉ vì một action fail. Fail được cô lập ở action result và phản ánh lên execution envelope.
15. Testing Strategy
15.1. Unit Tests
- rule validation cho DTO mới
- aggregate condition evaluation với
AND - aggregate condition evaluation với
OR - stale snapshot handling
- state transition logic
- cooldown logic theo từng phase
- action execution ordering
- alert payload validation
- device command payload validation
15.2. Service Tests
- telemetry update làm refresh latest endpoint snapshot
- event mới reevaluate đúng set rules liên quan
normal -> triggeredchạy trigger actions đúng một lầntriggered -> normalchạy recovery actions đúng một lần- multi-device rule dùng latest values từ nhiều sources
- rule không trigger nếu source khác organization
- conflict runtime giữ semantics
last command wins
15.3. Frontend Tests
- wizard render đúng từng step
- add/remove/reorder conditions
- add/remove/reorder actions
- validation khi thiếu trigger action
- serialization đúng DTO shape backend cần
16. Implementation Notes
Các thay đổi cốt lõi cần phản ánh trong code:
- bỏ
checkThresholds()khỏi runtime path của telemetry - bỏ assumption
farmIdtrong automation rule model và engine - reshape DTO/service/controller/entity của automation thành aggregate rule model
- tái sử dụng alert creation path thay vì giữ
alert-config
AlertConfigPage và các service liên quan không còn là target của feature mới. Chúng có thể bị loại khỏi navigation hoặc dọn hẳn tùy implementation phase, nhưng không còn được coi là source of truth cho reaction behavior.
17. Done Criteria
Feature được coi là xong khi:
- user tạo được rule có nhiều conditions và nhiều actions
- rule hỗ trợ
AND/OR - rule trigger theo edge-transition, không spam ở mọi telemetry packet
- rule chạy recovery actions khi quay về normal
- alert hoạt động như một action type trong automation
- device command hoạt động như một action type trong automation
- multi-device latest snapshot evaluation hoạt động với
freshness window = 300s - không còn threshold alert runtime path riêng ngoài automation
- test backend/frontend tương ứng đều pass