Skip to content

Commit 4de8423

Browse files
committed
Merge remote-tracking branch 'origin/main' into pprof-labels-stacks
2 parents ca5536a + 9cbeab4 commit 4de8423

File tree

6 files changed

+233
-102
lines changed

6 files changed

+233
-102
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ require (
3232
github.com/go-git/go-billy/v5 v5.3.1
3333
github.com/go-git/go-git/v5 v5.4.3-0.20210630082519-b4368b2a2ca4
3434
github.com/go-ldap/ldap/v3 v3.4.2
35-
github.com/go-redis/redis/v8 v8.11.4
35+
github.com/go-redis/redis/v8 v8.11.5
3636
github.com/go-sql-driver/mysql v1.6.0
3737
github.com/go-swagger/go-swagger v0.29.0
3838
github.com/go-testfixtures/testfixtures/v3 v3.6.1

go.sum

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -593,8 +593,8 @@ github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8w
593593
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
594594
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
595595
github.com/go-redis/redis/v8 v8.4.0/go.mod h1:A1tbYoHSa1fXwN+//ljcCYYJeLmVrwL9hbQN45Jdy0M=
596-
github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg=
597-
github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w=
596+
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
597+
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
598598
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
599599
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
600600
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
@@ -758,6 +758,7 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe
758758
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
759759
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
760760
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
761+
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
761762
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
762763
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
763764
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
@@ -1234,15 +1235,18 @@ github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
12341235
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
12351236
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
12361237
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
1237-
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
12381238
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
1239+
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
1240+
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
1241+
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
12391242
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
12401243
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
12411244
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
12421245
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
12431246
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
1244-
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
1245-
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
1247+
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
1248+
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
1249+
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
12461250
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
12471251
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
12481252
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=

modules/nosql/manager_leveldb.go

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,31 @@ func (m *Manager) CloseLevelDB(connection string) error {
5151
}
5252

5353
// GetLevelDB gets a levelDB for a particular connection
54-
func (m *Manager) GetLevelDB(connection string) (*leveldb.DB, error) {
54+
func (m *Manager) GetLevelDB(connection string) (db *leveldb.DB, err error) {
55+
// Because we want associate any goroutines created by this call to the main nosqldb context we need to
56+
// wrap this in a goroutine labelled with the nosqldb context
57+
done := make(chan struct{})
58+
var recovered interface{}
59+
go func() {
60+
defer func() {
61+
recovered = recover()
62+
if recovered != nil {
63+
log.Critical("PANIC during GetLevelDB: %v\nStacktrace: %s", recovered, log.Stack(2))
64+
}
65+
close(done)
66+
}()
67+
pprof.SetGoroutineLabels(m.ctx)
68+
69+
db, err = m.getLevelDB(connection)
70+
}()
71+
<-done
72+
if recovered != nil {
73+
panic(recovered)
74+
}
75+
return
76+
}
77+
78+
func (m *Manager) getLevelDB(connection string) (*leveldb.DB, error) {
5579
// Convert the provided connection description to the common format
5680
uri := ToLevelDBURI(connection)
5781

@@ -164,28 +188,21 @@ func (m *Manager) GetLevelDB(connection string) (*leveldb.DB, error) {
164188
}
165189
}
166190

167-
// Now because we want associate any goroutines created by this call to the main nosqldb context we need to
168-
// wrap the openFile within a goroutine which we can label nicely.
169191
var err error
170-
done := make(chan struct{})
171-
go func() {
172-
pprof.SetGoroutineLabels(m.ctx)
173-
defer close(done)
174-
db.db, err = leveldb.OpenFile(dataDir, opts)
175-
if err != nil {
176-
if !errors.IsCorrupted(err) {
177-
if strings.Contains(err.Error(), "resource temporarily unavailable") {
178-
err = fmt.Errorf("unable to lock level db at %s: %w", dataDir, err)
179-
return
180-
}
181-
182-
err = fmt.Errorf("unable to open level db at %s: %w", dataDir, err)
183-
return
192+
db.db, err = leveldb.OpenFile(dataDir, opts)
193+
if err != nil {
194+
if !errors.IsCorrupted(err) {
195+
if strings.Contains(err.Error(), "resource temporarily unavailable") {
196+
err = fmt.Errorf("unable to lock level db at %s: %w", dataDir, err)
197+
return nil, err
184198
}
185-
db.db, err = leveldb.RecoverFile(dataDir, opts)
199+
200+
err = fmt.Errorf("unable to open level db at %s: %w", dataDir, err)
201+
return nil, err
186202
}
187-
}()
188-
<-done
203+
db.db, err = leveldb.RecoverFile(dataDir, opts)
204+
}
205+
189206
if err != nil {
190207
return nil, err
191208
}

modules/nosql/manager_redis.go

Lines changed: 120 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@ package nosql
66

77
import (
88
"crypto/tls"
9+
"net/url"
910
"path"
1011
"runtime/pprof"
1112
"strconv"
1213
"strings"
1314

15+
"code.gitea.io/gitea/modules/log"
16+
1417
"github.com/go-redis/redis/v8"
1518
)
1619

@@ -41,7 +44,31 @@ func (m *Manager) CloseRedisClient(connection string) error {
4144
}
4245

4346
// GetRedisClient gets a redis client for a particular connection
44-
func (m *Manager) GetRedisClient(connection string) redis.UniversalClient {
47+
func (m *Manager) GetRedisClient(connection string) (client redis.UniversalClient) {
48+
// Because we want associate any goroutines created by this call to the main nosqldb context we need to
49+
// wrap this in a goroutine labelled with the nosqldb context
50+
done := make(chan struct{})
51+
var recovered interface{}
52+
go func() {
53+
defer func() {
54+
recovered = recover()
55+
if recovered != nil {
56+
log.Critical("PANIC during GetRedisClient: %v\nStacktrace: %s", recovered, log.Stack(2))
57+
}
58+
close(done)
59+
}()
60+
pprof.SetGoroutineLabels(m.ctx)
61+
62+
client = m.getRedisClient(connection)
63+
}()
64+
<-done
65+
if recovered != nil {
66+
panic(recovered)
67+
}
68+
return
69+
}
70+
71+
func (m *Manager) getRedisClient(connection string) redis.UniversalClient {
4572
m.mutex.Lock()
4673
defer m.mutex.Unlock()
4774
client, ok := m.RedisConnections[connection]
@@ -60,8 +87,59 @@ func (m *Manager) GetRedisClient(connection string) redis.UniversalClient {
6087
name: []string{connection, uri.String()},
6188
}
6289

90+
opts := getRedisOptions(uri)
91+
tlsConfig := getRedisTLSOptions(uri)
92+
93+
clientName := uri.Query().Get("clientname")
94+
95+
if len(clientName) > 0 {
96+
client.name = append(client.name, clientName)
97+
}
98+
99+
switch uri.Scheme {
100+
case "redis+sentinels":
101+
fallthrough
102+
case "rediss+sentinel":
103+
opts.TLSConfig = tlsConfig
104+
fallthrough
105+
case "redis+sentinel":
106+
client.UniversalClient = redis.NewFailoverClient(opts.Failover())
107+
case "redis+clusters":
108+
fallthrough
109+
case "rediss+cluster":
110+
opts.TLSConfig = tlsConfig
111+
fallthrough
112+
case "redis+cluster":
113+
client.UniversalClient = redis.NewClusterClient(opts.Cluster())
114+
case "redis+socket":
115+
simpleOpts := opts.Simple()
116+
simpleOpts.Network = "unix"
117+
simpleOpts.Addr = path.Join(uri.Host, uri.Path)
118+
client.UniversalClient = redis.NewClient(simpleOpts)
119+
case "rediss":
120+
opts.TLSConfig = tlsConfig
121+
fallthrough
122+
case "redis":
123+
client.UniversalClient = redis.NewClient(opts.Simple())
124+
default:
125+
return nil
126+
}
127+
128+
for _, name := range client.name {
129+
m.RedisConnections[name] = client
130+
}
131+
132+
client.count++
133+
134+
return client
135+
}
136+
137+
// getRedisOptions pulls various configuration options based on the RedisUri format and converts them to go-redis's
138+
// UniversalOptions fields. This function explicitly excludes fields related to TLS configuration, which is
139+
// conditionally attached to this options struct before being converted to the specific type for the redis scheme being
140+
// used, and only in scenarios where TLS is applicable (e.g. rediss://, redis+clusters://).
141+
func getRedisOptions(uri *url.URL) *redis.UniversalOptions {
63142
opts := &redis.UniversalOptions{}
64-
tlsConfig := &tls.Config{}
65143

66144
// Handle username/password
67145
if password, ok := uri.User.Password(); ok {
@@ -132,86 +210,54 @@ func (m *Manager) GetRedisClient(connection string) redis.UniversalClient {
132210
fallthrough
133211
case "mastername":
134212
opts.MasterName = v[0]
135-
case "skipverify":
136-
fallthrough
137-
case "insecureskipverify":
138-
insecureSkipVerify, _ := strconv.ParseBool(v[0])
139-
tlsConfig.InsecureSkipVerify = insecureSkipVerify
140-
case "clientname":
141-
client.name = append(client.name, v[0])
213+
case "sentinelusername":
214+
opts.SentinelUsername = v[0]
215+
case "sentinelpassword":
216+
opts.SentinelPassword = v[0]
142217
}
143218
}
144219

145-
done := make(chan struct{})
146-
go func() {
147-
defer close(done)
148-
pprof.SetGoroutineLabels(m.ctx)
149-
150-
switch uri.Scheme {
151-
case "redis+sentinels":
152-
fallthrough
153-
case "rediss+sentinel":
154-
opts.TLSConfig = tlsConfig
155-
fallthrough
156-
case "redis+sentinel":
157-
if uri.Host != "" {
158-
opts.Addrs = append(opts.Addrs, strings.Split(uri.Host, ",")...)
159-
}
160-
if uri.Path != "" {
161-
if db, err := strconv.Atoi(uri.Path[1:]); err == nil {
162-
opts.DB = db
163-
}
164-
}
220+
if uri.Host != "" {
221+
opts.Addrs = append(opts.Addrs, strings.Split(uri.Host, ",")...)
222+
}
165223

166-
client.UniversalClient = redis.NewFailoverClient(opts.Failover()).WithContext(m.ctx)
167-
case "redis+clusters":
168-
fallthrough
169-
case "rediss+cluster":
170-
opts.TLSConfig = tlsConfig
171-
fallthrough
172-
case "redis+cluster":
173-
if uri.Host != "" {
174-
opts.Addrs = append(opts.Addrs, strings.Split(uri.Host, ",")...)
175-
}
176-
if uri.Path != "" {
177-
if db, err := strconv.Atoi(uri.Path[1:]); err == nil {
178-
opts.DB = db
179-
}
180-
}
181-
client.UniversalClient = redis.NewClusterClient(opts.Cluster()).WithContext(m.ctx)
182-
case "redis+socket":
183-
simpleOpts := opts.Simple()
184-
simpleOpts.Network = "unix"
185-
simpleOpts.Addr = path.Join(uri.Host, uri.Path)
186-
client.UniversalClient = redis.NewClient(simpleOpts).WithContext(m.ctx)
187-
case "rediss":
188-
opts.TLSConfig = tlsConfig
189-
fallthrough
190-
case "redis":
191-
if uri.Host != "" {
192-
opts.Addrs = append(opts.Addrs, strings.Split(uri.Host, ",")...)
193-
}
194-
if uri.Path != "" {
195-
if db, err := strconv.Atoi(uri.Path[1:]); err == nil {
196-
opts.DB = db
197-
}
198-
}
199-
client.UniversalClient = redis.NewClient(opts.Simple()).WithContext(m.ctx)
200-
default:
201-
return
224+
// A redis connection string uses the path section of the URI in two different ways. In a TCP-based connection, the
225+
// path will be a database index to automatically have the client SELECT. In a Unix socket connection, it will be the
226+
// file path. We only want to try to coerce this to the database index when we're not expecting a file path so that
227+
// the error log stays clean.
228+
if uri.Path != "" && uri.Scheme != "redis+socket" {
229+
if db, err := strconv.Atoi(uri.Path[1:]); err == nil {
230+
opts.DB = db
231+
} else {
232+
log.Error("Provided database identifier '%s' is not a valid integer. Gitea will ignore this option.", uri.Path)
202233
}
203-
}()
204-
<-done
205-
206-
if client.UniversalClient == nil {
207-
return nil
208234
}
209235

210-
for _, name := range client.name {
211-
m.RedisConnections[name] = client
236+
return opts
237+
}
238+
239+
// getRedisTlsOptions parses RedisUri TLS configuration parameters and converts them to the go TLS configuration
240+
// equivalent fields.
241+
func getRedisTLSOptions(uri *url.URL) *tls.Config {
242+
tlsConfig := &tls.Config{}
243+
244+
skipverify := uri.Query().Get("skipverify")
245+
246+
if len(skipverify) > 0 {
247+
skipverify, err := strconv.ParseBool(skipverify)
248+
if err != nil {
249+
tlsConfig.InsecureSkipVerify = skipverify
250+
}
212251
}
213252

214-
client.count++
253+
insecureskipverify := uri.Query().Get("insecureskipverify")
215254

216-
return client
255+
if len(insecureskipverify) > 0 {
256+
insecureskipverify, err := strconv.ParseBool(insecureskipverify)
257+
if err != nil {
258+
tlsConfig.InsecureSkipVerify = insecureskipverify
259+
}
260+
}
261+
262+
return tlsConfig
217263
}

0 commit comments

Comments
 (0)