perf(go): cache realtime plate lookups

This commit is contained in:
lingniu
2026-07-03 07:42:24 +08:00
parent 9345fe60b5
commit 1c0d7dc03e
5 changed files with 124 additions and 2 deletions

View File

@@ -5,6 +5,7 @@ import (
"database/sql"
"errors"
"strings"
"sync"
"time"
"lingniu-vehicle-ingest/go/vehicle-gateway/internal/envelope"
@@ -18,6 +19,69 @@ type PlateResolver interface {
PlateByVIN(context.Context, string) (string, error)
}
type CachedPlateResolver struct {
delegate PlateResolver
ttl time.Duration
now func() time.Time
mu sync.Mutex
entries map[string]cachedPlateEntry
}
type cachedPlateEntry struct {
plate string
notFound bool
expiresAt time.Time
}
func NewCachedPlateResolver(delegate PlateResolver, ttl time.Duration) *CachedPlateResolver {
if delegate == nil {
panic("cached plate resolver delegate must not be nil")
}
if ttl <= 0 {
ttl = 10 * time.Minute
}
return &CachedPlateResolver{
delegate: delegate,
ttl: ttl,
now: time.Now,
entries: map[string]cachedPlateEntry{},
}
}
func (r *CachedPlateResolver) PlateByVIN(ctx context.Context, vin string) (string, error) {
vin = strings.TrimSpace(vin)
if vin == "" {
return "", sql.ErrNoRows
}
now := r.now()
r.mu.Lock()
entry, ok := r.entries[vin]
if ok && now.Before(entry.expiresAt) {
r.mu.Unlock()
if entry.notFound {
return "", sql.ErrNoRows
}
return entry.plate, nil
}
r.mu.Unlock()
plate, err := r.delegate.PlateByVIN(ctx, vin)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return "", err
}
r.mu.Lock()
r.entries[vin] = cachedPlateEntry{
plate: strings.TrimSpace(plate),
notFound: errors.Is(err, sql.ErrNoRows),
expiresAt: now.Add(r.ttl),
}
r.mu.Unlock()
if err != nil {
return "", err
}
return strings.TrimSpace(plate), nil
}
type SnapshotWriter struct {
exec SnapshotExecer
plateResolver PlateResolver