Version: 0.9.60.dev.260430

后端:
1.接入主动调度 worker 与飞书通知链路
- 新增 due job scanner 与 active_schedule.triggered workflow
- 接入 notification.feishu.requested handler、飞书 webhook provider 和用户通知配置接口
- 支持 notification_records 去重、重试、skipped/dead 状态流转
- 完成 api / worker / all 启动模式装配与主动调度验收记录
2.后续要做的就是补全从异常发生到给用户推送消息之间的逻辑缺口
This commit is contained in:
Losita
2026-04-30 23:45:27 +08:00
parent e945578fbf
commit 0a014f7472
26 changed files with 3636 additions and 55 deletions

View File

@@ -0,0 +1,32 @@
package notification
import (
"fmt"
"strings"
"time"
)
const (
// DefaultFeishuDedupeWindow 是 notification 第一版固定的 30 分钟去重窗口。
DefaultFeishuDedupeWindow = 30 * time.Minute
)
// BuildTimeWindowDedupeKey 构造“user_id + trigger_type + time_window”去重键。
//
// 职责边界:
// 1. 供事件发布方在生成 `notification.feishu.requested` payload 时复用;
// 2. 只负责把 30 分钟窗口归一成稳定 key不负责落 notification_records
// 3. unfinished_feedback 若要改用 feedback_id / idempotency_key可不使用这个 helper。
func BuildTimeWindowDedupeKey(userID int, triggerType string, requestedAt time.Time, window time.Duration) string {
if window <= 0 {
window = DefaultFeishuDedupeWindow
}
if userID <= 0 || strings.TrimSpace(triggerType) == "" || requestedAt.IsZero() {
return ""
}
// 1. 先把请求时间归一到固定窗口起点,保证 30 分钟内多次触发得到同一 key。
// 2. requestedAt 为空或非法时直接返回空字符串,让上游显式感知入参不完整。
windowStartUnix := requestedAt.Unix() / int64(window.Seconds())
return fmt.Sprintf("%d:%s:%d", userID, strings.TrimSpace(triggerType), windowStartUnix)
}