Files
yandex-music-api-go/internal/utils/schema.go
T
MrixsandClaude Code 7a68ad86cb Add package-level godoc documentation
- models: Package doc comment describing data models with DeJSON/DeList
- utils: Package doc comment for utility functions (JSON, signing, schema mismatch, errors)
- ynison: Package doc comment for Ynison WebSocket client protocol

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-18 08:39:50 +03:00

106 lines
2.9 KiB
Go

// Package utils provides utility functions for the Yandex Music API client,
// including JSON handling, request signing, schema mismatch tracking, and error types.
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
}