update: logs and comments also ref refreshLoop method

This commit is contained in:
ameersohel45
2025-12-12 15:10:21 +05:30
parent 5feb84196c
commit 5843d2a760
2 changed files with 27 additions and 31 deletions

View File

@@ -48,7 +48,7 @@ type cachedDomainSchema struct {
// validateExtendedSchemas validates all objects with @context against their schemas. // validateExtendedSchemas validates all objects with @context against their schemas.
func (v *schemav2Validator) validateExtendedSchemas(ctx context.Context, body interface{}) error { func (v *schemav2Validator) validateExtendedSchemas(ctx context.Context, body interface{}) error {
// Extract "message" object - only scan inside message, not root // Extract "message" object - only scan inside message
bodyMap, ok := body.(map[string]interface{}) bodyMap, ok := body.(map[string]interface{})
if !ok { if !ok {
return fmt.Errorf("body is not a valid JSON object") return fmt.Errorf("body is not a valid JSON object")
@@ -291,28 +291,30 @@ func findReferencedObjects(data interface{}, path string) []referencedObject {
// transformContextToSchemaURL transforms @context URL to schema URL. // transformContextToSchemaURL transforms @context URL to schema URL.
func transformContextToSchemaURL(contextURL string) string { func transformContextToSchemaURL(contextURL string) string {
// Hardcoded transformation: context.jsonld -> attributes.yaml // transformation: context.jsonld -> attributes.yaml
return strings.Replace(contextURL, "context.jsonld", "attributes.yaml", 1) return strings.Replace(contextURL, "context.jsonld", "attributes.yaml", 1)
} }
// findSchemaByType finds a schema in the document by @type value. // findSchemaByType finds a schema in the document by @type value.
func findSchemaByType(doc *openapi3.T, typeName string) (*openapi3.SchemaRef, error) { func findSchemaByType(ctx context.Context, doc *openapi3.T, typeName string) (*openapi3.SchemaRef, error) {
if doc.Components == nil || doc.Components.Schemas == nil { if doc.Components == nil || doc.Components.Schemas == nil {
return nil, fmt.Errorf("no schemas found in document") return nil, fmt.Errorf("no schemas found in document")
} }
// Try direct match by schema name // Try direct match by schema name
if schema, exists := doc.Components.Schemas[typeName]; exists { if schema, exists := doc.Components.Schemas[typeName]; exists {
log.Debugf(ctx, "Found schema by direct match: %s", typeName)
return schema, nil return schema, nil
} }
// Fallback: Try x-jsonld.@type match // Fallback: Try x-jsonld.@type match
for _, schema := range doc.Components.Schemas { for name, schema := range doc.Components.Schemas {
if schema.Value == nil { if schema.Value == nil {
continue continue
} }
if xJsonld, ok := schema.Value.Extensions["x-jsonld"].(map[string]interface{}); ok { if xJsonld, ok := schema.Value.Extensions["x-jsonld"].(map[string]interface{}); ok {
if atType, ok := xJsonld["@type"].(string); ok && atType == typeName { if atType, ok := xJsonld["@type"].(string); ok && atType == typeName {
log.Debugf(ctx, "Found schema by x-jsonld.@type match: %s (mapped to %s)", typeName, name)
return schema, nil return schema, nil
} }
} }
@@ -358,7 +360,7 @@ func (c *schemaCache) validateReferencedObject(
} }
// Find schema by @type // Find schema by @type
schema, err := findSchemaByType(doc, obj.Type) schema, err := findSchemaByType(ctx, doc, obj.Type)
if err != nil { if err != nil {
log.Errorf(ctx, err, "Schema not found for @type: %s at path: %s", obj.Type, obj.Path) log.Errorf(ctx, err, "Schema not found for @type: %s at path: %s", obj.Type, obj.Path)
return fmt.Errorf("at %s: %w", obj.Path, err) return fmt.Errorf("at %s: %w", obj.Path, err)

View File

@@ -27,7 +27,7 @@ type schemav2Validator struct {
config *Config config *Config
spec *cachedSpec spec *cachedSpec
specMutex sync.RWMutex specMutex sync.RWMutex
schemaCache *schemaCache // NEW: cache for referenced schemas schemaCache *schemaCache // cache for extended schemas
} }
// cachedSpec holds a cached OpenAPI spec. // cachedSpec holds a cached OpenAPI spec.
@@ -43,7 +43,7 @@ type Config struct {
Location string // URL, file path, or directory path Location string // URL, file path, or directory path
CacheTTL int CacheTTL int
// NEW: Extended Schema configuration // Extended Schema configuration
EnableExtendedSchema bool EnableExtendedSchema bool
ExtendedSchemaConfig ExtendedSchemaConfig ExtendedSchemaConfig ExtendedSchemaConfig
} }
@@ -73,7 +73,7 @@ func New(ctx context.Context, config *Config) (*schemav2Validator, func() error,
config: config, config: config,
} }
// NEW: Initialize extended schema cache if enabled // Initialize extended schema cache if enabled
if config.EnableExtendedSchema { if config.EnableExtendedSchema {
maxSize := 100 maxSize := 100
if config.ExtendedSchemaConfig.MaxCacheSize > 0 { if config.ExtendedSchemaConfig.MaxCacheSize > 0 {
@@ -136,13 +136,13 @@ func (v *schemav2Validator) Validate(ctx context.Context, reqURL *url.URL, data
return v.formatValidationError(err) return v.formatValidationError(err)
} }
log.Debugf(ctx, "Core schema validation passed for action: %s", action) log.Debugf(ctx, "base schema validation passed for action: %s", action)
// NEW: Extended Schema validation (if enabled) // Extended Schema validation (if enabled)
if v.config.EnableExtendedSchema && v.schemaCache != nil { if v.config.EnableExtendedSchema && v.schemaCache != nil {
log.Debugf(ctx, "Starting Extended Schema validation for action: %s", action) log.Debugf(ctx, "Starting Extended Schema validation for action: %s", action)
if err := v.validateExtendedSchemas(ctx, jsonData); err != nil { if err := v.validateExtendedSchemas(ctx, jsonData); err != nil {
// Extended Schema failure - return error (same behavior as core schema) // Extended Schema failure - return error.
log.Debugf(ctx, "Extended Schema validation failed for action %s: %v", action, err) log.Debugf(ctx, "Extended Schema validation failed for action %s: %v", action, err)
return v.formatValidationError(err) return v.formatValidationError(err)
} }
@@ -214,8 +214,10 @@ func (v *schemav2Validator) refreshLoop(ctx context.Context) {
coreTicker := time.NewTicker(time.Duration(v.config.CacheTTL) * time.Second) coreTicker := time.NewTicker(time.Duration(v.config.CacheTTL) * time.Second)
defer coreTicker.Stop() defer coreTicker.Stop()
// NEW: Ticker for extended schema cleanup // Ticker for extended schema cleanup
var refTicker *time.Ticker var refTicker *time.Ticker
var refTickerCh <-chan time.Time // Default nil, blocks forever
if v.config.EnableExtendedSchema { if v.config.EnableExtendedSchema {
ttl := v.config.ExtendedSchemaConfig.CacheTTL ttl := v.config.ExtendedSchemaConfig.CacheTTL
if ttl <= 0 { if ttl <= 0 {
@@ -223,30 +225,22 @@ func (v *schemav2Validator) refreshLoop(ctx context.Context) {
} }
refTicker = time.NewTicker(time.Duration(ttl) * time.Second) refTicker = time.NewTicker(time.Duration(ttl) * time.Second)
defer refTicker.Stop() defer refTicker.Stop()
refTickerCh = refTicker.C
} }
for { for {
if refTicker != nil { select {
select { case <-ctx.Done():
case <-ctx.Done(): return
return case <-coreTicker.C:
case <-coreTicker.C: v.reloadExpiredSpec(ctx)
v.reloadExpiredSpec(ctx) case <-refTickerCh:
case <-refTicker.C: if v.schemaCache != nil {
if v.schemaCache != nil { count := v.schemaCache.cleanupExpired()
count := v.schemaCache.cleanupExpired() if count > 0 {
if count > 0 { log.Debugf(ctx, "Cleaned up %d expired extended schemas", count)
log.Debugf(ctx, "Cleaned up %d expired extended schemas", count)
}
} }
} }
} else {
select {
case <-ctx.Done():
return
case <-coreTicker.C:
v.reloadExpiredSpec(ctx)
}
} }
} }
} }