Skip to content

Commit f7c98e5

Browse files
mhamza15timvaillancourt
authored andcommitted
mysqlctl: propagate remote shutdown timeout (vitessio#20059)
Signed-off-by: Mohamed Hamza <mhamza@fastmail.com> Signed-off-by: Tim Vaillancourt <tim@timvaillancourt.com>
1 parent 5cee86c commit f7c98e5

4 files changed

Lines changed: 77 additions & 4 deletions

File tree

go/vt/mysqlctl/grpcmysqlctlclient/client.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"google.golang.org/grpc/credentials/insecure"
3030
"google.golang.org/grpc/status"
3131

32+
"vitess.io/vitess/go/protoutil"
3233
"vitess.io/vitess/go/vt/grpcclient"
3334
"vitess.io/vitess/go/vt/mysqlctl/mysqlctlclient"
3435

@@ -73,10 +74,11 @@ func (c *client) Start(ctx context.Context, mysqldArgs ...string) error {
7374
}
7475

7576
// Shutdown is part of the MysqlctlClient interface.
76-
func (c *client) Shutdown(ctx context.Context, waitForMysqld bool) error {
77+
func (c *client) Shutdown(ctx context.Context, waitForMysqld bool, shutdownTimeout time.Duration) error {
7778
return c.withRetry(ctx, func() error {
7879
_, err := c.c.Shutdown(ctx, &mysqlctlpb.ShutdownRequest{
79-
WaitForMysqld: waitForMysqld,
80+
WaitForMysqld: waitForMysqld,
81+
MysqlShutdownTimeout: protoutil.DurationToProto(shutdownTimeout),
8082
})
8183
return err
8284
})

go/vt/mysqlctl/mysqlctlclient/interface.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"context"
2323
"fmt"
2424
"os"
25+
"time"
2526

2627
"github.com/spf13/pflag"
2728

@@ -47,7 +48,7 @@ type MysqlctlClient interface {
4748
Start(ctx context.Context, mysqldArgs ...string) error
4849

4950
// Shutdown calls Mysqld.Shutdown remotely.
50-
Shutdown(ctx context.Context, waitForMysqld bool) error
51+
Shutdown(ctx context.Context, waitForMysqld bool, shutdownTimeout time.Duration) error
5152

5253
// RunMysqlUpgrade calls Mysqld.RunMysqlUpgrade remotely.
5354
RunMysqlUpgrade(ctx context.Context) error

go/vt/mysqlctl/mysqld.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ func (mysqld *Mysqld) Shutdown(ctx context.Context, cnf *Mycnf, waitForMysqld bo
632632
return fmt.Errorf("can't dial mysqlctld: %v", err)
633633
}
634634
defer client.Close()
635-
return client.Shutdown(ctx, waitForMysqld)
635+
return client.Shutdown(ctx, waitForMysqld, shutdownTimeout)
636636
}
637637

638638
// We're shutting down on purpose. We no longer want to be notified when

go/vt/mysqlctl/mysqld_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ limitations under the License.
1717
package mysqlctl
1818

1919
import (
20+
"context"
21+
"net"
2022
"os"
2123
"strconv"
2224
"strings"
@@ -25,10 +27,14 @@ import (
2527

2628
"github.com/stretchr/testify/assert"
2729
"github.com/stretchr/testify/require"
30+
"google.golang.org/grpc"
2831

2932
"vitess.io/vitess/go/mysql/fakesqldb"
33+
"vitess.io/vitess/go/protoutil"
3034
"vitess.io/vitess/go/sqltypes"
3135
"vitess.io/vitess/go/vt/dbconfigs"
36+
_ "vitess.io/vitess/go/vt/mysqlctl/grpcmysqlctlclient"
37+
mysqlctlpb "vitess.io/vitess/go/vt/proto/mysqlctl"
3238
)
3339

3440
type testcase struct {
@@ -114,6 +120,70 @@ func TestParseVersionString(t *testing.T) {
114120
}
115121
}
116122

123+
// shutdownRecordingMysqlCtlServer records remote Shutdown requests from Mysqld.
124+
type shutdownRecordingMysqlCtlServer struct {
125+
mysqlctlpb.UnimplementedMysqlCtlServer
126+
127+
// shutdownRequests carries the remote shutdown request.
128+
shutdownRequests chan *mysqlctlpb.ShutdownRequest
129+
}
130+
131+
// Shutdown records the request and returns a successful response.
132+
func (s *shutdownRecordingMysqlCtlServer) Shutdown(ctx context.Context, request *mysqlctlpb.ShutdownRequest) (*mysqlctlpb.ShutdownResponse, error) {
133+
s.shutdownRequests <- request
134+
135+
return &mysqlctlpb.ShutdownResponse{}, nil
136+
}
137+
138+
// TestMysqldShutdownForwardsTimeoutToRemoteMysqlctld verifies that the remote
139+
// shutdown path preserves the caller's timeout.
140+
func TestMysqldShutdownForwardsTimeoutToRemoteMysqlctld(t *testing.T) {
141+
ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second)
142+
t.Cleanup(cancel)
143+
144+
oldSocketFile := socketFile
145+
t.Cleanup(func() {
146+
socketFile = oldSocketFile
147+
})
148+
149+
tempSocketFile, err := os.CreateTemp("/tmp", "mysqlctld-*.sock")
150+
require.NoError(t, err)
151+
require.NoError(t, tempSocketFile.Close())
152+
require.NoError(t, os.Remove(tempSocketFile.Name()))
153+
t.Cleanup(func() {
154+
_ = os.Remove(tempSocketFile.Name())
155+
})
156+
157+
socketPath := tempSocketFile.Name()
158+
listener, err := net.Listen("unix", socketPath)
159+
require.NoError(t, err)
160+
161+
server := grpc.NewServer()
162+
t.Cleanup(server.Stop)
163+
164+
recordingServer := &shutdownRecordingMysqlCtlServer{
165+
shutdownRequests: make(chan *mysqlctlpb.ShutdownRequest, 1),
166+
}
167+
mysqlctlpb.RegisterMysqlCtlServer(server, recordingServer)
168+
169+
go func() { _ = server.Serve(listener) }()
170+
171+
socketFile = socketPath
172+
shutdownTimeout := 43*time.Second + 125*time.Millisecond
173+
174+
mysqld := &Mysqld{}
175+
err = mysqld.Shutdown(ctx, &Mycnf{}, true, shutdownTimeout)
176+
require.NoError(t, err)
177+
178+
request := <-recordingServer.shutdownRequests
179+
assert.True(t, request.WaitForMysqld)
180+
181+
gotTimeout, ok, err := protoutil.DurationFromProto(request.MysqlShutdownTimeout)
182+
require.NoError(t, err)
183+
require.True(t, ok)
184+
assert.Equal(t, shutdownTimeout, gotTimeout)
185+
}
186+
117187
func TestRegexps(t *testing.T) {
118188
{
119189
submatch := binlogEntryTimestampGTIDRegexp.FindStringSubmatch(`#230608 13:14:31 server id 484362839 end_log_pos 259 CRC32 0xc07510d0 GTID last_committed=0 sequence_number=1 rbr_only=yes`)

0 commit comments

Comments
 (0)