Skip to content

Commit 2628622

Browse files
authored
Merge branch 'main' into feature/reduce-cpu
2 parents 96e074e + ffa29f1 commit 2628622

15 files changed

Lines changed: 1071 additions & 27 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,4 @@ jepsen/.ssh/
3737
# Build and lint cache directories
3838
.cache/
3939
.golangci-cache/
40+
server

adapter/redis_lua_context.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,12 @@ func (c *luaScriptContext) materializeList(key []byte, st *luaListState) error {
486486
return nil
487487
}
488488

489-
values := make([]string, 0, st.currentLen())
489+
length := st.currentLen()
490+
maxInt64 := int64(math.MaxInt)
491+
if length > maxInt64 {
492+
length = maxInt64
493+
}
494+
values := make([]string, 0, int(length))
490495
values = append(values, st.leftValues...)
491496
if remaining := st.remainingOriginalLen(); remaining > 0 {
492497
start := st.leftTrim

cmd/server/demo.go

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ var (
3838
dynamoAddress = flag.String("dynamoAddress", ":8000", "DynamoDB-compatible API address")
3939
metricsAddress = flag.String("metricsAddress", "127.0.0.1:9090", "Prometheus metrics address")
4040
metricsToken = flag.String("metricsToken", "", "Bearer token for Prometheus metrics; required for non-loopback metricsAddress")
41+
pprofAddress = flag.String("pprofAddress", "localhost:6060", "TCP host+port for pprof debug endpoints; empty to disable")
42+
pprofToken = flag.String("pprofToken", "", "Bearer token for pprof; required for non-loopback pprofAddress")
4143
raftID = flag.String("raftId", "", "Raft ID")
4244
raftDataDir = flag.String("raftDataDir", "/var/lib/elastickv", "Raft data directory")
4345
raftBootstrap = flag.Bool("raftBootstrap", false, "Bootstrap cluster")
@@ -67,6 +69,8 @@ type config struct {
6769
dynamoAddress string
6870
metricsAddress string
6971
metricsToken string
72+
pprofAddress string
73+
pprofToken string
7074
raftID string
7175
raftDataDir string
7276
raftBootstrap bool
@@ -86,6 +90,8 @@ func main() {
8690
dynamoAddress: *dynamoAddress,
8791
metricsAddress: *metricsAddress,
8892
metricsToken: *metricsToken,
93+
pprofAddress: *pprofAddress,
94+
pprofToken: *pprofToken,
8995
raftID: *raftID,
9096
raftDataDir: *raftDataDir,
9197
raftBootstrap: *raftBootstrap,
@@ -106,6 +112,7 @@ func main() {
106112
dynamoAddress: "127.0.0.1:63801",
107113
metricsAddress: "0.0.0.0:9091",
108114
metricsToken: demoMetricsToken,
115+
pprofAddress: "127.0.0.1:6061",
109116
raftID: "n1",
110117
raftDataDir: "", // In-memory
111118
raftBootstrap: true,
@@ -116,6 +123,7 @@ func main() {
116123
dynamoAddress: "127.0.0.1:63802",
117124
metricsAddress: "0.0.0.0:9092",
118125
metricsToken: demoMetricsToken,
126+
pprofAddress: "127.0.0.1:6062",
119127
raftID: "n2",
120128
raftDataDir: "",
121129
raftBootstrap: false,
@@ -126,6 +134,7 @@ func main() {
126134
dynamoAddress: "127.0.0.1:63803",
127135
metricsAddress: "0.0.0.0:9093",
128136
metricsToken: demoMetricsToken,
137+
pprofAddress: "127.0.0.1:6063",
129138
raftID: "n3",
130139
raftDataDir: "",
131140
raftBootstrap: false,
@@ -443,15 +452,10 @@ func run(ctx context.Context, eg *errgroup.Group, cfg config) error {
443452
adapter.WithDynamoDBRequestObserver(metricsRegistry.DynamoDBObserver()),
444453
)
445454
cleanup.Add(ds.Stop)
446-
metricsL, ms, err := setupMetricsHTTPServer(ctx, lc, cfg.metricsAddress, cfg.metricsToken, metricsRegistry.Handler())
455+
metricsL, ms, pprofL, ps, err := setupObservabilityServers(ctx, lc, &cleanup, cfg, metricsRegistry.Handler())
447456
if err != nil {
448457
return err
449458
}
450-
if metricsL != nil {
451-
cleanup.Add(func() {
452-
_ = metricsL.Close()
453-
})
454-
}
455459

456460
eg.Go(catalogWatcherTask(ctx, distCatalog, distEngine))
457461
eg.Go(func() error { return compactor.Run(ctx) })
@@ -463,11 +467,31 @@ func run(ctx context.Context, eg *errgroup.Group, cfg config) error {
463467
eg.Go(dynamoServeTask(ds, cfg.dynamoAddress))
464468
eg.Go(monitoring.MetricsShutdownTask(ctx, ms, cfg.metricsAddress))
465469
eg.Go(monitoring.MetricsServeTask(ms, metricsL, cfg.metricsAddress))
470+
eg.Go(monitoring.PprofShutdownTask(ctx, ps, cfg.pprofAddress))
471+
eg.Go(monitoring.PprofServeTask(ps, pprofL, cfg.pprofAddress))
466472

467473
cleanup.Release()
468474
return nil
469475
}
470476

477+
func setupObservabilityServers(ctx context.Context, lc net.ListenConfig, cleanup *internalutil.CleanupStack, cfg config, metricsHandler http.Handler) (metricsL net.Listener, ms *http.Server, pprofL net.Listener, ps *http.Server, err error) {
478+
metricsL, ms, err = setupMetricsHTTPServer(ctx, lc, cfg.metricsAddress, cfg.metricsToken, metricsHandler)
479+
if err != nil {
480+
return
481+
}
482+
if metricsL != nil {
483+
cleanup.Add(func() { _ = metricsL.Close() })
484+
}
485+
pprofL, ps, err = setupPprofHTTPServer(ctx, lc, cfg.pprofAddress, cfg.pprofToken)
486+
if err != nil {
487+
return
488+
}
489+
if pprofL != nil {
490+
cleanup.Add(func() { _ = pprofL.Close() })
491+
}
492+
return
493+
}
494+
471495
func setupMetricsHTTPServer(ctx context.Context, lc net.ListenConfig, metricsAddress string, metricsToken string, handler http.Handler) (net.Listener, *http.Server, error) {
472496
metricsAddress = strings.TrimSpace(metricsAddress)
473497
if metricsAddress == "" || handler == nil {
@@ -476,7 +500,7 @@ func setupMetricsHTTPServer(ctx context.Context, lc net.ListenConfig, metricsAdd
476500
if _, _, err := net.SplitHostPort(metricsAddress); err != nil {
477501
return nil, nil, errors.Wrapf(err, "invalid metricsAddress %q", metricsAddress)
478502
}
479-
if monitoring.MetricsAddressRequiresToken(metricsAddress) && strings.TrimSpace(metricsToken) == "" {
503+
if monitoring.AddressRequiresToken(metricsAddress) && strings.TrimSpace(metricsToken) == "" {
480504
return nil, nil, errors.New("metricsToken is required when metricsAddress is not loopback")
481505
}
482506
metricsL, err := lc.Listen(ctx, "tcp", metricsAddress)
@@ -487,6 +511,25 @@ func setupMetricsHTTPServer(ctx context.Context, lc net.ListenConfig, metricsAdd
487511
return metricsL, ms, nil
488512
}
489513

514+
func setupPprofHTTPServer(ctx context.Context, lc net.ListenConfig, pprofAddress string, pprofToken string) (net.Listener, *http.Server, error) {
515+
pprofAddress = strings.TrimSpace(pprofAddress)
516+
if pprofAddress == "" {
517+
return nil, nil, nil
518+
}
519+
if _, _, err := net.SplitHostPort(pprofAddress); err != nil {
520+
return nil, nil, errors.Wrapf(err, "invalid pprofAddress %q", pprofAddress)
521+
}
522+
if monitoring.AddressRequiresToken(pprofAddress) && strings.TrimSpace(pprofToken) == "" {
523+
return nil, nil, errors.New("pprofToken is required when pprofAddress is not loopback")
524+
}
525+
pprofL, err := lc.Listen(ctx, "tcp", pprofAddress)
526+
if err != nil {
527+
return nil, nil, errors.WithStack(err)
528+
}
529+
ps := monitoring.NewPprofServer(pprofToken)
530+
return pprofL, ps, nil
531+
}
532+
490533
func bootstrapClusterIfNeeded(r *raft.Raft, cfg config) error {
491534
if !cfg.raftBootstrap {
492535
return nil

cmd/server/demo_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,17 @@ func TestSetupMetricsHTTPServerRejectsInvalidAddressBeforeTokenCheck(t *testing.
2727
require.Nil(t, listener)
2828
require.Nil(t, server)
2929
}
30+
31+
func TestSetupPprofHTTPServerAllowsBlankAddress(t *testing.T) {
32+
listener, server, err := setupPprofHTTPServer(context.Background(), net.ListenConfig{}, "", "")
33+
require.NoError(t, err)
34+
require.Nil(t, listener)
35+
require.Nil(t, server)
36+
}
37+
38+
func TestSetupPprofHTTPServerRejectsInvalidAddressBeforeTokenCheck(t *testing.T) {
39+
listener, server, err := setupPprofHTTPServer(context.Background(), net.ListenConfig{}, "localhost", "")
40+
require.ErrorContains(t, err, `invalid pprofAddress "localhost"`)
41+
require.Nil(t, listener)
42+
require.Nil(t, server)
43+
}

kv/txn_errors.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ func TxnLockedDetails(err error) ([]byte, string, bool) {
3939

4040
func (e *TxnLockedError) Error() string {
4141
if e.detail != "" {
42-
return fmt.Sprintf("key: %s (%s): %s", string(e.key), e.detail, ErrTxnLocked)
42+
return fmt.Sprintf("key: %s (%s): %v", string(e.key), e.detail, ErrTxnLocked)
4343
}
44-
return fmt.Sprintf("key: %s: %s", string(e.key), ErrTxnLocked)
44+
return fmt.Sprintf("key: %s: %v", string(e.key), ErrTxnLocked)
4545
}
4646

4747
func (e *TxnLockedError) Unwrap() error {

main.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ var (
3939
dynamoAddr = flag.String("dynamoAddress", "localhost:8000", "TCP host+port for DynamoDB-compatible API")
4040
metricsAddr = flag.String("metricsAddress", "localhost:9090", "TCP host+port for Prometheus metrics")
4141
metricsToken = flag.String("metricsToken", "", "Bearer token for Prometheus metrics; required for non-loopback metricsAddress")
42+
pprofAddr = flag.String("pprofAddress", "localhost:6060", "TCP host+port for pprof debug endpoints; empty to disable")
43+
pprofToken = flag.String("pprofToken", "", "Bearer token for pprof; required for non-loopback pprofAddress")
4244
raftId = flag.String("raftId", "", "Node id used by Raft")
4345
raftDir = flag.String("raftDataDir", "data/", "Raft data dir")
4446
raftBootstrap = flag.Bool("raftBootstrap", false, "Whether to bootstrap the Raft cluster")
@@ -133,6 +135,8 @@ func run() error {
133135
dynamoAddress: *dynamoAddr,
134136
metricsAddress: *metricsAddr,
135137
metricsToken: *metricsToken,
138+
pprofAddress: *pprofAddr,
139+
pprofToken: *pprofToken,
136140
metricsRegistry: metricsRegistry,
137141
}
138142
if err := runner.start(); err != nil {
@@ -415,6 +419,27 @@ func startDynamoDBServer(ctx context.Context, lc *net.ListenConfig, eg *errgroup
415419
return nil
416420
}
417421

422+
func startPprofServer(ctx context.Context, lc *net.ListenConfig, eg *errgroup.Group, pprofAddr string, pprofToken string) error {
423+
pprofAddr = strings.TrimSpace(pprofAddr)
424+
if pprofAddr == "" {
425+
return nil
426+
}
427+
if _, _, err := net.SplitHostPort(pprofAddr); err != nil {
428+
return errors.Wrapf(err, "invalid pprofAddress %q; expected host:port", pprofAddr)
429+
}
430+
if monitoring.AddressRequiresToken(pprofAddr) && strings.TrimSpace(pprofToken) == "" {
431+
return errors.New("pprofToken is required when pprofAddress is not loopback")
432+
}
433+
pprofL, err := lc.Listen(ctx, "tcp", pprofAddr)
434+
if err != nil {
435+
return errors.Wrapf(err, "failed to listen on %s", pprofAddr)
436+
}
437+
pprofServer := monitoring.NewPprofServer(pprofToken)
438+
eg.Go(monitoring.PprofShutdownTask(ctx, pprofServer, pprofAddr))
439+
eg.Go(monitoring.PprofServeTask(pprofServer, pprofL, pprofAddr))
440+
return nil
441+
}
442+
418443
func startMetricsServer(ctx context.Context, lc *net.ListenConfig, eg *errgroup.Group, metricsAddr string, metricsToken string, handler http.Handler) error {
419444
metricsAddr = strings.TrimSpace(metricsAddr)
420445
if metricsAddr == "" || handler == nil {
@@ -423,7 +448,7 @@ func startMetricsServer(ctx context.Context, lc *net.ListenConfig, eg *errgroup.
423448
if _, _, err := net.SplitHostPort(metricsAddr); err != nil {
424449
return errors.Wrapf(err, "invalid metricsAddress %q; expected host:port", metricsAddr)
425450
}
426-
if monitoring.MetricsAddressRequiresToken(metricsAddr) && strings.TrimSpace(metricsToken) == "" {
451+
if monitoring.AddressRequiresToken(metricsAddr) && strings.TrimSpace(metricsToken) == "" {
427452
return errors.New("metricsToken is required when metricsAddress is not loopback")
428453
}
429454
metricsL, err := lc.Listen(ctx, "tcp", metricsAddr)
@@ -516,6 +541,8 @@ type runtimeServerRunner struct {
516541
dynamoAddress string
517542
metricsAddress string
518543
metricsToken string
544+
pprofAddress string
545+
pprofToken string
519546
metricsRegistry *monitoring.Registry
520547
}
521548

@@ -532,5 +559,8 @@ func (r runtimeServerRunner) start() error {
532559
if err := startMetricsServer(r.ctx, r.lc, r.eg, r.metricsAddress, r.metricsToken, r.metricsRegistry.Handler()); err != nil {
533560
return waitErrgroupAfterStartupFailure(r.cancel, r.eg, err)
534561
}
562+
if err := startPprofServer(r.ctx, r.lc, r.eg, r.pprofAddress, r.pprofToken); err != nil {
563+
return waitErrgroupAfterStartupFailure(r.cancel, r.eg, err)
564+
}
535565
return nil
536566
}

main_pprof_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"net"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
"golang.org/x/sync/errgroup"
10+
)
11+
12+
func TestStartPprofServerRejectsInvalidAddressBeforeTokenCheck(t *testing.T) {
13+
eg, ctx := errgroup.WithContext(context.Background())
14+
err := startPprofServer(ctx, &net.ListenConfig{}, eg, "localhost", "")
15+
require.ErrorContains(t, err, `invalid pprofAddress "localhost"`)
16+
}
17+
18+
func TestStartPprofServerAllowsEmptyAddress(t *testing.T) {
19+
eg, ctx := errgroup.WithContext(context.Background())
20+
err := startPprofServer(ctx, &net.ListenConfig{}, eg, "", "")
21+
require.NoError(t, err)
22+
}

0 commit comments

Comments
 (0)