Skip to content

Commit b7be747

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

File tree

4 files changed

+51
-14
lines changed

4 files changed

+51
-14
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

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

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

67
"github.com/kong/deck/crud"
78
"github.com/kong/deck/diff"
@@ -14,9 +15,22 @@ 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+
}
26+
27+
func (a *AtomicInt32Counter) Increment(delta int32) {
28+
atomic.AddInt32(&a.counter, delta)
29+
}
30+
31+
func (a *AtomicInt32Counter) Read() int32 {
32+
counter := atomic.LoadInt32(&a.counter)
33+
return counter
2034
}
2135

2236
// Solve generates a diff and walks the graph.
@@ -30,11 +44,11 @@ func Solve(ctx context.Context, syncer *diff.Syncer,
3044
recordOp := func(op crud.Op) {
3145
switch op {
3246
case crud.Create:
33-
stats.CreateOps = stats.CreateOps + 1
47+
stats.CreateOps.Increment(1)
3448
case crud.Update:
35-
stats.UpdateOps = stats.UpdateOps + 1
49+
stats.UpdateOps.Increment(1)
3650
case crud.Delete:
37-
stats.DeleteOps = stats.DeleteOps + 1
51+
stats.DeleteOps.Increment(1)
3852
}
3953
}
4054

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)