Skip to content

Commit be00ff5

Browse files
committed
chore: redo event filtering as a sequence of iterators
This should be both easier to understand and debug. Replace this stuff with `range` loops once Go 1.23 lands. Signed-off-by: Dmitriy Matrenichev <dmitry.matrenichev@siderolabs.com>
1 parent a936b60 commit be00ff5

File tree

10 files changed

+600
-125
lines changed

10 files changed

+600
-125
lines changed

.github/workflows/ci.yaml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
22
#
3-
# Generated on 2024-04-26T15:13:42Z by kres ebc009d.
3+
# Generated on 2024-05-13T15:08:28Z by kres ce88e1c.
44

55
name: default
66
concurrency:
@@ -31,7 +31,7 @@ jobs:
3131
if: (!startsWith(github.head_ref, 'renovate/') && !startsWith(github.head_ref, 'dependabot/'))
3232
services:
3333
buildkitd:
34-
image: moby/buildkit:v0.13.1
34+
image: moby/buildkit:v0.13.2
3535
options: --privileged
3636
ports:
3737
- 1234:1234
@@ -61,8 +61,11 @@ jobs:
6161
run: |
6262
make unit-tests-race
6363
- name: coverage
64-
run: |
65-
make coverage
64+
uses: codecov/codecov-action@v4
65+
with:
66+
files: _out/coverage-unit-tests.txt
67+
token: ${{ secrets.CODECOV_TOKEN }}
68+
timeout-minutes: 3
6669
- name: siderolink-agent
6770
run: |
6871
make siderolink-agent

.golangci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
22
#
3-
# Generated on 2024-03-20T20:16:10Z by kres latest.
3+
# Generated on 2024-05-13T15:08:28Z by kres ce88e1c.
44

55
# options for analysis running
66
run:
@@ -54,7 +54,6 @@ linters-settings:
5454
goimports:
5555
local-prefixes: github.com/siderolabs/siderolink/
5656
gomodguard: { }
57-
gomnd: { }
5857
govet:
5958
enable-all: true
6059
lll:
@@ -109,17 +108,18 @@ linters:
109108
disable:
110109
- exhaustivestruct
111110
- exhaustruct
111+
- err113
112112
- forbidigo
113113
- funlen
114114
- gochecknoglobals
115115
- gochecknoinits
116116
- godox
117-
- goerr113
118117
- gomnd
119118
- gomoddirectives
120119
- gosec
121120
- inamedparam
122121
- ireturn
122+
- mnd
123123
- nestif
124124
- nonamedreturns
125125
- nosnakecase

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# syntax = docker/dockerfile-upstream:1.7.0-labs
1+
# syntax = docker/dockerfile-upstream:1.7.1-labs
22

33
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
44
#
5-
# Generated on 2024-04-26T15:13:42Z by kres ebc009d.
5+
# Generated on 2024-05-13T15:08:28Z by kres ce88e1c.
66

77
ARG TOOLCHAIN
88

Makefile

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
22
#
3-
# Generated on 2024-04-26T15:13:42Z by kres ebc009d.
3+
# Generated on 2024-05-13T15:08:28Z by kres ce88e1c.
44

55
# common variables
66

@@ -20,9 +20,9 @@ GRPC_GO_VERSION ?= 1.3.0
2020
GRPC_GATEWAY_VERSION ?= 2.19.1
2121
VTPROTOBUF_VERSION ?= 0.6.0
2222
DEEPCOPY_VERSION ?= v0.5.6
23-
GOLANGCILINT_VERSION ?= v1.57.2
23+
GOLANGCILINT_VERSION ?= v1.58.0
2424
GOFUMPT_VERSION ?= v0.6.0
25-
GO_VERSION ?= 1.22.2
25+
GO_VERSION ?= 1.22.3
2626
GOIMPORTS_VERSION ?= v0.20.0
2727
GO_BUILDFLAGS ?=
2828
GO_LDFLAGS ?=
@@ -176,10 +176,6 @@ unit-tests: ## Performs unit tests
176176
unit-tests-race: ## Performs unit tests with race detection enabled.
177177
@$(MAKE) target-$@
178178

179-
.PHONY: coverage
180-
coverage: ## Upload coverage data to codecov.io.
181-
bash -c "bash <(curl -s https://codecov.io/bash) -f $(ARTIFACTS)/coverage-unit-tests.txt -X fix"
182-
183179
.PHONY: $(ARTIFACTS)/siderolink-agent-darwin-amd64
184180
$(ARTIFACTS)/siderolink-agent-darwin-amd64:
185181
@$(MAKE) local-siderolink-agent-darwin-amd64 DEST=$(ARTIFACTS)

go.mod

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,20 @@ go 1.22.0
44

55
require (
66
github.com/google/uuid v1.6.0
7-
github.com/jsimonetti/rtnetlink v1.4.1
7+
github.com/jsimonetti/rtnetlink v1.4.2
88
github.com/planetscale/vtprotobuf v0.6.0
99
github.com/siderolabs/gen v0.4.8
1010
github.com/siderolabs/go-pointer v1.0.0
1111
github.com/stretchr/testify v1.9.0
12+
go.uber.org/multierr v1.11.0
1213
go.uber.org/zap v1.27.0
1314
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
1415
golang.org/x/sync v0.7.0
15-
golang.org/x/sys v0.19.0
16+
golang.org/x/sys v0.20.0
1617
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
1718
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
1819
google.golang.org/grpc v1.63.2
19-
google.golang.org/protobuf v1.33.0
20+
google.golang.org/protobuf v1.34.1
2021
gopkg.in/yaml.v3 v3.0.1
2122
)
2223

@@ -28,12 +29,11 @@ require (
2829
github.com/mdlayher/netlink v1.7.2 // indirect
2930
github.com/mdlayher/socket v0.5.1 // indirect
3031
github.com/pmezard/go-difflib v1.0.0 // indirect
31-
go.uber.org/multierr v1.11.0 // indirect
32-
golang.org/x/crypto v0.22.0 // indirect
32+
golang.org/x/crypto v0.23.0 // indirect
3333
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect
34-
golang.org/x/net v0.24.0 // indirect
35-
golang.org/x/text v0.14.0 // indirect
34+
golang.org/x/net v0.25.0 // indirect
35+
golang.org/x/text v0.15.0 // indirect
3636
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
37-
google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect
37+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434 // indirect
3838
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
3939
)

go.sum

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtL
1212
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
1313
github.com/jsimonetti/rtnetlink v1.4.1 h1:JfD4jthWBqZMEffc5RjgmlzpYttAVw1sdnmiNaPO3hE=
1414
github.com/jsimonetti/rtnetlink v1.4.1/go.mod h1:xJjT7t59UIZ62GLZbv6PLLo8VFrostJMPBAheR6OM8w=
15+
github.com/jsimonetti/rtnetlink v1.4.2 h1:Df9w9TZ3npHTyDn0Ev9e1uzmN2odmXd0QX+J5GTEn90=
16+
github.com/jsimonetti/rtnetlink v1.4.2/go.mod h1:92s6LJdE+1iOrw+F2/RO7LYI2Qd8pPpFNNUYW06gcoM=
1517
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
1618
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
1719
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -46,16 +48,24 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
4648
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
4749
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
4850
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
51+
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
52+
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
4953
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY=
5054
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
5155
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
5256
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
57+
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
58+
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
5359
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
5460
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
5561
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
5662
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
63+
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
64+
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
5765
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
5866
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
67+
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
68+
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
5969
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
6070
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
6171
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
@@ -66,10 +76,14 @@ golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvY
6676
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
6777
google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be h1:LG9vZxsWGOmUKieR8wPAUR3u3MpnYFQZROPIMaXh7/A=
6878
google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
79+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434 h1:umK/Ey0QEzurTNlsV3R+MfxHAb78HCEX/IkuR+zH4WQ=
80+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM=
6981
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
7082
google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
7183
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
7284
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
85+
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
86+
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
7387
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
7488
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
7589
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

pkg/iter/iter.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4+
5+
// Package iter provides utilities for working with iterators.
6+
package iter
7+
8+
// Seq is a sequence of elements.
9+
type Seq[T any] func(yield func(T) bool)
10+
11+
// Deduplicate yields elements from elems, skipping duplicates. It always yields the last equal element.
12+
// The equal function is used to compare elements.
13+
// The yield function is used to yield elements. If it returns false, the iteration stops.
14+
// Slice should be sorted before calling this function.
15+
func Deduplicate[T any](elems []T, equal func(a, b T) bool) Seq[T] {
16+
return func(yield func(T) bool) {
17+
switch len(elems) {
18+
case 1:
19+
yield(elems[0])
20+
21+
fallthrough
22+
case 0:
23+
return
24+
}
25+
26+
last := elems[0]
27+
for _, elem := range elems[1:] {
28+
if equal(last, elem) {
29+
last = elem
30+
31+
continue
32+
}
33+
34+
if !yield(last) {
35+
return
36+
}
37+
38+
last = elem
39+
}
40+
41+
yield(last)
42+
}
43+
}
44+
45+
// Filter iterates over elements in seq, calling the given function for each element.
46+
// If the function returns true, the element is yielded.
47+
func Filter[T any](seq Seq[T], fn func(T) bool) Seq[T] {
48+
return func(yield func(T) bool) {
49+
seq(func(elem T) bool {
50+
if fn(elem) {
51+
return yield(elem)
52+
}
53+
54+
return true
55+
})
56+
}
57+
}

pkg/iter/iter_test.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4+
5+
package iter_test
6+
7+
import (
8+
"testing"
9+
10+
"github.com/stretchr/testify/require"
11+
12+
"github.com/siderolabs/siderolink/pkg/iter"
13+
)
14+
15+
func TestDeduplicate(t *testing.T) {
16+
type elem struct { //nolint:govet
17+
value int
18+
name string
19+
}
20+
21+
tests := map[string]struct {
22+
elems []elem
23+
expected []string
24+
}{
25+
"empty": {},
26+
"single": {
27+
elems: []elem{
28+
{1, "a"},
29+
},
30+
expected: []string{"a"},
31+
},
32+
"multiple equal": {
33+
elems: []elem{
34+
{1, "a"},
35+
{1, "b"},
36+
{1, "c"},
37+
},
38+
expected: []string{"c"},
39+
},
40+
"two different": {
41+
elems: []elem{
42+
{1, "a"},
43+
{1, "b"},
44+
{1, "c"},
45+
{2, "d"},
46+
{2, "e"},
47+
{2, "f"},
48+
},
49+
expected: []string{"c", "f"},
50+
},
51+
"three different": {
52+
elems: []elem{
53+
{1, "a"},
54+
{2, "d"},
55+
{2, "e"},
56+
{2, "f"},
57+
{3, "g"},
58+
},
59+
expected: []string{"a", "f", "g"},
60+
},
61+
}
62+
63+
for name, test := range tests {
64+
t.Run(name, func(t *testing.T) {
65+
it := iter.Deduplicate(test.elems, func(a, b elem) bool { return a.value == b.value })
66+
67+
var result []string
68+
69+
it(func(elem elem) bool {
70+
result = append(result, elem.name)
71+
72+
return true
73+
})
74+
75+
require.Equal(t, test.expected, result)
76+
})
77+
}
78+
}

0 commit comments

Comments
 (0)