2000908bac
- Added functionality to list and start Safew tokens in the main server function, ensuring proper initialization of the Safew watcher. - Introduced `ensureSafewWatcher` method in the ChannelHandler to manage Safew tokens during channel creation and updates. - Implemented `StartTokens` method in the Watcher to handle multiple tokens efficiently. - Enhanced error handling and logging for Safew watcher operations to improve observability.
133 lines
4.1 KiB
Go
133 lines
4.1 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"aiaa-notification-service/internal/model"
|
|
)
|
|
|
|
func (s *Store) CreateChannel(ctx context.Context, ch *model.Channel) error {
|
|
configJSON, err := json.Marshal(ch.Config)
|
|
if err != nil {
|
|
return fmt.Errorf("marshal channel config: %w", err)
|
|
}
|
|
query := `INSERT INTO notification_channel (name, type, config, status) VALUES (?, ?, ?, ?)`
|
|
result, err := s.DB.ExecContext(ctx, query, ch.Name, ch.Type, configJSON, ch.Status)
|
|
if err != nil {
|
|
return fmt.Errorf("create channel: %w", err)
|
|
}
|
|
id, _ := result.LastInsertId()
|
|
ch.ID = int(id)
|
|
return nil
|
|
}
|
|
|
|
func (s *Store) GetChannel(ctx context.Context, id int) (*model.Channel, error) {
|
|
var ch model.Channel
|
|
var configBytes []byte
|
|
row := s.DB.QueryRowContext(ctx, `SELECT id, name, type, config, status, created_at, updated_at FROM notification_channel WHERE id = ?`, id)
|
|
if err := row.Scan(&ch.ID, &ch.Name, &ch.Type, &configBytes, &ch.Status, &ch.CreatedAt, &ch.UpdatedAt); err != nil {
|
|
return nil, fmt.Errorf("get channel %d: %w", id, err)
|
|
}
|
|
raw := json.RawMessage(configBytes)
|
|
ch.Config = &raw
|
|
return &ch, nil
|
|
}
|
|
|
|
func (s *Store) GetChannelByName(ctx context.Context, name string) (*model.Channel, error) {
|
|
var ch model.Channel
|
|
var configBytes []byte
|
|
row := s.DB.QueryRowContext(ctx, `SELECT id, name, type, config, status, created_at, updated_at FROM notification_channel WHERE name = ?`, name)
|
|
if err := row.Scan(&ch.ID, &ch.Name, &ch.Type, &configBytes, &ch.Status, &ch.CreatedAt, &ch.UpdatedAt); err != nil {
|
|
return nil, fmt.Errorf("get channel by name %s: %w", name, err)
|
|
}
|
|
raw := json.RawMessage(configBytes)
|
|
ch.Config = &raw
|
|
return &ch, nil
|
|
}
|
|
|
|
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, 0, fmt.Errorf("list channels: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
channels := make([]model.Channel, 0)
|
|
for rows.Next() {
|
|
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, 0, fmt.Errorf("scan channel: %w", err)
|
|
}
|
|
raw := json.RawMessage(configBytes)
|
|
ch.Config = &raw
|
|
channels = append(channels, ch)
|
|
}
|
|
return channels, count, rows.Err()
|
|
}
|
|
|
|
func (s *Store) UpdateChannel(ctx context.Context, id int, ch *model.Channel) error {
|
|
configJSON, err := json.Marshal(ch.Config)
|
|
if err != nil {
|
|
return fmt.Errorf("marshal channel config: %w", err)
|
|
}
|
|
query := `UPDATE notification_channel SET name=?, type=?, config=?, status=? WHERE id=?`
|
|
_, err = s.DB.ExecContext(ctx, query, ch.Name, ch.Type, configJSON, ch.Status, id)
|
|
if err != nil {
|
|
return fmt.Errorf("update channel %d: %w", id, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Store) DeleteChannel(ctx context.Context, id int) error {
|
|
_, err := s.DB.ExecContext(ctx, `DELETE FROM notification_channel WHERE id = ?`, id)
|
|
if err != nil {
|
|
return fmt.Errorf("delete channel %d: %w", id, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Store) ListSafewTokens(ctx context.Context) ([]string, error) {
|
|
rows, err := s.DB.QueryContext(ctx, `SELECT config FROM notification_channel WHERE type = 'safew'`)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("list safew tokens: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
seen := map[string]struct{}{}
|
|
var tokens []string
|
|
for rows.Next() {
|
|
var configBytes []byte
|
|
if err := rows.Scan(&configBytes); err != nil {
|
|
return nil, fmt.Errorf("scan safew config: %w", err)
|
|
}
|
|
var cfg struct {
|
|
Token string `json:"token"`
|
|
}
|
|
if err := json.Unmarshal(configBytes, &cfg); err != nil {
|
|
continue
|
|
}
|
|
tok := strings.TrimSpace(cfg.Token)
|
|
if tok == "" {
|
|
continue
|
|
}
|
|
if _, ok := seen[tok]; ok {
|
|
continue
|
|
}
|
|
seen[tok] = struct{}{}
|
|
tokens = append(tokens, tok)
|
|
}
|
|
if tokens == nil {
|
|
tokens = []string{}
|
|
}
|
|
return tokens, rows.Err()
|
|
}
|