Re-enabled JSON Parsing async channel

The channel is used by vacuum and the validator, it is required for schema validation. but it also slows things down considerably when done synchronously. I have moved this code back to async, it cuts parsing time in half for vaccum, and restores super speed.

Signed-off-by: quobix <dave@quobix.com>
This commit is contained in:
quobix
2023-11-09 06:30:13 -05:00
parent 6a6d6d6e31
commit 8b9ef11270
2 changed files with 38 additions and 24 deletions

View File

@@ -101,6 +101,7 @@ func ExtractSpecInfoWithDocumentCheck(spec []byte, bypass bool) (*SpecInfo, erro
spec.APISchema = OpenAPI2SchemaData spec.APISchema = OpenAPI2SchemaData
} }
go func() {
if utils.IsYAML(string(bytes)) { if utils.IsYAML(string(bytes)) {
_ = parsedNode.Decode(&jsonSpec) _ = parsedNode.Decode(&jsonSpec)
b, _ := json.Marshal(&jsonSpec) b, _ := json.Marshal(&jsonSpec)
@@ -111,7 +112,8 @@ func ExtractSpecInfoWithDocumentCheck(spec []byte, bypass bool) (*SpecInfo, erro
spec.SpecJSONBytes = &bytes spec.SpecJSONBytes = &bytes
spec.SpecJSON = &jsonSpec spec.SpecJSON = &jsonSpec
} }
close(spec.JsonParsingChannel) // this needs removing at some point close(spec.JsonParsingChannel)
}()
} }
if !bypass { if !bypass {
@@ -177,11 +179,12 @@ func ExtractSpecInfoWithDocumentCheck(spec []byte, bypass bool) (*SpecInfo, erro
if specInfo.SpecType == "" { if specInfo.SpecType == "" {
// parse JSON // parse JSON
parseJSON(spec, specInfo, &parsedSpec) go parseJSON(spec, specInfo, &parsedSpec)
specInfo.Error = errors.New("spec type not supported by libopenapi, sorry") specInfo.Error = errors.New("spec type not supported by libopenapi, sorry")
return specInfo, specInfo.Error return specInfo, specInfo.Error
} }
} else { } else {
go func() {
var jsonSpec map[string]interface{} var jsonSpec map[string]interface{}
if utils.IsYAML(string(spec)) { if utils.IsYAML(string(spec)) {
_ = parsedSpec.Decode(&jsonSpec) _ = parsedSpec.Decode(&jsonSpec)
@@ -194,6 +197,7 @@ func ExtractSpecInfoWithDocumentCheck(spec []byte, bypass bool) (*SpecInfo, erro
specInfo.SpecJSON = &jsonSpec specInfo.SpecJSON = &jsonSpec
} }
close(specInfo.JsonParsingChannel) // this needs removing at some point close(specInfo.JsonParsingChannel) // this needs removing at some point
}()
} }
// detect the original whitespace indentation // detect the original whitespace indentation

View File

@@ -116,6 +116,7 @@ info:
func TestExtractSpecInfo_ValidJSON(t *testing.T) { func TestExtractSpecInfo_ValidJSON(t *testing.T) {
r, e := ExtractSpecInfo([]byte(goodJSON)) r, e := ExtractSpecInfo([]byte(goodJSON))
<-r.JsonParsingChannel
assert.Greater(t, len(*r.SpecJSONBytes), 0) assert.Greater(t, len(*r.SpecJSONBytes), 0)
assert.Error(t, e) assert.Error(t, e)
} }
@@ -132,6 +133,7 @@ func TestExtractSpecInfo_Nothing(t *testing.T) {
func TestExtractSpecInfo_ValidYAML(t *testing.T) { func TestExtractSpecInfo_ValidYAML(t *testing.T) {
r, e := ExtractSpecInfo([]byte(goodYAML)) r, e := ExtractSpecInfo([]byte(goodYAML))
<-r.JsonParsingChannel
assert.Greater(t, len(*r.SpecJSONBytes), 0) assert.Greater(t, len(*r.SpecJSONBytes), 0)
assert.Error(t, e) assert.Error(t, e)
} }
@@ -149,6 +151,7 @@ func TestExtractSpecInfo_InvalidOpenAPIVersion(t *testing.T) {
func TestExtractSpecInfo_OpenAPI3(t *testing.T) { func TestExtractSpecInfo_OpenAPI3(t *testing.T) {
r, e := ExtractSpecInfo([]byte(OpenApi3Spec)) r, e := ExtractSpecInfo([]byte(OpenApi3Spec))
<-r.JsonParsingChannel
assert.Nil(t, e) assert.Nil(t, e)
assert.Equal(t, utils.OpenApi3, r.SpecType) assert.Equal(t, utils.OpenApi3, r.SpecType)
assert.Equal(t, "3.0.1", r.Version) assert.Equal(t, "3.0.1", r.Version)
@@ -159,6 +162,7 @@ func TestExtractSpecInfo_OpenAPI3(t *testing.T) {
func TestExtractSpecInfo_OpenAPIWat(t *testing.T) { func TestExtractSpecInfo_OpenAPIWat(t *testing.T) {
r, e := ExtractSpecInfo([]byte(OpenApiWat)) r, e := ExtractSpecInfo([]byte(OpenApiWat))
<-r.JsonParsingChannel
assert.Nil(t, e) assert.Nil(t, e)
assert.Equal(t, OpenApi3, r.SpecType) assert.Equal(t, OpenApi3, r.SpecType)
assert.Equal(t, "3.2", r.Version) assert.Equal(t, "3.2", r.Version)
@@ -167,6 +171,7 @@ func TestExtractSpecInfo_OpenAPIWat(t *testing.T) {
func TestExtractSpecInfo_OpenAPI31(t *testing.T) { func TestExtractSpecInfo_OpenAPI31(t *testing.T) {
r, e := ExtractSpecInfo([]byte(OpenApi31)) r, e := ExtractSpecInfo([]byte(OpenApi31))
<-r.JsonParsingChannel
assert.Nil(t, e) assert.Nil(t, e)
assert.Equal(t, OpenApi3, r.SpecType) assert.Equal(t, OpenApi3, r.SpecType)
assert.Equal(t, "3.1", r.Version) assert.Equal(t, "3.1", r.Version)
@@ -183,6 +188,7 @@ why:
yes: no` yes: no`
r, e := ExtractSpecInfoWithDocumentCheck([]byte(random), true) r, e := ExtractSpecInfoWithDocumentCheck([]byte(random), true)
<-r.JsonParsingChannel
assert.Nil(t, e) assert.Nil(t, e)
assert.NotNil(t, r.RootNode) assert.NotNil(t, r.RootNode)
assert.Equal(t, "something", r.RootNode.Content[0].Content[0].Value) assert.Equal(t, "something", r.RootNode.Content[0].Content[0].Value)
@@ -194,6 +200,7 @@ func TestExtractSpecInfo_AnyDocument_JSON(t *testing.T) {
random := `{ "something" : "yeah"}` random := `{ "something" : "yeah"}`
r, e := ExtractSpecInfoWithDocumentCheck([]byte(random), true) r, e := ExtractSpecInfoWithDocumentCheck([]byte(random), true)
<-r.JsonParsingChannel
assert.Nil(t, e) assert.Nil(t, e)
assert.NotNil(t, r.RootNode) assert.NotNil(t, r.RootNode)
assert.Equal(t, "something", r.RootNode.Content[0].Content[0].Value) assert.Equal(t, "something", r.RootNode.Content[0].Content[0].Value)
@@ -212,6 +219,7 @@ why:
r, e := ExtractSpecInfoWithConfig([]byte(random), &DocumentConfiguration{ r, e := ExtractSpecInfoWithConfig([]byte(random), &DocumentConfiguration{
BypassDocumentCheck: true, BypassDocumentCheck: true,
}) })
<-r.JsonParsingChannel
assert.Nil(t, e) assert.Nil(t, e)
assert.NotNil(t, r.RootNode) assert.NotNil(t, r.RootNode)
assert.Equal(t, "something", r.RootNode.Content[0].Content[0].Value) assert.Equal(t, "something", r.RootNode.Content[0].Content[0].Value)
@@ -228,6 +236,7 @@ func TestExtractSpecInfo_OpenAPIFalse(t *testing.T) {
func TestExtractSpecInfo_OpenAPI2(t *testing.T) { func TestExtractSpecInfo_OpenAPI2(t *testing.T) {
r, e := ExtractSpecInfo([]byte(OpenApi2Spec)) r, e := ExtractSpecInfo([]byte(OpenApi2Spec))
<-r.JsonParsingChannel
assert.Nil(t, e) assert.Nil(t, e)
assert.Equal(t, OpenApi2, r.SpecType) assert.Equal(t, OpenApi2, r.SpecType)
assert.Equal(t, "2.0.1", r.Version) assert.Equal(t, "2.0.1", r.Version)
@@ -246,6 +255,7 @@ func TestExtractSpecInfo_OpenAPI2_OddVersion(t *testing.T) {
func TestExtractSpecInfo_AsyncAPI(t *testing.T) { func TestExtractSpecInfo_AsyncAPI(t *testing.T) {
r, e := ExtractSpecInfo([]byte(AsyncAPISpec)) r, e := ExtractSpecInfo([]byte(AsyncAPISpec))
<-r.JsonParsingChannel
assert.Nil(t, e) assert.Nil(t, e)
assert.Equal(t, AsyncApi, r.SpecType) assert.Equal(t, AsyncApi, r.SpecType)
assert.Equal(t, "2.0.0", r.Version) assert.Equal(t, "2.0.0", r.Version)