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,88 @@
package notification
import "context"
const (
// ChannelFeishu 表示当前通知记录走飞书通道。
ChannelFeishu = "feishu"
)
const (
// FeishuErrorCodeProviderTimeout 表示 provider 超时,属于可重试错误。
FeishuErrorCodeProviderTimeout = "provider_timeout"
// FeishuErrorCodeProviderRateLimited 表示 provider 限流,属于可重试错误。
FeishuErrorCodeProviderRateLimited = "provider_rate_limited"
// FeishuErrorCodeProvider5xx 表示 provider 服务端异常,属于可重试错误。
FeishuErrorCodeProvider5xx = "provider_5xx"
// FeishuErrorCodeNetworkError 表示网络层异常,属于可重试错误。
FeishuErrorCodeNetworkError = "network_error"
// FeishuErrorCodeRecipientMissing 表示缺少接收方,属于不可恢复错误。
FeishuErrorCodeRecipientMissing = "recipient_missing"
// FeishuErrorCodeInvalidURL 表示目标链接非法,属于不可恢复错误。
FeishuErrorCodeInvalidURL = "invalid_url"
// FeishuErrorCodeProviderAuthFailed 表示 provider 认证失败,属于不可恢复错误。
FeishuErrorCodeProviderAuthFailed = "provider_auth_failed"
// FeishuErrorCodePayloadInvalid 表示请求体非法,属于不可恢复错误。
FeishuErrorCodePayloadInvalid = "payload_invalid"
)
// FeishuSendOutcome 表示 provider 对一次投递尝试的分类结果。
//
// 职责边界:
// 1. 只表达 provider 层对“这次投递”是否成功、是否可重试的判断;
// 2. 不直接承载 notification_records 的状态机,状态流转由 NotificationService 决定;
// 3. future webhook/open_id provider 只要返回同一套枚举,即可复用现有重试逻辑。
type FeishuSendOutcome string
const (
FeishuSendOutcomeSuccess FeishuSendOutcome = "success"
FeishuSendOutcomeTemporaryFail FeishuSendOutcome = "temporary_fail"
FeishuSendOutcomePermanentFail FeishuSendOutcome = "permanent_fail"
FeishuSendOutcomeSkipped FeishuSendOutcome = "skipped"
)
// FeishuSendRequest 是通知服务传给 provider 的稳定输入。
//
// 职责边界:
// 1. 只描述 provider 真正发消息所需的信息;
// 2. 不暴露 GORM model避免 provider 依赖数据库细节;
// 3. 同时保留审计字段,方便 mock/webhook provider 记录请求摘要。
type FeishuSendRequest struct {
NotificationID int64 `json:"notification_id"`
UserID int `json:"user_id"`
TriggerID string `json:"trigger_id"`
PreviewID string `json:"preview_id"`
TriggerType string `json:"trigger_type"`
TargetType string `json:"target_type"`
TargetID int `json:"target_id"`
TargetURL string `json:"target_url"`
MessageText string `json:"message_text"`
FallbackUsed bool `json:"fallback_used"`
TraceID string `json:"trace_id,omitempty"`
AttemptCount int `json:"attempt_count"`
}
// FeishuSendResult 是 provider 对外返回的投递结果。
//
// 职责边界:
// 1. outcome 决定 NotificationService 应该进入 sent / failed / dead 中哪一条路径;
// 2. request/response payload 仅用于落库审计,不要求与任意具体 SDK 强绑定;
// 3. error_code 需要尽量稳定,便于后续按错误码做告警和排障。
type FeishuSendResult struct {
Outcome FeishuSendOutcome `json:"outcome"`
ProviderMessageID string `json:"provider_message_id,omitempty"`
ErrorCode string `json:"error_code,omitempty"`
ErrorMessage string `json:"error_message,omitempty"`
RequestPayload any `json:"request_payload,omitempty"`
ResponsePayload any `json:"response_payload,omitempty"`
}
// FeishuProvider 是飞书投递能力的抽象边界。
//
// 职责边界:
// 1. 负责把最终文案发给具体 provider
// 2. 不负责 notification_records 的创建、去重、状态机和重试节奏;
// 3. 后续新增 WebhookFeishuProvider / OpenIDFeishuProvider 时,只需实现这个接口。
type FeishuProvider interface {
Send(ctx context.Context, req FeishuSendRequest) (FeishuSendResult, error)
}