104 lines
2.8 KiB
Go
104 lines
2.8 KiB
Go
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
// SchemaMismatch represents a mismatch between expected and actual API response
|
|
type SchemaMismatch struct {
|
|
ModelName string
|
|
MissingFields []string
|
|
UnknownFields []string
|
|
UnknownValues map[string]any
|
|
Endpoint string
|
|
LibraryVersion string
|
|
}
|
|
|
|
func (sm *SchemaMismatch) Describe() string {
|
|
var parts []string
|
|
parts = append(parts, fmt.Sprintf("Model: %s", sm.ModelName))
|
|
if len(sm.MissingFields) > 0 {
|
|
parts = append(parts, fmt.Sprintf("Missing fields: %v", sm.MissingFields))
|
|
}
|
|
if len(sm.UnknownFields) > 0 {
|
|
parts = append(parts, fmt.Sprintf("Unknown fields: %v", sm.UnknownFields))
|
|
}
|
|
if len(sm.UnknownValues) > 0 {
|
|
parts = append(parts, fmt.Sprintf("Unknown field structures: %v", sm.UnknownValues))
|
|
}
|
|
parts = append(parts, fmt.Sprintf("Endpoint: %s", sm.Endpoint))
|
|
parts = append(parts, fmt.Sprintf("Library version: %s", sm.LibraryVersion))
|
|
return strings.Join(parts, "\n")
|
|
}
|
|
|
|
// SchemaMismatchHandler is a callback for handling schema mismatches
|
|
type SchemaMismatchHandler func(*SchemaMismatch)
|
|
|
|
// SchemaMismatchConfig holds configuration for schema mismatch handling
|
|
type SchemaMismatchConfig struct {
|
|
ReportUnknownFields bool
|
|
Strict bool
|
|
OnSchemaMismatch SchemaMismatchHandler
|
|
}
|
|
|
|
// DefaultSchemaMismatchConfig returns the default configuration
|
|
func DefaultSchemaMismatchConfig() SchemaMismatchConfig {
|
|
return SchemaMismatchConfig{
|
|
ReportUnknownFields: false,
|
|
Strict: false,
|
|
OnSchemaMismatch: nil,
|
|
}
|
|
}
|
|
|
|
// ReportSchemaMismatch reports a schema mismatch according to config
|
|
func ReportSchemaMismatch(config SchemaMismatchConfig, modelName, endpoint string, missingFields, unknownFields []string, unknownValues map[string]any) error {
|
|
mismatch := &SchemaMismatch{
|
|
ModelName: modelName,
|
|
MissingFields: missingFields,
|
|
UnknownFields: unknownFields,
|
|
UnknownValues: unknownValues,
|
|
Endpoint: endpoint,
|
|
LibraryVersion: "go-port-0.1.0",
|
|
}
|
|
|
|
if config.OnSchemaMismatch != nil {
|
|
config.OnSchemaMismatch(mismatch)
|
|
return nil
|
|
}
|
|
|
|
msg := mismatch.Describe()
|
|
if config.Strict {
|
|
return fmt.Errorf("schema mismatch: %s", msg)
|
|
}
|
|
|
|
log.Printf("WARNING: Schema mismatch for %s:\n%s", modelName, msg)
|
|
return nil
|
|
}
|
|
|
|
// SchemaMismatchTracker tracks reported mismatches to avoid duplicates
|
|
type SchemaMismatchTracker struct {
|
|
mu sync.Mutex
|
|
reported map[string]bool
|
|
}
|
|
|
|
func NewSchemaMismatchTracker() *SchemaMismatchTracker {
|
|
return &SchemaMismatchTracker{
|
|
reported: make(map[string]bool),
|
|
}
|
|
}
|
|
|
|
func (t *SchemaMismatchTracker) ShouldReport(modelName string, fields []string) bool {
|
|
t.mu.Lock()
|
|
defer t.mu.Unlock()
|
|
|
|
key := modelName + ":" + strings.Join(fields, ",")
|
|
if t.reported[key] {
|
|
return false
|
|
}
|
|
t.reported[key] = true
|
|
return true
|
|
}
|