Skip to content

Commit c3f0207

Browse files
Cache YAML Nodes
1 parent cadff75 commit c3f0207

4 files changed

Lines changed: 28 additions & 7 deletions

File tree

cache/cache.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package cache
66
import (
77
"github.com/pb33f/libopenapi/datamodel/high/base"
88
"github.com/santhosh-tekuri/jsonschema/v6"
9+
"go.yaml.in/yaml/v4"
910
)
1011

1112
// SchemaCacheEntry holds a compiled schema and its intermediate representations.
@@ -16,6 +17,7 @@ type SchemaCacheEntry struct {
1617
ReferenceSchema string // String version of RenderedInline
1718
RenderedJSON []byte
1819
CompiledSchema *jsonschema.Schema
20+
RenderedNode *yaml.Node
1921
}
2022

2123
// SchemaCache defines the interface for schema caching implementations.

requests/validate_request.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
4747
var renderedSchema, jsonSchema []byte
4848
var referenceSchema string
4949
var compiledSchema *jsonschema.Schema
50+
var cachedNode *yaml.Node
5051

5152
if input.Schema == nil {
5253
return false, []*errors.ValidationError{{
@@ -71,7 +72,7 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
7172
referenceSchema = cached.ReferenceSchema
7273
jsonSchema = cached.RenderedJSON
7374
compiledSchema = cached.CompiledSchema
74-
}
75+
cachedNode = cached.RenderedNode
7576
}
7677

7778
// Cache miss or no cache - render and compile
@@ -229,9 +230,12 @@ func ValidateRequestSchema(input *ValidateRequestSchemaInput) (bool, []*errors.V
229230
schFlatErrs := jk.BasicOutput().Errors
230231
var schemaValidationErrors []*errors.SchemaValidationFailure
231232

232-
// re-encode the schema.
233-
var renderedNode yaml.Node
234-
_ = yaml.Unmarshal(renderedSchema, &renderedNode)
233+
// Use cached node if available, otherwise parse
234+
renderedNode := cachedNode
235+
if renderedNode == nil {
236+
renderedNode = new(yaml.Node)
237+
_ = yaml.Unmarshal(renderedSchema, renderedNode)
238+
}
235239
for q := range schFlatErrs {
236240
er := schFlatErrs[q]
237241

responses/validate_response.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
5151
var renderedSchema, jsonSchema []byte
5252
var referenceSchema string
5353
var compiledSchema *jsonschema.Schema
54+
var cachedNode *yaml.Node
5455

5556
if input.Schema == nil {
5657
return false, []*errors.ValidationError{{
@@ -74,6 +75,7 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
7475
renderedSchema = cached.RenderedInline
7576
referenceSchema = cached.ReferenceSchema
7677
compiledSchema = cached.CompiledSchema
78+
cachedNode = cached.RenderedNode
7779
}
7880
}
7981

@@ -247,9 +249,11 @@ func ValidateResponseSchema(input *ValidateResponseSchemaInput) (bool, []*errors
247249
schFlatErrs := jk.BasicOutput().Errors
248250
var schemaValidationErrors []*errors.SchemaValidationFailure
249251

250-
// re-encode the schema once for error reporting
251-
var renderedNode yaml.Node
252-
_ = yaml.Unmarshal(renderedSchema, &renderedNode)
252+
renderedNode := cachedNode
253+
if renderedNode == nil {
254+
renderedNode = new(yaml.Node)
255+
_ = yaml.Unmarshal(renderedSchema, renderedNode)
256+
}
253257

254258
for q := range schFlatErrs {
255259
er := schFlatErrs[q]

validator.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/pb33f/libopenapi"
1313
"github.com/pb33f/libopenapi/datamodel/high/base"
1414
"github.com/pb33f/libopenapi/utils"
15+
"go.yaml.in/yaml/v4"
1516

1617
v3 "github.com/pb33f/libopenapi/datamodel/high/v3"
1718

@@ -491,12 +492,17 @@ func warmMediaTypeSchema(mediaType *v3.MediaType, schemaCache cache.SchemaCache,
491492
if len(renderedInline) > 0 {
492493
compiledSchema, _ := helpers.NewCompiledSchema(fmt.Sprintf("%x", hash), renderedJSON, options)
493494

495+
// Pre-parse YAML node for error reporting (avoids re-parsing on each error)
496+
var renderedNode yaml.Node
497+
_ = yaml.Unmarshal(renderedInline, &renderedNode)
498+
494499
schemaCache.Store(hash, &cache.SchemaCacheEntry{
495500
Schema: schema,
496501
RenderedInline: renderedInline,
497502
ReferenceSchema: referenceSchema,
498503
RenderedJSON: renderedJSON,
499504
CompiledSchema: compiledSchema,
505+
RenderedNode: &renderedNode,
500506
})
501507
}
502508
}
@@ -539,13 +545,18 @@ func warmParameterSchema(param *v3.Parameter, schemaCache cache.SchemaCache, opt
539545
if len(renderedInline) > 0 {
540546
compiledSchema, _ := helpers.NewCompiledSchema(fmt.Sprintf("%x", hash), renderedJSON, options)
541547

548+
// Pre-parse YAML node for error reporting (avoids re-parsing on each error)
549+
var renderedNode yaml.Node
550+
_ = yaml.Unmarshal(renderedInline, &renderedNode)
551+
542552
// Store in cache using the shared SchemaCache type
543553
schemaCache.Store(hash, &cache.SchemaCacheEntry{
544554
Schema: schema,
545555
RenderedInline: renderedInline,
546556
ReferenceSchema: referenceSchema,
547557
RenderedJSON: renderedJSON,
548558
CompiledSchema: compiledSchema,
559+
RenderedNode: &renderedNode,
549560
})
550561
}
551562
}

0 commit comments

Comments
 (0)