Skip to content

Commit 1861bbe

Browse files
committed
fix(solver) resolve a data race with ops counters
1 parent 729559e commit 1861bbe

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
@@ -153,14 +153,14 @@ func syncMain(ctx context.Context, filenames []string, dry bool, parallelism,
153153
stats, errs := solver.Solve(ctx, s, wsClient, nil, parallelism, dry)
154154
printFn := color.New(color.FgGreen, color.Bold).PrintfFunc()
155155
printFn("Summary:\n")
156-
printFn(" Created: %v\n", stats.CreateOps)
157-
printFn(" Updated: %v\n", stats.UpdateOps)
158-
printFn(" Deleted: %v\n", stats.DeleteOps)
156+
printFn(" Created: %v\n", stats.CreateOps.Read())
157+
printFn(" Updated: %v\n", stats.UpdateOps.Read())
158+
printFn(" Deleted: %v\n", stats.DeleteOps.Read())
159159
if errs != nil {
160160
return utils.ErrArray{Errors: errs}
161161
}
162162
if diffCmdNonZeroExitCode &&
163-
stats.CreateOps+stats.UpdateOps+stats.DeleteOps != 0 {
163+
stats.CreateOps.Read()+stats.UpdateOps.Read()+stats.DeleteOps.Read() != 0 {
164164
os.Exit(exitCodeDiffDetection)
165165
}
166166
return nil

cmd/common_konnect.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,14 @@ func syncKonnect(ctx context.Context,
8282
stats, errs := solver.Solve(ctx, s, kongClient, konnectClient, parallelism, dry)
8383
printFn := color.New(color.FgGreen, color.Bold).PrintfFunc()
8484
printFn("Summary:\n")
85-
printFn(" Created: %v\n", stats.CreateOps)
86-
printFn(" Updated: %v\n", stats.UpdateOps)
87-
printFn(" Deleted: %v\n", stats.DeleteOps)
85+
printFn(" Created: %v\n", stats.CreateOps.Read())
86+
printFn(" Updated: %v\n", stats.UpdateOps.Read())
87+
printFn(" Deleted: %v\n", stats.DeleteOps.Read())
8888
if errs != nil {
8989
return utils.ErrArray{Errors: errs}
9090
}
9191
if diffCmdNonZeroExitCode &&
92-
stats.CreateOps+stats.UpdateOps+stats.DeleteOps != 0 {
92+
stats.CreateOps.Read()+stats.UpdateOps.Read()+stats.DeleteOps.Read() != 0 {
9393
os.Exit(exitCodeDiffDetection)
9494
}
9595

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) Read() 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 TestStats_CreateOps(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.Read())
23+
}

0 commit comments

Comments
 (0)