feat: 配置列表分页与钉钉机器人分钟级排队限流
统一 sources/templates/channels/rules 列表为分页响应,避免配置增多时全量返回;按钉钉 access_token 限制每分钟发送并在超限时等待下一分钟,降低触发官方封禁风险。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -47,10 +47,16 @@ func (s *Store) GetChannelByName(ctx context.Context, name string) (*model.Chann
|
||||
return &ch, nil
|
||||
}
|
||||
|
||||
func (s *Store) ListChannels(ctx context.Context) ([]model.Channel, error) {
|
||||
rows, err := s.DB.QueryContext(ctx, `SELECT id, name, type, config, status, created_at, updated_at FROM notification_channel ORDER BY id`)
|
||||
func (s *Store) ListChannels(ctx context.Context, page PageFilter) ([]model.Channel, int, error) {
|
||||
var count int
|
||||
if err := s.DB.GetContext(ctx, &count, `SELECT COUNT(*) FROM notification_channel`); err != nil {
|
||||
return nil, 0, fmt.Errorf("count channels: %w", err)
|
||||
}
|
||||
|
||||
page.Normalize()
|
||||
rows, err := s.DB.QueryContext(ctx, `SELECT id, name, type, config, status, created_at, updated_at FROM notification_channel ORDER BY id LIMIT ? OFFSET ?`, page.PageSize, page.Offset())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list channels: %w", err)
|
||||
return nil, 0, fmt.Errorf("list channels: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
@@ -59,13 +65,13 @@ func (s *Store) ListChannels(ctx context.Context) ([]model.Channel, error) {
|
||||
var ch model.Channel
|
||||
var configBytes []byte
|
||||
if err := rows.Scan(&ch.ID, &ch.Name, &ch.Type, &configBytes, &ch.Status, &ch.CreatedAt, &ch.UpdatedAt); err != nil {
|
||||
return nil, fmt.Errorf("scan channel: %w", err)
|
||||
return nil, 0, fmt.Errorf("scan channel: %w", err)
|
||||
}
|
||||
raw := json.RawMessage(configBytes)
|
||||
ch.Config = &raw
|
||||
channels = append(channels, ch)
|
||||
}
|
||||
return channels, rows.Err()
|
||||
return channels, count, rows.Err()
|
||||
}
|
||||
|
||||
func (s *Store) UpdateChannel(ctx context.Context, id int, ch *model.Channel) error {
|
||||
|
||||
Reference in New Issue
Block a user