69 lines
1.5 KiB
Go
69 lines
1.5 KiB
Go
package stats
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"time"
|
|
|
|
"lingniu-vehicle-ingest/go/vehicle-gateway/internal/envelope"
|
|
)
|
|
|
|
type SourceIdentity struct {
|
|
Protocol envelope.Protocol
|
|
SourceIP string
|
|
SourceEndpoint string
|
|
}
|
|
|
|
func NewSourceIdentity(protocol envelope.Protocol, endpoint string) (SourceIdentity, bool) {
|
|
sourceIP := NormalizeSourceIP(endpoint)
|
|
if sourceIP == "" {
|
|
return SourceIdentity{}, false
|
|
}
|
|
return SourceIdentity{
|
|
Protocol: protocol,
|
|
SourceIP: sourceIP,
|
|
SourceEndpoint: strings.TrimSpace(endpoint),
|
|
}, true
|
|
}
|
|
|
|
func NormalizeSourceIP(endpoint string) string {
|
|
endpoint = strings.TrimSpace(endpoint)
|
|
if endpoint == "" {
|
|
return ""
|
|
}
|
|
if host, _, ok := strings.Cut(endpoint, ":"); ok {
|
|
return strings.TrimSpace(host)
|
|
}
|
|
return endpoint
|
|
}
|
|
|
|
func UpsertDataSource(ctx context.Context, exec Execer, identity SourceIdentity, now time.Time) error {
|
|
if exec == nil {
|
|
panic("stats execer must not be nil")
|
|
}
|
|
if identity.SourceIP == "" {
|
|
return nil
|
|
}
|
|
if now.IsZero() {
|
|
now = time.Now()
|
|
}
|
|
_, err := exec.ExecContext(ctx, upsertDataSourceSQL,
|
|
string(identity.Protocol),
|
|
identity.SourceIP,
|
|
identity.SourceEndpoint,
|
|
now,
|
|
now,
|
|
)
|
|
return err
|
|
}
|
|
|
|
const upsertDataSourceSQL = `
|
|
INSERT INTO vehicle_data_source
|
|
(protocol, source_ip, latest_source_endpoint, first_seen_at, latest_seen_at)
|
|
VALUES (?, ?, ?, ?, ?)
|
|
ON DUPLICATE KEY UPDATE
|
|
latest_source_endpoint = VALUES(latest_source_endpoint),
|
|
latest_seen_at = VALUES(latest_seen_at),
|
|
updated_at = CURRENT_TIMESTAMP
|
|
`
|