Skip to content

Commit

Permalink
chore: redo event filtering as a sequence of iterators
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
DmitriyMV committed May 14, 2024
1 parent a936b60 commit be00ff5
Show file tree
Hide file tree
Showing 10 changed files with 600 additions and 125 deletions.
11 changes: 7 additions & 4 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2024-04-26T15:13:42Z by kres ebc009d.
# Generated on 2024-05-13T15:08:28Z by kres ce88e1c.

name: default
concurrency:
Expand Down Expand Up @@ -31,7 +31,7 @@ jobs:
if: (!startsWith(github.head_ref, 'renovate/') && !startsWith(github.head_ref, 'dependabot/'))
services:
buildkitd:
image: moby/buildkit:v0.13.1
image: moby/buildkit:v0.13.2
options: --privileged
ports:
- 1234:1234
Expand Down Expand Up @@ -61,8 +61,11 @@ jobs:
run: |
make unit-tests-race
- name: coverage
run: |
make coverage
uses: codecov/codecov-action@v4
with:
files: _out/coverage-unit-tests.txt
token: ${{ secrets.CODECOV_TOKEN }}
timeout-minutes: 3
- name: siderolink-agent
run: |
make siderolink-agent
Expand Down
6 changes: 3 additions & 3 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2024-03-20T20:16:10Z by kres latest.
# Generated on 2024-05-13T15:08:28Z by kres ce88e1c.

# options for analysis running
run:
Expand Down Expand Up @@ -54,7 +54,6 @@ linters-settings:
goimports:
local-prefixes: github.com/siderolabs/siderolink/
gomodguard: { }
gomnd: { }
govet:
enable-all: true
lll:
Expand Down Expand Up @@ -109,17 +108,18 @@ linters:
disable:
- exhaustivestruct
- exhaustruct
- err113
- forbidigo
- funlen
- gochecknoglobals
- gochecknoinits
- godox
- goerr113
- gomnd
- gomoddirectives
- gosec
- inamedparam
- ireturn
- mnd
- nestif
- nonamedreturns
- nosnakecase
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# syntax = docker/dockerfile-upstream:1.7.0-labs
# syntax = docker/dockerfile-upstream:1.7.1-labs

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

ARG TOOLCHAIN

Expand Down
10 changes: 3 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2024-04-26T15:13:42Z by kres ebc009d.
# Generated on 2024-05-13T15:08:28Z by kres ce88e1c.

# common variables

Expand All @@ -20,9 +20,9 @@ GRPC_GO_VERSION ?= 1.3.0
GRPC_GATEWAY_VERSION ?= 2.19.1
VTPROTOBUF_VERSION ?= 0.6.0
DEEPCOPY_VERSION ?= v0.5.6
GOLANGCILINT_VERSION ?= v1.57.2
GOLANGCILINT_VERSION ?= v1.58.0
GOFUMPT_VERSION ?= v0.6.0
GO_VERSION ?= 1.22.2
GO_VERSION ?= 1.22.3
GOIMPORTS_VERSION ?= v0.20.0
GO_BUILDFLAGS ?=
GO_LDFLAGS ?=
Expand Down Expand Up @@ -176,10 +176,6 @@ unit-tests: ## Performs unit tests
unit-tests-race: ## Performs unit tests with race detection enabled.
@$(MAKE) target-$@

.PHONY: coverage
coverage: ## Upload coverage data to codecov.io.
bash -c "bash <(curl -s https://codecov.io/bash) -f $(ARTIFACTS)/coverage-unit-tests.txt -X fix"

.PHONY: $(ARTIFACTS)/siderolink-agent-darwin-amd64
$(ARTIFACTS)/siderolink-agent-darwin-amd64:
@$(MAKE) local-siderolink-agent-darwin-amd64 DEST=$(ARTIFACTS)
Expand Down
16 changes: 8 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@ go 1.22.0

require (
github.com/google/uuid v1.6.0
github.com/jsimonetti/rtnetlink v1.4.1
github.com/jsimonetti/rtnetlink v1.4.2
github.com/planetscale/vtprotobuf v0.6.0
github.com/siderolabs/gen v0.4.8
github.com/siderolabs/go-pointer v1.0.0
github.com/stretchr/testify v1.9.0
go.uber.org/multierr v1.11.0
go.uber.org/zap v1.27.0
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
golang.org/x/sync v0.7.0
golang.org/x/sys v0.19.0
golang.org/x/sys v0.20.0
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
google.golang.org/grpc v1.63.2
google.golang.org/protobuf v1.33.0
google.golang.org/protobuf v1.34.1
gopkg.in/yaml.v3 v3.0.1
)

Expand All @@ -28,12 +29,11 @@ require (
github.com/mdlayher/netlink v1.7.2 // indirect
github.com/mdlayher/socket v0.5.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)
14 changes: 14 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtL
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/jsimonetti/rtnetlink v1.4.1 h1:JfD4jthWBqZMEffc5RjgmlzpYttAVw1sdnmiNaPO3hE=
github.com/jsimonetti/rtnetlink v1.4.1/go.mod h1:xJjT7t59UIZ62GLZbv6PLLo8VFrostJMPBAheR6OM8w=
github.com/jsimonetti/rtnetlink v1.4.2 h1:Df9w9TZ3npHTyDn0Ev9e1uzmN2odmXd0QX+J5GTEn90=
github.com/jsimonetti/rtnetlink v1.4.2/go.mod h1:92s6LJdE+1iOrw+F2/RO7LYI2Qd8pPpFNNUYW06gcoM=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
Expand Down Expand Up @@ -46,16 +48,24 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY=
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
Expand All @@ -66,10 +76,14 @@ golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvY
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be h1:LG9vZxsWGOmUKieR8wPAUR3u3MpnYFQZROPIMaXh7/A=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434 h1:umK/Ey0QEzurTNlsV3R+MfxHAb78HCEX/IkuR+zH4WQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM=
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
Expand Down
57 changes: 57 additions & 0 deletions pkg/iter/iter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Package iter provides utilities for working with iterators.
package iter

// Seq is a sequence of elements.
type Seq[T any] func(yield func(T) bool)

// Deduplicate yields elements from elems, skipping duplicates. It always yields the last equal element.
// The equal function is used to compare elements.
// The yield function is used to yield elements. If it returns false, the iteration stops.
// Slice should be sorted before calling this function.
func Deduplicate[T any](elems []T, equal func(a, b T) bool) Seq[T] {
return func(yield func(T) bool) {
switch len(elems) {
case 1:
yield(elems[0])

fallthrough
case 0:
return
}

last := elems[0]
for _, elem := range elems[1:] {
if equal(last, elem) {
last = elem

continue
}

if !yield(last) {
return
}

last = elem
}

yield(last)
}
}

// Filter iterates over elements in seq, calling the given function for each element.
// If the function returns true, the element is yielded.
func Filter[T any](seq Seq[T], fn func(T) bool) Seq[T] {
return func(yield func(T) bool) {
seq(func(elem T) bool {
if fn(elem) {
return yield(elem)
}

return true
})
}
}
78 changes: 78 additions & 0 deletions pkg/iter/iter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package iter_test

import (
"testing"

"github.com/stretchr/testify/require"

"github.com/siderolabs/siderolink/pkg/iter"
)

func TestDeduplicate(t *testing.T) {
type elem struct { //nolint:govet
value int
name string
}

tests := map[string]struct {
elems []elem
expected []string
}{
"empty": {},
"single": {
elems: []elem{
{1, "a"},
},
expected: []string{"a"},
},
"multiple equal": {
elems: []elem{
{1, "a"},
{1, "b"},
{1, "c"},
},
expected: []string{"c"},
},
"two different": {
elems: []elem{
{1, "a"},
{1, "b"},
{1, "c"},
{2, "d"},
{2, "e"},
{2, "f"},
},
expected: []string{"c", "f"},
},
"three different": {
elems: []elem{
{1, "a"},
{2, "d"},
{2, "e"},
{2, "f"},
{3, "g"},
},
expected: []string{"a", "f", "g"},
},
}

for name, test := range tests {
t.Run(name, func(t *testing.T) {
it := iter.Deduplicate(test.elems, func(a, b elem) bool { return a.value == b.value })

var result []string

it(func(elem elem) bool {
result = append(result, elem.name)

return true
})

require.Equal(t, test.expected, result)
})
}
}
Loading

0 comments on commit be00ff5

Please sign in to comment.