164 lines
4.5 KiB
Go
164 lines
4.5 KiB
Go
package sqlite
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
type RouteFailoverEvent struct {
|
|
ID int64
|
|
RequestID string
|
|
LogicalGroupID string
|
|
PublicModel string
|
|
FromRouteID string
|
|
ToRouteID string
|
|
Reason string
|
|
FailureCount int
|
|
CreatedAt string
|
|
}
|
|
|
|
type RouteFailoverEventFilter struct {
|
|
RequestID string
|
|
LogicalGroupID string
|
|
PublicModel string
|
|
FromRouteID string
|
|
ToRouteID string
|
|
Limit int
|
|
}
|
|
|
|
type RouteFailoverEventsRepo struct {
|
|
db execQuerier
|
|
}
|
|
|
|
func newRouteFailoverEventsRepo(db execQuerier) *RouteFailoverEventsRepo {
|
|
return &RouteFailoverEventsRepo{db: db}
|
|
}
|
|
|
|
func (r *RouteFailoverEventsRepo) Create(ctx context.Context, row RouteFailoverEvent) (int64, error) {
|
|
row, err := normalizeRouteFailoverEvent(row)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
result, err := r.db.ExecContext(
|
|
ctx,
|
|
`INSERT INTO route_failover_events (
|
|
request_id,
|
|
logical_group_id,
|
|
public_model,
|
|
from_route_id,
|
|
to_route_id,
|
|
reason,
|
|
failure_count
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
row.RequestID,
|
|
row.LogicalGroupID,
|
|
row.PublicModel,
|
|
row.FromRouteID,
|
|
row.ToRouteID,
|
|
row.Reason,
|
|
row.FailureCount,
|
|
)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("insert route failover event %q: %w", row.RequestID, err)
|
|
}
|
|
|
|
id, err := result.LastInsertId()
|
|
if err != nil {
|
|
return 0, fmt.Errorf("read inserted route failover event id for %q: %w", row.RequestID, err)
|
|
}
|
|
return id, nil
|
|
}
|
|
|
|
func (r *RouteFailoverEventsRepo) ListRecent(ctx context.Context, filter RouteFailoverEventFilter) ([]RouteFailoverEvent, error) {
|
|
clauses := make([]string, 0, 5)
|
|
args := make([]any, 0, 6)
|
|
|
|
if requestID := strings.TrimSpace(filter.RequestID); requestID != "" {
|
|
clauses = append(clauses, "request_id = ?")
|
|
args = append(args, requestID)
|
|
}
|
|
if logicalGroupID := strings.TrimSpace(filter.LogicalGroupID); logicalGroupID != "" {
|
|
clauses = append(clauses, "logical_group_id = ?")
|
|
args = append(args, logicalGroupID)
|
|
}
|
|
if publicModel := strings.TrimSpace(filter.PublicModel); publicModel != "" {
|
|
clauses = append(clauses, "public_model = ?")
|
|
args = append(args, publicModel)
|
|
}
|
|
if fromRouteID := strings.TrimSpace(filter.FromRouteID); fromRouteID != "" {
|
|
clauses = append(clauses, "from_route_id = ?")
|
|
args = append(args, fromRouteID)
|
|
}
|
|
if toRouteID := strings.TrimSpace(filter.ToRouteID); toRouteID != "" {
|
|
clauses = append(clauses, "to_route_id = ?")
|
|
args = append(args, toRouteID)
|
|
}
|
|
|
|
query := `SELECT id, request_id, logical_group_id, public_model, from_route_id, to_route_id, reason, failure_count, created_at
|
|
FROM route_failover_events`
|
|
if len(clauses) > 0 {
|
|
query += " WHERE " + strings.Join(clauses, " AND ")
|
|
}
|
|
query += " ORDER BY id DESC LIMIT ?"
|
|
args = append(args, normalizeRouteLogListLimit(filter.Limit))
|
|
|
|
rows, err := r.db.QueryContext(ctx, query, args...)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("list route failover events: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
items := make([]RouteFailoverEvent, 0)
|
|
for rows.Next() {
|
|
var item RouteFailoverEvent
|
|
if err := rows.Scan(
|
|
&item.ID,
|
|
&item.RequestID,
|
|
&item.LogicalGroupID,
|
|
&item.PublicModel,
|
|
&item.FromRouteID,
|
|
&item.ToRouteID,
|
|
&item.Reason,
|
|
&item.FailureCount,
|
|
&item.CreatedAt,
|
|
); err != nil {
|
|
return nil, fmt.Errorf("scan route failover event: %w", err)
|
|
}
|
|
items = append(items, item)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, fmt.Errorf("iterate route failover events: %w", err)
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
func normalizeRouteFailoverEvent(row RouteFailoverEvent) (RouteFailoverEvent, error) {
|
|
row.RequestID = strings.TrimSpace(row.RequestID)
|
|
row.LogicalGroupID = strings.TrimSpace(row.LogicalGroupID)
|
|
row.PublicModel = strings.TrimSpace(row.PublicModel)
|
|
row.FromRouteID = strings.TrimSpace(row.FromRouteID)
|
|
row.ToRouteID = strings.TrimSpace(row.ToRouteID)
|
|
row.Reason = strings.TrimSpace(row.Reason)
|
|
|
|
switch {
|
|
case row.RequestID == "":
|
|
return RouteFailoverEvent{}, fmt.Errorf("request_id is required")
|
|
case row.LogicalGroupID == "":
|
|
return RouteFailoverEvent{}, fmt.Errorf("logical_group_id is required")
|
|
case row.PublicModel == "":
|
|
return RouteFailoverEvent{}, fmt.Errorf("public_model is required")
|
|
case row.FromRouteID == "":
|
|
return RouteFailoverEvent{}, fmt.Errorf("from_route_id is required")
|
|
case row.ToRouteID == "":
|
|
return RouteFailoverEvent{}, fmt.Errorf("to_route_id is required")
|
|
case row.Reason == "":
|
|
return RouteFailoverEvent{}, fmt.Errorf("reason is required")
|
|
case row.FailureCount < 0:
|
|
return RouteFailoverEvent{}, fmt.Errorf("failure_count must be >= 0")
|
|
}
|
|
|
|
return row, nil
|
|
}
|