Skip to content

Commit 3423945

Browse files
authored
fix(solver) resolve a data race with ops counters (#381)
1 parent de1c830 commit 3423945

File tree

4 files changed

+60
-15
lines changed

4 files changed

+60
-15
lines changed

cmd/common.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -166,14 +166,14 @@ func syncMain(ctx context.Context, filenames []string, dry bool, parallelism,
166166
stats, errs := solver.Solve(ctx, s, wsClient, nil, parallelism, dry)
167167
printFn := color.New(color.FgGreen, color.Bold).PrintfFunc()
168168
printFn("Summary:\n")
169-
printFn(" Created: %v\n", stats.CreateOps)
170-
printFn(" Updated: %v\n", stats.UpdateOps)
171-
printFn(" Deleted: %v\n", stats.DeleteOps)
169+
printFn(" Created: %v\n", stats.CreateOps.Count())
170+
printFn(" Updated: %v\n", stats.UpdateOps.Count())
171+
printFn(" Deleted: %v\n", stats.DeleteOps.Count())
172172
if errs != nil {
173173
return utils.ErrArray{Errors: errs}
174174
}
175175
if diffCmdNonZeroExitCode &&
176-
stats.CreateOps+stats.UpdateOps+stats.DeleteOps != 0 {
176+
stats.CreateOps.Count()+stats.UpdateOps.Count()+stats.DeleteOps.Count() != 0 {
177177
os.Exit(exitCodeDiffDetection)
178178
}
179179
return nil

cmd/common_konnect.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,14 @@ func syncKonnect(ctx context.Context,
9090
stats, errs := solver.Solve(ctx, s, kongClient, konnectClient, parallelism, dry)
9191
printFn := color.New(color.FgGreen, color.Bold).PrintfFunc()
9292
printFn("Summary:\n")
93-
printFn(" Created: %v\n", stats.CreateOps)
94-
printFn(" Updated: %v\n", stats.UpdateOps)
95-
printFn(" Deleted: %v\n", stats.DeleteOps)
93+
printFn(" Created: %v\n", stats.CreateOps.Count())
94+
printFn(" Updated: %v\n", stats.UpdateOps.Count())
95+
printFn(" Deleted: %v\n", stats.DeleteOps.Count())
9696
if errs != nil {
9797
return utils.ErrArray{Errors: errs}
9898
}
9999
if diffCmdNonZeroExitCode &&
100-
stats.CreateOps+stats.UpdateOps+stats.DeleteOps != 0 {
100+
stats.CreateOps.Count()+stats.UpdateOps.Count()+stats.DeleteOps.Count() != 0 {
101101
os.Exit(exitCodeDiffDetection)
102102
}
103103

solver/solver.go

+29-7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package solver
22

33
import (
44
"context"
5+
"sync"
56

67
"github.com/kong/deck/crud"
78
"github.com/kong/deck/diff"
@@ -14,9 +15,26 @@ import (
1415

1516
// Stats holds the stats related to a Solve.
1617
type Stats struct {
17-
CreateOps int
18-
UpdateOps int
19-
DeleteOps int
18+
CreateOps *AtomicInt32Counter
19+
UpdateOps *AtomicInt32Counter
20+
DeleteOps *AtomicInt32Counter
21+
}
22+
23+
type AtomicInt32Counter struct {
24+
counter int32
25+
lock sync.RWMutex
26+
}
27+
28+
func (a *AtomicInt32Counter) Increment(delta int32) {
29+
a.lock.Lock()
30+
defer a.lock.Unlock()
31+
a.counter += delta
32+
}
33+
34+
func (a *AtomicInt32Counter) Count() int32 {
35+
a.lock.RLock()
36+
defer a.lock.RUnlock()
37+
return a.counter
2038
}
2139

2240
// Solve generates a diff and walks the graph.
@@ -26,15 +44,19 @@ func Solve(ctx context.Context, syncer *diff.Syncer,
2644

2745
r := buildRegistry(client, konnectClient)
2846

29-
var stats Stats
47+
stats := Stats{
48+
CreateOps: &AtomicInt32Counter{},
49+
UpdateOps: &AtomicInt32Counter{},
50+
DeleteOps: &AtomicInt32Counter{},
51+
}
3052
recordOp := func(op crud.Op) {
3153
switch op {
3254
case crud.Create:
33-
stats.CreateOps = stats.CreateOps + 1
55+
stats.CreateOps.Increment(1)
3456
case crud.Update:
35-
stats.UpdateOps = stats.UpdateOps + 1
57+
stats.UpdateOps.Increment(1)
3658
case crud.Delete:
37-
stats.DeleteOps = stats.DeleteOps + 1
59+
stats.DeleteOps.Increment(1)
3860
}
3961
}
4062

solver/solver_test.go

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package solver
2+
3+
import (
4+
"sync"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestAtomicInt32Counter(t *testing.T) {
11+
var a AtomicInt32Counter
12+
var wg sync.WaitGroup
13+
14+
wg.Add(10)
15+
for i := 0; i < 10; i++ {
16+
go func() {
17+
defer wg.Done()
18+
a.Increment(int32(1))
19+
}()
20+
}
21+
wg.Wait()
22+
assert.Equal(t, int32(10), a.Count())
23+
}

0 commit comments

Comments
 (0)