@@ -144,7 +144,6 @@ func (s *SchemaChanges) TotalChanges() int {
144144 if s == nil {
145145 return 0
146146 }
147-
148147 t := s .PropertyChanges .TotalChanges ()
149148 if s .DiscriminatorChanges != nil {
150149 t += s .DiscriminatorChanges .TotalChanges ()
@@ -230,7 +229,6 @@ func (s *SchemaChanges) TotalBreakingChanges() int {
230229 if s == nil {
231230 return 0
232231 }
233-
234232 t := s .PropertyChanges .TotalBreakingChanges ()
235233 if s .DiscriminatorChanges != nil {
236234 t += s .DiscriminatorChanges .TotalBreakingChanges ()
@@ -391,32 +389,35 @@ func CompareSchemas(l, r *base.SchemaProxy) *SchemaChanges {
391389
392390 // now for the confusing part, there is also a schema's 'properties' property to parse.
393391 // inception, eat your heart out.
394- doneChan := make (chan struct {})
395- props , totalProperties := checkMappedSchemaOfASchema (lSchema .Properties .Value , rSchema .Properties .Value , & changes , doneChan )
392+ props := checkMappedSchemaOfASchema (lSchema .Properties .Value , rSchema .Properties .Value , & changes )
396393 sc .SchemaPropertyChanges = props
397394
398- deps , depsTotal := checkMappedSchemaOfASchema (lSchema .DependentSchemas .Value , rSchema .DependentSchemas .Value , & changes , doneChan )
395+ deps := checkMappedSchemaOfASchema (lSchema .DependentSchemas .Value , rSchema .DependentSchemas .Value , & changes )
399396 sc .DependentSchemasChanges = deps
400397
401- patterns , patternsTotal := checkMappedSchemaOfASchema (lSchema .PatternProperties .Value , rSchema .PatternProperties .Value , & changes , doneChan )
398+ patterns := checkMappedSchemaOfASchema (lSchema .PatternProperties .Value , rSchema .PatternProperties .Value , & changes )
402399 sc .PatternPropertiesChanges = patterns
403400
404- // check polymorphic and multi-values async for speed.
405- go extractSchemaChanges (lSchema .OneOf .Value , rSchema .OneOf .Value , v3 .OneOfLabel ,
406- & sc .OneOfChanges , & changes , doneChan )
407-
408- go extractSchemaChanges (lSchema .AllOf .Value , rSchema .AllOf .Value , v3 .AllOfLabel ,
409- & sc .AllOfChanges , & changes , doneChan )
410-
411- go extractSchemaChanges (lSchema .AnyOf .Value , rSchema .AnyOf .Value , v3 .AnyOfLabel ,
412- & sc .AnyOfChanges , & changes , doneChan )
401+ var wg sync.WaitGroup
402+ wg .Add (3 )
403+ go func () {
404+ extractSchemaChanges (lSchema .OneOf .Value , rSchema .OneOf .Value , v3 .OneOfLabel ,
405+ & sc .OneOfChanges , & changes )
406+ wg .Done ()
407+
408+ }()
409+ go func () {
410+ extractSchemaChanges (lSchema .AllOf .Value , rSchema .AllOf .Value , v3 .AllOfLabel ,
411+ & sc .AllOfChanges , & changes )
412+ wg .Done ()
413+ }()
414+ go func () {
415+ extractSchemaChanges (lSchema .AnyOf .Value , rSchema .AnyOf .Value , v3 .AnyOfLabel ,
416+ & sc .AnyOfChanges , & changes )
417+ wg .Done ()
418+ }()
419+ wg .Wait ()
413420
414- totalChecks := totalProperties + depsTotal + patternsTotal + 3
415- completedChecks := 0
416- for completedChecks < totalChecks {
417- <- doneChan
418- completedChecks ++
419- }
420421 }
421422 // done
422423 if changes != nil {
@@ -454,10 +455,8 @@ func checkMappedSchemaOfASchema(
454455 lSchema ,
455456 rSchema * orderedmap.Map [low.KeyReference [string ], low.ValueReference [* base.SchemaProxy ]],
456457 changes * []* Change ,
457- doneChan chan struct {},
458- ) (map [string ]* SchemaChanges , int ) {
459- propChanges := make (map [string ]* SchemaChanges )
460-
458+ ) map [string ]* SchemaChanges {
459+ var syncPropChanges sync.Map // concurrent-safe map
461460 var lProps []string
462461 lEntities := make (map [string ]* base.SchemaProxy )
463462 lKeyNodes := make (map [string ]* yaml.Node )
@@ -477,42 +476,43 @@ func checkMappedSchemaOfASchema(
477476 }
478477 sort .Strings (lProps )
479478 sort .Strings (rProps )
480- totalProperties := buildProperty (lProps , rProps , lEntities , rEntities , propChanges , doneChan , changes , rKeyNodes , lKeyNodes )
481- return propChanges , totalProperties
479+ buildProperty (lProps , rProps , lEntities , rEntities , & syncPropChanges , changes , rKeyNodes , lKeyNodes )
480+
481+ // Convert the sync.Map into a regular map[string]*SchemaChanges.
482+ propChanges := make (map [string ]* SchemaChanges )
483+ syncPropChanges .Range (func (key , value interface {}) bool {
484+ propChanges [key .(string )] = value .(* SchemaChanges )
485+ return true
486+ })
487+ return propChanges
482488}
483489
484490func buildProperty (lProps , rProps []string , lEntities , rEntities map [string ]* base.SchemaProxy ,
485- propChanges map [string ]* SchemaChanges , doneChan chan struct {}, changes * []* Change , rKeyNodes , lKeyNodes map [string ]* yaml.Node ,
486- ) int {
487- var propLock sync.Mutex
488- checkProperty := func (key string , lp , rp * base.SchemaProxy , propChanges map [string ]* SchemaChanges , done chan struct {}) {
489- if lp != nil && rp != nil {
490- if low .AreEqual (lp , rp ) {
491- done <- struct {}{}
492- return
493- }
494- s := CompareSchemas (lp , rp )
495- propLock .Lock ()
496- propChanges [key ] = s
497- propLock .Unlock ()
498- done <- struct {}{}
491+ propChanges * sync.Map , changes * []* Change , rKeyNodes , lKeyNodes map [string ]* yaml.Node ,
492+ ) {
493+ var wg sync.WaitGroup
494+ checkProperty := func (key string , lp , rp * base.SchemaProxy ) {
495+ defer wg .Done ()
496+ if low .AreEqual (lp , rp ) {
497+ return
499498 }
499+ s := CompareSchemas (lp , rp )
500+ propChanges .Store (key , s )
500501 }
501502
502- totalProperties := 0
503+ // left and right equal.
503504 if len (lProps ) == len (rProps ) {
504505 for w := range lProps {
505506 lp := lEntities [lProps [w ]]
506507 rp := rEntities [rProps [w ]]
507508 if lProps [w ] == rProps [w ] && lp != nil && rp != nil {
508- totalProperties ++
509- go checkProperty (lProps [w ], lp , rp , propChanges , doneChan )
509+ wg . Add ( 1 )
510+ go checkProperty (lProps [w ], lp , rp )
510511 }
511-
512- // keys do not match, even after sorting, check which one was added and which one was removed.
512+ // Handle keys that do not match.
513513 if lProps [w ] != rProps [w ] {
514514 if ! slices .Contains (lProps , rProps [w ]) {
515- // new added.
515+ // new property added.
516516 CreateChange (changes , ObjectAdded , v3 .PropertiesLabel ,
517517 nil , rKeyNodes [rProps [w ]], false , nil , rEntities [rProps [w ]])
518518 }
@@ -522,63 +522,61 @@ func buildProperty(lProps, rProps []string, lEntities, rEntities map[string]*bas
522522 }
523523 if slices .Contains (lProps , rProps [w ]) {
524524 h := slices .Index (lProps , rProps [w ])
525- totalProperties ++
526525 lp = lEntities [lProps [h ]]
527526 rp = rEntities [rProps [w ]]
528- go checkProperty (lProps [h ], lp , rp , propChanges , doneChan )
527+ wg .Add (1 )
528+ go checkProperty (lProps [h ], lp , rp )
529529 }
530530 }
531531 }
532532 }
533533
534- // something removed
534+ // things removed
535535 if len (lProps ) > len (rProps ) {
536536 for w := range lProps {
537537 if rEntities [lProps [w ]] != nil {
538- totalProperties ++
539- go checkProperty (lProps [w ], lEntities [lProps [w ]], rEntities [lProps [w ]], propChanges , doneChan )
540- continue
538+ wg .Add (1 )
539+ go checkProperty (lProps [w ], lEntities [lProps [w ]], rEntities [lProps [w ]])
541540 } else {
542541 CreateChange (changes , ObjectRemoved , v3 .PropertiesLabel ,
543542 lKeyNodes [lProps [w ]], nil , true , lEntities [lProps [w ]], nil )
544- continue
545543 }
546544 }
547545 for w := range rProps {
548546 if lEntities [rProps [w ]] != nil {
549- go checkProperty (rProps [w ], lEntities [rProps [w ]], rEntities [rProps [w ]], propChanges , doneChan )
547+ wg .Add (1 )
548+ go checkProperty (rProps [w ], lEntities [rProps [w ]], rEntities [rProps [w ]])
550549 } else {
551550 CreateChange (changes , ObjectAdded , v3 .PropertiesLabel ,
552551 nil , rKeyNodes [rProps [w ]], false , nil , rEntities [rProps [w ]])
553- continue
554552 }
555553 }
556554 }
557555
558- // something added
556+ // stuff added
559557 if len (rProps ) > len (lProps ) {
560558 for w := range rProps {
561559 if lEntities [rProps [w ]] != nil {
562- totalProperties ++
563- go checkProperty (rProps [w ], lEntities [rProps [w ]], rEntities [rProps [w ]], propChanges , doneChan )
560+ wg . Add ( 1 )
561+ go checkProperty (rProps [w ], lEntities [rProps [w ]], rEntities [rProps [w ]])
564562 } else {
565563 CreateChange (changes , ObjectAdded , v3 .PropertiesLabel ,
566564 nil , rKeyNodes [rProps [w ]], false , nil , rEntities [rProps [w ]])
567- continue
568565 }
569566 }
570- // now check if anything was removed
571567 for w := range lProps {
572568 if rEntities [lProps [w ]] != nil {
573- go checkProperty (lProps [w ], rEntities [lProps [w ]], lEntities [rProps [w ]], propChanges , doneChan )
569+ wg .Add (1 )
570+ go checkProperty (lProps [w ], lEntities [lProps [w ]], rEntities [rProps [w ]])
574571 } else {
575572 CreateChange (changes , ObjectRemoved , v3 .PropertiesLabel ,
576573 nil , lKeyNodes [lProps [w ]], true , lEntities [lProps [w ]], nil )
577- continue
578574 }
579575 }
580576 }
581- return totalProperties
577+
578+ // Wait for all property comparisons to finish.
579+ wg .Wait ()
582580}
583581
584582func checkSchemaPropertyChanges (
@@ -1253,11 +1251,9 @@ func extractSchemaChanges(
12531251 label string ,
12541252 sc * []* SchemaChanges ,
12551253 changes * []* Change ,
1256- done chan struct {},
12571254) {
12581255 // if there is nothing here, there is nothing to do.
12591256 if lSchema == nil && rSchema == nil {
1260- done <- struct {}{}
12611257 return
12621258 }
12631259
@@ -1316,5 +1312,4 @@ func extractSchemaChanges(
13161312 }
13171313 }
13181314 }
1319- done <- struct {}{}
13201315}
0 commit comments