-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Reroute 'ALTER VITESS_MIGRATION ... THROTTLE ...' through topo #13511
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,11 +35,14 @@ import ( | |
|
|
||
| "vitess.io/vitess/go/test/endtoend/cluster" | ||
|
|
||
| "github.com/buger/jsonparser" | ||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| const ( | ||
| ThrottledAppsTimeout = 60 * time.Second | ||
| ) | ||
|
|
||
| // VtgateExecQuery runs a query on VTGate using given query params | ||
| func VtgateExecQuery(t *testing.T, vtParams *mysql.ConnParams, query string, expectError string) *sqltypes.Result { | ||
| t.Helper() | ||
|
|
@@ -313,16 +316,35 @@ func UnthrottleAllMigrations(t *testing.T, vtParams *mysql.ConnParams) { | |
|
|
||
| // CheckThrottledApps checks for existence or non-existence of an app in the throttled apps list | ||
| func CheckThrottledApps(t *testing.T, vtParams *mysql.ConnParams, throttlerApp throttlerapp.Name, expectFind bool) { | ||
| query := "show vitess_throttled_apps" | ||
| r := VtgateExecQuery(t, vtParams, query, "") | ||
|
|
||
| found := false | ||
| for _, row := range r.Named().Rows { | ||
| if throttlerApp.Equals(row.AsString("app", "")) { | ||
| found = true | ||
| ctx, cancel := context.WithTimeout(context.Background(), ThrottledAppsTimeout) | ||
| defer cancel() | ||
|
|
||
| ticker := time.NewTicker(time.Second) | ||
| defer ticker.Stop() | ||
|
|
||
| for { | ||
| query := "show vitess_throttled_apps" | ||
| r := VtgateExecQuery(t, vtParams, query, "") | ||
|
|
||
| appFound := false | ||
| for _, row := range r.Named().Rows { | ||
| if throttlerApp.Equals(row.AsString("app", "")) { | ||
| appFound = true | ||
| } | ||
| } | ||
| if appFound == expectFind { | ||
| // we're all good | ||
| return | ||
| } | ||
|
|
||
| select { | ||
| case <-ctx.Done(): | ||
| assert.Failf(t, "CheckThrottledApps timed out waiting for %v to be in throttled status '%v'", throttlerApp.String(), expectFind) | ||
| return | ||
| case <-ticker.C: | ||
| } | ||
| } | ||
| assert.Equal(t, expectFind, found, "check app %v in throttled apps: %v", throttlerApp, found) | ||
| } | ||
|
|
||
| // WaitForThrottledTimestamp waits for a migration to have a non-empty last_throttled_timestamp | ||
|
|
@@ -350,33 +372,6 @@ func WaitForThrottledTimestamp(t *testing.T, vtParams *mysql.ConnParams, uuid st | |
| return | ||
| } | ||
|
|
||
| // WaitForThrottlerStatusEnabled waits for a tablet to report its throttler status as enabled. | ||
| func WaitForThrottlerStatusEnabled(t *testing.T, tablet *cluster.Vttablet, timeout time.Duration) { | ||
| jsonPath := "IsEnabled" | ||
| url := fmt.Sprintf("http://localhost:%d/throttler/status", tablet.HTTPPort) | ||
|
|
||
| ctx, cancel := context.WithTimeout(context.Background(), throttlerConfigTimeout) | ||
| defer cancel() | ||
|
|
||
| ticker := time.NewTicker(time.Second) | ||
| defer ticker.Stop() | ||
|
|
||
| for { | ||
| body := getHTTPBody(url) | ||
| val, err := jsonparser.GetBoolean([]byte(body), jsonPath) | ||
| require.NoError(t, err) | ||
| if val { | ||
| return | ||
| } | ||
| select { | ||
| case <-ctx.Done(): | ||
| t.Error("timeout waiting for tablet's throttler status to be enabled") | ||
| return | ||
| case <-ticker.C: | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This here is just code I found was unused. |
||
| func getHTTPBody(url string) string { | ||
| resp, err := http.Get(url) | ||
| if err != nil { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -210,19 +210,23 @@ func UnthrottleApp(clusterInstance *cluster.LocalProcessCluster, throttlerApp th | |
| return throttleApp(clusterInstance, throttlerApp, false) | ||
| } | ||
|
|
||
| // ThrottleAppAndWaitUntilTabletsConfirm | ||
| func ThrottleAppAndWaitUntilTabletsConfirm(t *testing.T, clusterInstance *cluster.LocalProcessCluster, throttlerApp throttlerapp.Name) (string, error) { | ||
| res, err := throttleApp(clusterInstance, throttlerApp, true) | ||
| if err != nil { | ||
| return res, err | ||
| } | ||
| func WaitUntilTabletsConfirmThrottledApp(t *testing.T, clusterInstance *cluster.LocalProcessCluster, throttlerApp throttlerapp.Name, expectThrottled bool) { | ||
| for _, ks := range clusterInstance.Keyspaces { | ||
| for _, shard := range ks.Shards { | ||
| for _, tablet := range shard.Vttablets { | ||
| WaitForThrottledApp(t, tablet, throttlerApp, true, ConfigTimeout) | ||
| WaitForThrottledApp(t, tablet, throttlerApp, expectThrottled, ConfigTimeout) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // ThrottleAppAndWaitUntilTabletsConfirm | ||
| func ThrottleAppAndWaitUntilTabletsConfirm(t *testing.T, clusterInstance *cluster.LocalProcessCluster, throttlerApp throttlerapp.Name) (string, error) { | ||
| res, err := throttleApp(clusterInstance, throttlerApp, true) | ||
| if err != nil { | ||
| return res, err | ||
| } | ||
| WaitUntilTabletsConfirmThrottledApp(t, clusterInstance, throttlerApp, true) | ||
| return res, nil | ||
| } | ||
|
|
||
|
|
@@ -232,13 +236,7 @@ func UnthrottleAppAndWaitUntilTabletsConfirm(t *testing.T, clusterInstance *clus | |
| if err != nil { | ||
| return res, err | ||
| } | ||
| for _, ks := range clusterInstance.Keyspaces { | ||
| for _, shard := range ks.Shards { | ||
| for _, tablet := range shard.Vttablets { | ||
| WaitForThrottledApp(t, tablet, throttlerApp, false, ConfigTimeout) | ||
| } | ||
| } | ||
| } | ||
| WaitUntilTabletsConfirmThrottledApp(t, clusterInstance, throttlerApp, false) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changes in this file are just a simple refactor into a function. Not really related to the overall changes in the PR. |
||
| return res, nil | ||
| } | ||
|
|
||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| /* | ||
| Copyright 2023 The Vitess Authors. | ||
|
|
||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||
| you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
|
|
||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the License for the specific language governing permissions and | ||
| limitations under the License. | ||
| */ | ||
|
|
||
| package engine | ||
|
|
||
| import ( | ||
| "context" | ||
|
|
||
| "vitess.io/vitess/go/sqltypes" | ||
| querypb "vitess.io/vitess/go/vt/proto/query" | ||
| topodatapb "vitess.io/vitess/go/vt/proto/topodata" | ||
| vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" | ||
| "vitess.io/vitess/go/vt/vterrors" | ||
| "vitess.io/vitess/go/vt/vtgate/vindexes" | ||
| ) | ||
|
|
||
| var _ Primitive = (*ThrottleApp)(nil) | ||
|
|
||
| // ThrottleApp represents the instructions to perform an online schema change via vtctld | ||
| type ThrottleApp struct { | ||
| Keyspace *vindexes.Keyspace | ||
| ThrottledAppRule *topodatapb.ThrottledAppRule | ||
|
|
||
| noTxNeeded | ||
|
|
||
| noInputs | ||
| } | ||
|
|
||
| func (v *ThrottleApp) description() PrimitiveDescription { | ||
| return PrimitiveDescription{ | ||
| OperatorType: "ThrottleApp", | ||
| Keyspace: v.Keyspace, | ||
| Other: map[string]any{ | ||
| "appName": v.ThrottledAppRule.Name, | ||
| "expireAt": v.ThrottledAppRule.ExpiresAt, | ||
| "ratio": v.ThrottledAppRule.Ratio, | ||
| }, | ||
| } | ||
| } | ||
|
|
||
| // RouteType implements the Primitive interface | ||
| func (v *ThrottleApp) RouteType() string { | ||
| return "ThrottleApp" | ||
| } | ||
|
|
||
| // GetKeyspaceName implements the Primitive interface | ||
| func (v *ThrottleApp) GetKeyspaceName() string { | ||
| return v.Keyspace.Name | ||
| } | ||
|
|
||
| // GetTableName implements the Primitive interface | ||
| func (v *ThrottleApp) GetTableName() string { | ||
| return "" | ||
| } | ||
|
|
||
| // TryExecute implements the Primitive interface | ||
| func (v *ThrottleApp) TryExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool) (result *sqltypes.Result, err error) { | ||
| if err := vcursor.ThrottleApp(ctx, v.ThrottledAppRule); err != nil { | ||
| return nil, err | ||
| } | ||
| return &sqltypes.Result{}, nil | ||
| } | ||
|
|
||
| // TryStreamExecute implements the Primitive interface | ||
| func (v *ThrottleApp) TryStreamExecute(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable, wantfields bool, callback func(*sqltypes.Result) error) error { | ||
| results, err := v.TryExecute(ctx, vcursor, bindVars, wantfields) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| return callback(results) | ||
| } | ||
|
|
||
| // GetFields implements the Primitive interface | ||
| func (v *ThrottleApp) GetFields(ctx context.Context, vcursor VCursor, bindVars map[string]*querypb.BindVariable) (*sqltypes.Result, error) { | ||
| return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] GetFields is not reachable") | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding a "wait-for", because
onlineddl.ThrottleAllMigrationsis now an async flow.