|
1 | 1 | --- |
2 | 2 | title: Automation Rules |
3 | | -description: The Protocol for Server-Side Logic. Database Triggers, Scheduled Jobs, and No-Code Automation Flows. |
| 3 | +description: The Protocol for Lightweight, Event-Driven Logic. |
4 | 4 | --- |
5 | 5 |
|
| 6 | +Automation Rules differ from Workflows in that they are typically strictly **Event-Driven** and stateless. |
6 | 7 |
|
7 | | -While Workflows guide a record through a lifecycle, **Automation Rules** handle the immediate logic and side effects of data changes. |
8 | | - |
9 | | -ObjectOS divides automation into three categories: |
10 | | -1. **Triggers (Code):** High-performance, synchronous TypeScript hooks for data integrity. |
11 | | -2. **Flows (Low-Code):** Declarative, asynchronous event chains (IFTTT style). |
12 | | -3. **Scheduled Jobs:** Time-based execution (CRON). |
13 | | - |
14 | | -## 1. Database Triggers (Synchronous Logic) |
15 | | - |
16 | | -Triggers are the "Reflexes" of the system. They intercept database operations **before** or **after** they happen. They execute within the same database transaction as the mutation. |
17 | | - |
18 | | -### Trigger Definition |
19 | | - |
20 | | -Triggers are defined in TypeScript files next to your Object definitions. |
| 8 | +## 1. Triggers (Code) |
| 9 | +Server-side scripts (TypeScript/Python) that run in the transaction transaction. |
21 | 10 |
|
22 | 11 | ```typescript |
23 | | -// triggers/order.trigger.ts |
24 | | -import { Trigger } from '@objectos/types'; |
25 | | - |
26 | | -export const validateDiscount: Trigger = { |
27 | | - name: 'validate_order_discount', |
28 | | - object: 'order', |
29 | | - on: ['create', 'update'], |
30 | | - when: 'before', // Runs before writing to DB |
31 | | - |
32 | | - handler: async ({ doc, previousDoc, session, broker }) => { |
33 | | - // 1. Logic: Discount cannot exceed 20% unless authorized |
34 | | - if (doc.discount > 0.20 && !session.hasRole('manager')) { |
35 | | - throw new Error("Discounts > 20% require Manager approval."); |
| 12 | +// project.trigger.ts |
| 13 | +export const beforeInsert = async (ctx) => { |
| 14 | + if (ctx.doc.amount > 10000) { |
| 15 | + ctx.doc.status = 'High Value'; |
36 | 16 | } |
37 | | - |
38 | | - // 2. Logic: Auto-calculate final price |
39 | | - doc.final_price = doc.list_price * (1 - doc.discount); |
40 | | - } |
41 | 17 | } |
42 | | - |
43 | 18 | ``` |
44 | 19 |
|
45 | | -### Key Capabilities |
46 | | - |
47 | | -* **Validation:** Throwing an error aborts the entire transaction. |
48 | | -* **Computation:** Modifying `doc` directly updates the data being saved. |
49 | | -* **Snapshot Access:** You have access to `doc` (new state) and `previousDoc` (old state) to detect changes (e.g., `if (doc.status !== previousDoc.status)`). |
50 | | - |
51 | | -## 2. Automation Flows (Declarative Logic) |
52 | | - |
53 | | -For logic that doesn't require hard coding, ObjectOS supports **Automation Flows**. These are defined in YAML (or built via a Visual Builder) and run **asynchronously** after the transaction commits. |
54 | | - |
55 | | -### The Flow Protocol |
56 | | - |
57 | | -```yaml |
58 | | -# automations/notify_high_value_deal.yaml |
59 | | -name: notify_high_value_deal |
60 | | -label: Notify VP on Big Deals |
61 | | -trigger: |
62 | | - type: data.changed |
63 | | - object: deal |
64 | | - condition: "doc.amount > 1000000 && doc.stage == 'closed_won'" |
65 | | - |
66 | | -actions: |
67 | | - - type: notification.send |
68 | | - params: |
69 | | - recipient: "role:vp_sales" |
70 | | - subject: "Big Win: ${doc.name}" |
71 | | - message: "Deal closed for ${formatCurrency(doc.amount)}!" |
72 | | - |
73 | | - - type: record.create |
74 | | - params: |
75 | | - object: "audit_log" |
76 | | - data: |
77 | | - event: "big_deal_alert" |
78 | | - deal_id: "${doc._id}" |
79 | | - |
80 | | -``` |
81 | | - |
82 | | -### Flow Components |
83 | | - |
84 | | -* **Trigger:** What starts the flow? (`data.changed`, `user.login`, `webhook.received`). |
85 | | -* **Condition:** A logical expression (Expression Language) that must be true. |
86 | | -* **Actions:** A sequential list of tasks (Send Email, Call API, Create Record). |
87 | | - |
88 | | -## 3. Scheduled Jobs (CRON) |
89 | | - |
90 | | -Enterprise systems need to do things when no one is watching. ObjectOS includes a distributed **Job Scheduler**. |
91 | | - |
92 | | -### Protocol Definition |
93 | | - |
94 | | -```yaml |
95 | | -# jobs/monthly_invoicing.job.yml |
96 | | -name: generate_monthly_invoices |
97 | | -cron: "0 0 1 * *" # Run at midnight on the 1st of every month |
98 | | -timeout: 3600 # 1 hour max |
99 | | -retries: 3 |
100 | | - |
101 | | -task: |
102 | | - action: "finance.batch_generate_invoices" |
103 | | - params: |
104 | | - period: "last_month" |
105 | | - |
106 | | -``` |
107 | | - |
108 | | -* **Distributed:** In a cluster, the OS ensures the job runs on only **one** node (via Redis locks). |
109 | | -* **Resilient:** Failed jobs are automatically retried based on the policy. |
110 | | - |
111 | | -## 4. Server-Side Scripting API |
112 | | - |
113 | | -Whether writing Triggers or Custom Actions, you interact with the ObjectOS Kernel via the standard **Broker API**. This ensures your code is safe and upgrade-proof. |
114 | | - |
115 | | -### The Broker Object |
116 | | - |
117 | | -The `broker` is your gateway to the rest of the OS. |
118 | | - |
119 | | -```typescript |
120 | | -// Inside a Trigger or Service |
121 | | -async function handler({ broker, session }) { |
122 | | - |
123 | | - // 1. Data Access (Respects Permissions) |
124 | | - const user = await broker.call('data.find', { |
125 | | - object: 'user', |
126 | | - id: 'u1' |
127 | | - }, { session }); |
128 | | - |
129 | | - // 2. Cross-Service Calls |
130 | | - await broker.call('mail.send', { ... }); |
131 | | - |
132 | | - // 3. Emit Custom Events |
133 | | - broker.emit('custom.event', { foo: 'bar' }); |
134 | | -} |
135 | | - |
136 | | -``` |
137 | | - |
138 | | -### The "Sudo" Mode |
139 | | - |
140 | | -Sometimes you need to bypass permissions (e.g., a system background job). |
141 | | - |
142 | | -```typescript |
143 | | -// Create a System Session (Super Admin) |
144 | | -const sudoSession = session.sudo(); |
145 | | - |
146 | | -await broker.call('data.update', { ... }, { session: sudoSession }); |
147 | | - |
148 | | -``` |
| 20 | +## 2. Validation Rules (No-Code) |
| 21 | +Boolean expressions that block a save if they return `true`. |
| 22 | +Defined in the Object Schema (`validation` property). |
149 | 23 |
|
150 | | -## 5. Comparison: Trigger vs. Flow vs. Workflow |
| 24 | +## 3. Auto-Response Rules |
| 25 | +Logic for sending immediate email replies (e.g., "Thanks for your Ticket"). |
151 | 26 |
|
152 | | -| Feature | Database Trigger | Automation Flow | Workflow (BPM) | |
153 | | -| --- | --- | --- | --- | |
154 | | -| **Protocol** | TypeScript | YAML / JSON | YAML / BPMN | |
155 | | -| **Timing** | Synchronous (Blocking) | Asynchronous (Background) | Long-Running (Days/Weeks) | |
156 | | -| **Transactional** | Yes (Can Rollback) | No (Committed) | No | |
157 | | -| **Use Case** | Data Integrity, Calculations | Notifications, Sync | Approvals, Lifecycle | |
158 | | -| **Complexity** | High (Code) | Low (Config) | Medium (State Machine) | |
| 27 | +## 4. Assignment Rules |
| 28 | +Logic for changing the `owner` of a record (e.g., "Round Robin" assignment for Leads). |
159 | 29 |
|
160 | | -:::tip Best Practice |
161 | | -Always prefer **Triggers** for data integrity (e.g., "Price cannot be negative"). |
162 | | -Always prefer **Workflows** for human processes (e.g., "Manager must approve"). |
163 | | -Use **Flows** for everything in between (e.g., "Send email on update"). |
164 | | -::: |
| 30 | +## 5. Escalation Rules |
| 31 | +Logic for time-based updates (e.g., "If Case not solved in 4h, notify Manager"). |
0 commit comments