Skip to content

Commit 1ec9cf6

Browse files
committed
Rename Random to Jitter and introduce timeouts
This patch renames the `Random` parameter of the leadership flag to `Jitter` because it reflects better what it is used for. The patch also introduces timeouts for the database operations so that the flag will recover faster when database connection packets are silently dropped. Note that the `lib/pq` doesn't always respect timeouts, in particular it doesn't respect them when packags are dropped. To effectively respect those timeouts it is necessary to switch to the `pgx` family of libraries. In order to make that easier this patch also adds some functions to abstract the differences, like the `database.ErrorCode` that extracts the error code from a database error and works with both `lib/pq` and `pgx`. Signed-off-by: Juan Hernandez <[email protected]>
1 parent ae4eb83 commit 1ec9cf6

File tree

8 files changed

+353
-60
lines changed

8 files changed

+353
-60
lines changed

database/error_code.go

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
Copyright (c) 2021 Red Hat, Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package database
18+
19+
import (
20+
"reflect"
21+
)
22+
23+
// ErrorCode extracts the error code from the given error returned by a database operation. It uses
24+
// reflection to get the value of the `Code` field in order to avoid having to import the `lib/pq`
25+
// and `pgx` packages. It returns an empty string if the passed error is nil or it hasn't the `Code`
26+
// field.
27+
func ErrorCode(err error) string {
28+
if err == nil {
29+
return ""
30+
}
31+
value := reflect.ValueOf(err)
32+
if value.Type().Kind() != reflect.Ptr {
33+
return ""
34+
}
35+
elem := value.Elem()
36+
if elem.Type().Kind() != reflect.Struct {
37+
return ""
38+
}
39+
field := elem.FieldByName("Code")
40+
if !field.IsValid() {
41+
return ""
42+
}
43+
if field.Type().Kind() != reflect.String {
44+
return ""
45+
}
46+
return field.String()
47+
}

database/error_code_test.go

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
Copyright (c) 2021 Red Hat, Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package database
18+
19+
import (
20+
"io"
21+
22+
. "github.com/onsi/ginkgo/extensions/table" // nolint
23+
. "github.com/onsi/gomega" // nolint
24+
25+
"github.com/jackc/pgconn"
26+
"github.com/lib/pq"
27+
)
28+
29+
var _ = DescribeTable(
30+
"Error code extraction",
31+
func(err error, expected string) {
32+
actual := ErrorCode(err)
33+
Expect(actual).To(Equal(expected))
34+
},
35+
Entry(
36+
"Nil",
37+
nil,
38+
"",
39+
),
40+
Entry(
41+
"From 'pq'",
42+
&pq.Error{
43+
Code: "123",
44+
},
45+
"123",
46+
),
47+
Entry(
48+
"From 'pgconn'",
49+
&pgconn.PgError{
50+
Code: "123",
51+
},
52+
"123",
53+
),
54+
Entry(
55+
"Non SQL error",
56+
io.EOF,
57+
"",
58+
),
59+
)

database/main_test.go

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
Copyright (c) 2021 Red Hat, Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package database
18+
19+
import (
20+
"testing"
21+
22+
. "github.com/onsi/ginkgo" // nolint
23+
. "github.com/onsi/gomega" // nolint
24+
)
25+
26+
func TestDatabase(t *testing.T) {
27+
RegisterFailHandler(Fail)
28+
RunSpecs(t, "Database")
29+
}

go.mod

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ require (
99
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
1010
github.com/google/uuid v1.2.0
1111
github.com/grokify/html-strip-tags-go v0.0.0-20200322061010-ea0c1cf2f119
12+
github.com/jackc/pgconn v1.9.0
13+
github.com/jackc/pgx/v4 v4.12.0
1214
github.com/json-iterator/go v1.1.10
1315
github.com/lib/pq v1.10.2
1416
github.com/onsi/ginkgo v1.11.0
1517
github.com/onsi/gomega v1.7.0
1618
github.com/prometheus/client_golang v1.9.0
1719
gitlab.com/c0b/go-ordered-json v0.0.0-20171130231205-49bbdab258c2
1820
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
19-
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 // indirect
20-
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
2121
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
2222
k8s.io/api v0.18.5
2323
k8s.io/apimachinery v0.18.5

go.sum

+126-2
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)