通知
配置 ObjectOS 如何把事件路由進使用者的收件箱 —— 生產方傳送到的受眾、每個使用者的偏好,以及渲染模板。
本頁講的是通知的管理員一側:事件如何變成訊息,以及支撐它們的三個由系統 管理的物件。收件人視角的收件箱 —— 閱讀和靜音通知 —— 參見使用一節中的 通知。
通知管道
一條通知不是單獨一條記錄。它流經四個階段:
emit() + explicit audience → Notification Event → recipients, filtered by Preference → Inbox Messageemit()—— 應用程式碼發起一個事件(審批已提交、記錄已共享、邀請已 傳送),並指定它的受眾。受眾是必需的輸入,由它決定通知誰。- 通知事件(
sys_notification)—— 每次emit()寫入一行入口記錄。這是 在做出任何投遞決定之前,發生了什麼的診斷日誌。如何閱讀它,參見 審計日誌。 - 路由 —— 對每個事件,ObjectOS 把生產方傳入的受眾展開為收件人,檢查每個 收件人是否允許該主題在該渠道上投遞(偏好),並把每個被接受的投遞交給 相應的渠道,由渠道負責渲染。渠道基於什麼渲染因渠道而異:郵件和簡訊渲染 通知模板;應用內收件箱則不用(參見 各渠道渲染什麼)。
- 收件箱訊息(
sys_inbox_message)—— 收件人在收件箱中實際看到的、按使用者 生成的結果。
偏好、訂閱和模板是管理員 / 系統一側的配置。收件箱訊息是使用者一側的輸出。
路由如何解析
對於單個事件,決定誰收到什麼的輸入是:
| 輸入 | 它回答的問題 |
|---|---|
傳給 emit() 的受眾 | 誰收到它? —— 由生產方指定收件人,這是唯一能把人放進名單的輸入 |
| 通知偏好 | 這個收件人允許在這裡收到它嗎? —— 每個使用者對該主題和渠道的靜音 / 允許設定,作用於每一個(收件人 × 渠道)組合 |
| 通知模板 | 它怎麼寫? —— 在郵件和簡訊渠道上渲染的主題和正文。應用內收件箱不讀取這些行;參見各渠道渲染什麼 |
| 通知訂閱 | 誰宣告過長期的關注? —— 由管理員編寫的行,在路由事件時不會被參考 |
當生產方的受眾解析到某個收件人,且其偏好沒有在該渠道上靜音該主題時,這個 收件人就會收到收件箱訊息。預設是允許,所以沒有偏好行的收件人依然會收到通知, 而強制性主題(安全告警之類)會完全繞過偏好。
警告: 訂閱行不會路由任何東西。從訂閱到收件人的展開沒有接通:
emit()需要一個顯式的受眾,上述管道中沒有任何環節會把某個主題的訂閱展開 為收件人。每一次投遞都來自生產方傳入的受眾,這使得 Setup 中的 Notification Subscriptions 表格只是管理員編寫的資料,而不是一個生效的 路由控制元件 —— 暫停一行(enabled = false)什麼也不會阻止,新增一行也什麼都 不會投遞。
這是對本頁所述通知管道的陳述。它並不是在斷言執行在 ObjectOS 之上的某項能力 或整合會出於自身目的如何使用這些行。ADR-0012 和 ADR-0030 把訂閱驅動的路由 描述為目標狀態,而不是今天的行為:能讓這些行與路由相關的那個展開並沒有 被構建,也沒有排期。如果將來構建了它,這裡描述的行為也會隨之改變。
偏好和模板由平臺預置並維護,所以這些列表檢視中大多是系統生成的行。訂閱行是 管理員在 Setup 中編寫的那一類,這也是為什麼那張表格讀起來像一個路由控制元件。
通知偏好
位於 Setup → Configuration → Notification Preferences
(sys_notification_preference)。
按使用者 × 主題 × 渠道的開關(靜音 / 允許),並帶有管理員設定的全域性預設值。 偏好決定某個收件人是否在某個渠道上收到某個主題。
| 欄位 | 用途 |
|---|---|
user_id | 偏好所屬的主體 |
topic | 通知主題(例如 project.digest) |
channel | 投遞渠道(應用內、郵件 ……) |
enabled | 布林值 —— 為該使用者允許或靜音此主題 / 渠道 |
digest | 該主題的批次彙總節奏 |
quiet_hours | 抑制投遞的時間視窗(JSON) |
created_at / updated_at | 審計時間戳 |
條目會在其來源動作第一次執行時自動出現(例如 Submit for Approval、 Share 或 Invite)—— 你很少需要手工建立偏好行。用這個列表調整管理員 預設值,或者靜音一個吵鬧的主題。
通知訂閱
位於 Setup → Configuration → Notification Subscriptions
(sys_notification_subscription)。
某個主體對某個通知主題的長期訂閱:這一行記錄的是有人宣告過對該主題感 興趣。它是參考資料 —— 投遞路徑的任何部分都不會讀取它,所以訂閱行既不會增加 收件人,也不會移除收件人(參見路由如何解析)。
| 欄位 | 用途 |
|---|---|
topic | 被訂閱的主題 |
principal | 訂閱者 —— 一個選擇器字串;參見在 principal 中填什麼 |
enabled | 布林值 —— 把這一行標記為啟用或暫停。沒有任何投遞會參考它 |
在 principal 中填什麼
principal 是一個單獨的文本欄位,而不是選擇器:值是一個選擇器字串,
它的字首決定這個值與什麼匹配。下面這些形式,是平臺的收件人解析器對任何
選擇器字串都接受的形式 —— 與 emit() 受眾所用的語法相同。沒有可識別
字首的值會被當作裸使用者 id —— 所以填入 sales_manager(或 Sales team)
指向的是一個不存在的使用者,而不是你想要的那個群體。
| 值 | 解析為 | 示例 |
|---|---|---|
role:name | 組織中成員層級為該名稱的所有人(sys_member.role) | role:admin |
team:id | 該團隊的所有成員,按團隊 id 而不是標籤匹配(sys_team_member.team_id) | team:team_123 |
user:id | 那一個使用者,按使用者 id | user:usr_123 |
owner_of:object:id | 擁有那一條記錄的人 —— 記錄上第一個負責人 / 被指派人欄位 | owner_of:invoice:inv_123 |
| 一個郵箱地址 | 郵箱與之匹配的使用者。沒有匹配到任何使用者的地址會被原樣保留為收件人 id,而不是被拒絕 | ada@example.com |
id | 沒有可識別的字首 —— 整個值被當作裸使用者 id | usr_123 |
這張列表是解析器接受的內容,而不是為訂閱行設計的契約:owner_of: 和郵箱
形式之所以存在,是因為每個選擇器字串都經過同一個解析器。它們是否適合出現
在長期訂閱中,是平臺尚未定論的開放問題。
這裡的
role:指的是組織成員層級,而不是職能。 層級包括owner、admin、delegated_admin和member—— 即使用者在 組織中的身份。職能是一個崗位,而 崗位名稱在這裡無法定址:role:sales_manager匹配不到任何人。在 ObjectOS 的 其他地方,role 都是已退役的詞彙(能力是許可權集,分配是崗位);組織成員 層級是唯一的例外,這個選擇器也沿用了同樣的寫法。
選擇器背後的目錄查詢被有意設計為盡力而為 —— 絕不會因為某次查詢沒有命中就讓 一個事件失敗。因此,匹配不到任何東西的選擇器會悄無聲息地解析為零個 收件人:這一行依然有效、依然啟用,也不會有任何報告。未匹配的郵箱是更鋒利 的邊緣 —— 它會被原樣保留為收件人 id,所以一個拼寫錯誤就成了一個永遠無法 觸達的收件人。當某個主題沒有送達任何人時,先檢查值的字首和拼寫。
通知模板
位於 Setup → Configuration → Notification Templates
(sys_notification_template)。
按**(主題 × 渠道 × locale)劃分的渲染模板,由郵件和簡訊**渠道讀取: 模板把事件內容轉換成這些渠道傳送的主題和正文。應用內收件箱不讀取這些行 —— 參見各渠道渲染什麼。
| 欄位 | 用途 |
|---|---|
topic | 此模板渲染的主題 |
channel | 渲染輸出的目標渠道 |
locale | 此渲染的 locale —— 是通知自身的,而不是收件人的 |
version | 模板版本號 |
subject | 渲染後的標題 |
body | 訊息正文(markdown) |
format | 正文的輸出格式 |
is_active | 布林值 —— 此模板是否用於渲染 |
locale 是按通知而不是按收件人匹配的:如果生產方設定了 payload.locale,
投遞就用它渲染,否則用部署的預設值。沒有任何環節會根據接收者來解析 locale,
所以一次 emit 對它觸達的每個收件人都以同一個 locale 渲染 —— 為某個主題編寫
es 和 en 兩行,是給生產方兩種可選的渲染,而不是讓兩個收件人各自用自己的
語言閱讀。
這些物件是系統管理的:行由平臺以及你執行的能力預置,所以你的大部分工作
是編輯模板內容,或切換 is_active、enabled 和偏好預設值,而不是從零建立
記錄。
各渠道渲染什麼
渲染按渠道進行,只有兩個渠道會讀取上面這些行:
| 渠道 | 基於什麼渲染 |
|---|---|
| 郵件 | 匹配(主題、email、locale)的通知模板。沒有匹配的啟用行時,原樣傳送通知自身的標題和正文 |
| 簡訊 | 匹配(主題、sms、locale)的通知模板,回落方式相同 |
| 應用內收件箱 | 不是通知模板。 收件箱行由通知自身的標題和正文寫成 —— 生產方沒有設定標題時就用主題。當通知指定的是一個郵件模板時,收件箱會渲染那個模板:通過郵件服務按(名稱、locale)解析的一行 sys_email_template,郵件中有說明。如果沒有能渲染它的郵件服務,這次投遞會失敗,而不是回落 |
警告:
inbox是預設渠道 —— 沒有指定渠道的通知只會投遞到那裡。 所以管理員最可能在看的那次投遞,恰恰是從不讀取通知模板的那一次:在這裡 編輯模板行會改變郵件和簡訊傳送的內容,而對應用內訊息毫無影響。本頁描述的 是現有的接線方式;它並不預告收件箱與這些行之間會有銜接。