mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-09 20:47:44 +00:00
Implement TranslatePipeline() as generalized concurrent map iterator.
Integrate `TranslatePipeline()` into datamodel for schema components to replace specialized async logic.
This commit is contained in:
@@ -4,6 +4,9 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
"github.com/pb33f/libopenapi/datamodel/high"
|
||||
highbase "github.com/pb33f/libopenapi/datamodel/high/base"
|
||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||
@@ -12,18 +15,6 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// used for internal channel co-ordination for building out different component types.
|
||||
const (
|
||||
responses = iota
|
||||
parameters
|
||||
examples
|
||||
requestBodies
|
||||
headers
|
||||
securitySchemes
|
||||
links
|
||||
callbacks
|
||||
)
|
||||
|
||||
// Components represents a high-level OpenAPI 3+ Components Object, that is backed by a low-level one.
|
||||
//
|
||||
// Holds a set of reusable objects for different aspects of the OAS. All objects defined within the components object
|
||||
@@ -61,83 +52,48 @@ func NewComponents(comp *low.Components) *Components {
|
||||
headerMap := make(map[string]*Header)
|
||||
securitySchemeMap := make(map[string]*SecurityScheme)
|
||||
schemas := make(map[string]*highbase.SchemaProxy)
|
||||
schemaChan := make(chan componentResult[*highbase.SchemaProxy])
|
||||
cbChan := make(chan componentResult[*Callback])
|
||||
linkChan := make(chan componentResult[*Link])
|
||||
responseChan := make(chan componentResult[*Response])
|
||||
paramChan := make(chan componentResult[*Parameter])
|
||||
exampleChan := make(chan componentResult[*highbase.Example])
|
||||
requestBodyChan := make(chan componentResult[*RequestBody])
|
||||
headerChan := make(chan componentResult[*Header])
|
||||
securitySchemeChan := make(chan componentResult[*SecurityScheme])
|
||||
|
||||
// build all components asynchronously.
|
||||
for k, v := range comp.Callbacks.Value {
|
||||
go buildComponent[*Callback, *low.Callback](callbacks, k.Value, v.Value, cbChan, NewCallback)
|
||||
}
|
||||
for k, v := range comp.Links.Value {
|
||||
go buildComponent[*Link, *low.Link](links, k.Value, v.Value, linkChan, NewLink)
|
||||
}
|
||||
for k, v := range comp.Responses.Value {
|
||||
go buildComponent[*Response, *low.Response](responses, k.Value, v.Value, responseChan, NewResponse)
|
||||
}
|
||||
for k, v := range comp.Parameters.Value {
|
||||
go buildComponent[*Parameter, *low.Parameter](parameters, k.Value, v.Value, paramChan, NewParameter)
|
||||
}
|
||||
for k, v := range comp.Examples.Value {
|
||||
go buildComponent[*highbase.Example, *base.Example](examples, k.Value, v.Value, exampleChan, highbase.NewExample)
|
||||
}
|
||||
for k, v := range comp.RequestBodies.Value {
|
||||
go buildComponent[*RequestBody, *low.RequestBody](requestBodies, k.Value, v.Value,
|
||||
requestBodyChan, NewRequestBody)
|
||||
}
|
||||
for k, v := range comp.Headers.Value {
|
||||
go buildComponent[*Header, *low.Header](headers, k.Value, v.Value, headerChan, NewHeader)
|
||||
}
|
||||
for k, v := range comp.SecuritySchemes.Value {
|
||||
go buildComponent[*SecurityScheme, *low.SecurityScheme](securitySchemes, k.Value, v.Value,
|
||||
securitySchemeChan, NewSecurityScheme)
|
||||
}
|
||||
for k, v := range comp.Schemas.Value {
|
||||
go buildSchema(k, v, schemaChan)
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(9)
|
||||
go func() {
|
||||
buildComponent[*low.Callback, *Callback](comp.Callbacks.Value, cbMap, NewCallback)
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
buildComponent[*low.Link, *Link](comp.Links.Value, linkMap, NewLink)
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
buildComponent[*low.Response, *Response](comp.Responses.Value, responseMap, NewResponse)
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
buildComponent[*low.Parameter, *Parameter](comp.Parameters.Value, parameterMap, NewParameter)
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
buildComponent[*base.Example, *highbase.Example](comp.Examples.Value, exampleMap, highbase.NewExample)
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
buildComponent[*low.RequestBody, *RequestBody](comp.RequestBodies.Value, requestBodyMap, NewRequestBody)
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
buildComponent[*low.Header, *Header](comp.Headers.Value, headerMap, NewHeader)
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
buildComponent[*low.SecurityScheme, *SecurityScheme](comp.SecuritySchemes.Value, securitySchemeMap, NewSecurityScheme)
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
buildSchema(comp.Schemas.Value, schemas)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
totalComponents := len(comp.Callbacks.Value) + len(comp.Links.Value) + len(comp.Responses.Value) +
|
||||
len(comp.Parameters.Value) + len(comp.Examples.Value) + len(comp.RequestBodies.Value) +
|
||||
len(comp.Headers.Value) + len(comp.SecuritySchemes.Value) + len(comp.Schemas.Value)
|
||||
|
||||
processedComponents := 0
|
||||
for processedComponents < totalComponents {
|
||||
select {
|
||||
case sRes := <-schemaChan:
|
||||
processedComponents++
|
||||
schemas[sRes.key] = sRes.res
|
||||
case cbRes := <-cbChan:
|
||||
processedComponents++
|
||||
cbMap[cbRes.key] = cbRes.res
|
||||
case lRes := <-linkChan:
|
||||
processedComponents++
|
||||
linkMap[lRes.key] = lRes.res
|
||||
case respRes := <-responseChan:
|
||||
processedComponents++
|
||||
responseMap[respRes.key] = respRes.res
|
||||
case pRes := <-paramChan:
|
||||
processedComponents++
|
||||
parameterMap[pRes.key] = pRes.res
|
||||
case eRes := <-exampleChan:
|
||||
processedComponents++
|
||||
exampleMap[eRes.key] = eRes.res
|
||||
case rbRes := <-requestBodyChan:
|
||||
processedComponents++
|
||||
requestBodyMap[rbRes.key] = rbRes.res
|
||||
case hRes := <-headerChan:
|
||||
processedComponents++
|
||||
headerMap[hRes.key] = hRes.res
|
||||
case ssRes := <-securitySchemeChan:
|
||||
processedComponents++
|
||||
securitySchemeMap[ssRes.key] = ssRes.res
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
c.Schemas = schemas
|
||||
c.Callbacks = cbMap
|
||||
c.Links = linkMap
|
||||
@@ -157,20 +113,33 @@ type componentResult[T any] struct {
|
||||
comp int
|
||||
}
|
||||
|
||||
// build out a component.
|
||||
func buildComponent[N any, O any](comp int, key string, orig O, c chan componentResult[N], f func(O) N) {
|
||||
c <- componentResult[N]{comp: comp, res: f(orig), key: key}
|
||||
// buildComponent builds component structs from low level structs.
|
||||
func buildComponent[IN any, OUT any](inMap map[lowmodel.KeyReference[string]]lowmodel.ValueReference[IN], outMap map[string]OUT, translateItem func(IN) OUT) {
|
||||
translateFunc := func(key lowmodel.KeyReference[string], value lowmodel.ValueReference[IN]) (componentResult[OUT], error) {
|
||||
return componentResult[OUT]{key: key.Value, res: translateItem(value.Value)}, nil
|
||||
}
|
||||
resultFunc := func(value componentResult[OUT]) error {
|
||||
outMap[value.key] = value.res
|
||||
return nil
|
||||
}
|
||||
_ = datamodel.TranslateMapParallel(inMap, translateFunc, resultFunc)
|
||||
}
|
||||
|
||||
// build out a schema
|
||||
func buildSchema(key lowmodel.KeyReference[string], orig lowmodel.ValueReference[*base.SchemaProxy],
|
||||
c chan componentResult[*highbase.SchemaProxy]) {
|
||||
var sch *highbase.SchemaProxy
|
||||
sch = highbase.NewSchemaProxy(&lowmodel.NodeReference[*base.SchemaProxy]{
|
||||
Value: orig.Value,
|
||||
ValueNode: orig.ValueNode,
|
||||
})
|
||||
c <- componentResult[*highbase.SchemaProxy]{res: sch, key: key.Value}
|
||||
// buildSchema builds a schema from low level structs.
|
||||
func buildSchema(inMap map[lowmodel.KeyReference[string]]lowmodel.ValueReference[*base.SchemaProxy], outMap map[string]*highbase.SchemaProxy) {
|
||||
translateFunc := func(key lowmodel.KeyReference[string], value lowmodel.ValueReference[*base.SchemaProxy]) (componentResult[*highbase.SchemaProxy], error) {
|
||||
var sch *highbase.SchemaProxy
|
||||
sch = highbase.NewSchemaProxy(&lowmodel.NodeReference[*base.SchemaProxy]{
|
||||
Value: value.Value,
|
||||
ValueNode: value.ValueNode,
|
||||
})
|
||||
return componentResult[*highbase.SchemaProxy]{res: sch, key: key.Value}, nil
|
||||
}
|
||||
resultFunc := func(value componentResult[*highbase.SchemaProxy]) error {
|
||||
outMap[value.key] = value.res
|
||||
return nil
|
||||
}
|
||||
_ = datamodel.TranslateMapParallel(inMap, translateFunc, resultFunc)
|
||||
}
|
||||
|
||||
// GoLow returns the low-level Components instance used to create the high-level one.
|
||||
|
||||
Reference in New Issue
Block a user