Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions client/http/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func (ci *clientInner) requestWithRetry(
continue
}
statusCode, err = ci.doRequest(ctx, serverURL, reqInfo, headerOpts...)
if err == nil || noNeedRetry(statusCode) {
if err == nil || noNeedRetryForRequest(reqInfo, statusCode) {
return err
}
log.Debug("[pd] http request url failed", append(logFields,
Expand All @@ -177,7 +177,7 @@ func (ci *clientInner) requestWithRetry(
// Set the retryable checker for the backoffer if it's not set.
bo.SetRetryableChecker(func(err error) bool {
// Backoffer also needs to check the status code to determine whether to retry.
return err != nil && !noNeedRetry(statusCode)
return err != nil && !noNeedRetryForRequest(reqInfo, statusCode)
}, false)
return bo.Exec(ctx, execFunc)
}
Expand All @@ -188,6 +188,13 @@ func noNeedRetry(statusCode int) bool {
statusCode == http.StatusBadRequest
}

func noNeedRetryForRequest(reqInfo *requestInfo, statusCode int) bool {
if noNeedRetry(statusCode) {
return true
}
return reqInfo.name == UpdateKeyspaceConfigName && statusCode == http.StatusConflict
}

func (ci *clientInner) doRequest(
ctx context.Context,
serverURL string, reqInfo *requestInfo,
Expand Down
72 changes: 29 additions & 43 deletions client/http/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ type Client interface {

/* Keyspace interface */

// UpdateKeyspaceConfig patches the keyspace config and returns the updated keyspace meta.
UpdateKeyspaceConfig(ctx context.Context, keyspaceName string, params *UpdateKeyspaceConfigParams) (*keyspacepb.KeyspaceMeta, error)
// UpdateKeyspaceGCManagementType update the `gc_management_type` in keyspace meta config.
// If `gc_management_type` is `global_gc`, it means the current keyspace requires a tidb without 'keyspace-name'
// configured to run a global gc worker to calculate a global gc safe point.
Expand Down Expand Up @@ -1143,25 +1145,38 @@ func (c *client) DeleteOperators(ctx context.Context) error {
WithMethod(http.MethodDelete))
}

// UpdateKeyspaceGCManagementType patches the keyspace config.
func (c *client) UpdateKeyspaceGCManagementType(ctx context.Context, keyspaceName string, keyspaceGCmanagementType *KeyspaceGCManagementTypeConfig) error {
keyspaceConfigPatchJSON, err := json.Marshal(keyspaceGCmanagementType)
func (c *client) patchKeyspaceConfig(ctx context.Context, reqName, keyspaceName string, params any) (*keyspacepb.KeyspaceMeta, error) {
var tempMeta tempKeyspaceMeta
keyspaceConfigPatchJSON, err := json.Marshal(params)
if err != nil {
return errors.Trace(err)
return nil, errors.Trace(err)
}
return c.request(ctx, newRequestInfo().
WithName(UpdateKeyspaceGCManagementTypeName).
err = c.request(ctx, newRequestInfo().
WithName(reqName).
WithURI(GetUpdateKeyspaceConfigURL(keyspaceName)).
WithMethod(http.MethodPatch).
WithBody(keyspaceConfigPatchJSON))
WithBody(keyspaceConfigPatchJSON).
WithResp(&tempMeta))
if err != nil {
return nil, err
}
return tempMeta.toPB()
}

// UpdateKeyspaceConfig patches the keyspace config.
func (c *client) UpdateKeyspaceConfig(ctx context.Context, keyspaceName string, params *UpdateKeyspaceConfigParams) (*keyspacepb.KeyspaceMeta, error) {
return c.patchKeyspaceConfig(ctx, UpdateKeyspaceConfigName, keyspaceName, params)
}

// UpdateKeyspaceGCManagementType patches the keyspace config.
func (c *client) UpdateKeyspaceGCManagementType(ctx context.Context, keyspaceName string, keyspaceGCmanagementType *KeyspaceGCManagementTypeConfig) error {
_, err := c.patchKeyspaceConfig(ctx, UpdateKeyspaceGCManagementTypeName, keyspaceName, keyspaceGCmanagementType)
return err
}

// GetKeyspaceMetaByName get the given keyspace meta.
func (c *client) GetKeyspaceMetaByName(ctx context.Context, keyspaceName string) (*keyspacepb.KeyspaceMeta, error) {
var (
tempKeyspaceMeta tempKeyspaceMeta
keyspaceMetaPB keyspacepb.KeyspaceMeta
)
var tempKeyspaceMeta tempKeyspaceMeta
err := c.request(ctx, newRequestInfo().
WithName(GetKeyspaceMetaByNameName).
WithURI(GetKeyspaceMetaByNameURL(keyspaceName)).
Expand All @@ -1172,28 +1187,12 @@ func (c *client) GetKeyspaceMetaByName(ctx context.Context, keyspaceName string)
return nil, err
}

keyspaceState, err := stringToKeyspaceState(tempKeyspaceMeta.State)
if err != nil {
return nil, err
}

keyspaceMetaPB = keyspacepb.KeyspaceMeta{
Name: tempKeyspaceMeta.Name,
Id: tempKeyspaceMeta.ID,
Config: tempKeyspaceMeta.Config,
CreatedAt: tempKeyspaceMeta.CreatedAt,
StateChangedAt: tempKeyspaceMeta.StateChangedAt,
State: keyspaceState,
}
return &keyspaceMetaPB, nil
return tempKeyspaceMeta.toPB()
}

// GetKeyspaceMetaByID get the given keyspace meta.
func (c *client) GetKeyspaceMetaByID(ctx context.Context, keyspaceID uint32) (*keyspacepb.KeyspaceMeta, error) {
var (
tempKeyspaceMeta tempKeyspaceMeta
keyspaceMetaPB keyspacepb.KeyspaceMeta
)
var tempKeyspaceMeta tempKeyspaceMeta
err := c.request(ctx, newRequestInfo().
WithName(GetKeyspaceMetaByIDName).
WithURI(GetKeyspaceMetaByIDURL(keyspaceID)).
Expand All @@ -1204,20 +1203,7 @@ func (c *client) GetKeyspaceMetaByID(ctx context.Context, keyspaceID uint32) (*k
return nil, err
}

keyspaceState, err := stringToKeyspaceState(tempKeyspaceMeta.State)
if err != nil {
return nil, err
}

keyspaceMetaPB = keyspacepb.KeyspaceMeta{
Name: tempKeyspaceMeta.Name,
Id: tempKeyspaceMeta.ID,
Config: tempKeyspaceMeta.Config,
CreatedAt: tempKeyspaceMeta.CreatedAt,
StateChangedAt: tempKeyspaceMeta.StateChangedAt,
State: keyspaceState,
}
return &keyspaceMetaPB, nil
return tempKeyspaceMeta.toPB()
}

// GetGCSafePoint gets the GC safe point list.
Expand Down
1 change: 1 addition & 0 deletions client/http/request_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ const (
deletePitrRestoreModeMarkName = "DeletePitrRestoreModeMark"
createOperators = "CreateOperators"
deleteOperators = "DeleteOperators"
UpdateKeyspaceConfigName = "UpdateKeyspaceConfig"
UpdateKeyspaceGCManagementTypeName = "UpdateKeyspaceGCManagementType"
GetKeyspaceMetaByNameName = "GetKeyspaceMetaByName"
GetKeyspaceMetaByIDName = "GetKeyspaceMetaByID"
Expand Down
27 changes: 27 additions & 0 deletions client/http/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,17 @@ type KeyspaceGCManagementTypeConfig struct {
Config KeyspaceGCManagementType `json:"config"`
}

// UpdateKeyspaceConfigParams represents parameters needed to modify target keyspace configs.
// A map of string to string pointer is used to differentiate between json null and "",
// which will both be set to "" if value type is string during marshaling.
type UpdateKeyspaceConfigParams struct {
Config map[string]*string `json:"config"`
// Preconditions specifies prerequisites for updating config, using a JSON-merge-patch-like encoding:
// - key -> nil means the key must be absent.
// - key -> "value" means the key must exist and equal "value".
Preconditions map[string]*string `json:"preconditions,omitempty"`
}

// tempKeyspaceMeta is the keyspace meta struct that returned from the http interface.
type tempKeyspaceMeta struct {
ID uint32 `json:"id"`
Expand All @@ -685,6 +696,22 @@ type tempKeyspaceMeta struct {
Config map[string]string `json:"config"`
}

func (meta *tempKeyspaceMeta) toPB() (*keyspacepb.KeyspaceMeta, error) {
keyspaceState, err := stringToKeyspaceState(meta.State)
if err != nil {
return nil, err
}

return &keyspacepb.KeyspaceMeta{
Name: meta.Name,
Id: meta.ID,
Config: meta.Config,
CreatedAt: meta.CreatedAt,
StateChangedAt: meta.StateChangedAt,
State: keyspaceState,
}, nil
}

func stringToKeyspaceState(str string) (keyspacepb.KeyspaceState, error) {
switch str {
case "ENABLED":
Expand Down
67 changes: 67 additions & 0 deletions tests/integrations/client/http_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,73 @@ func (suite *httpClientTestSuite) TestUpdateKeyspaceGCManagementType() {
re.Error(err)
}

func (suite *httpClientTestSuite) TestUpdateKeyspaceConfig() {
re := suite.Require()
client := suite.client
ctx, cancel := context.WithCancel(suite.ctx)
defer cancel()

var keyspaceName string
if kerneltype.IsNextGen() {
keyspaceName = constant.SystemKeyspaceName
} else {
keyspaceName = constant.DefaultKeyspaceName
}

configKey := "http_client_test_update_keyspace_config"
initialValue := "v1"
updatedMeta, err := client.UpdateKeyspaceConfig(ctx, keyspaceName, &pd.UpdateKeyspaceConfigParams{
Config: map[string]*string{
configKey: &initialValue,
},
Preconditions: map[string]*string{
configKey: nil,
},
})
re.NoError(err)
re.NotNil(updatedMeta)
re.Equal(keyspaceName, updatedMeta.GetName())
re.Equal(initialValue, updatedMeta.GetConfig()[configKey])

keyspaceMetaRes, err := client.GetKeyspaceMetaByName(ctx, keyspaceName)
re.NoError(err)
val, ok := keyspaceMetaRes.Config[configKey]
re.True(ok)
re.Equal(initialValue, val)

wrongExpected := "wrong"
nextValue := "v2"
_, err = client.UpdateKeyspaceConfig(ctx, keyspaceName, &pd.UpdateKeyspaceConfigParams{
Config: map[string]*string{
configKey: &nextValue,
},
Preconditions: map[string]*string{
configKey: &wrongExpected,
},
})
re.Error(err)
re.Contains(err.Error(), "409 Conflict")
re.Contains(err.Error(), "precondition failed")

updatedMeta, err = client.UpdateKeyspaceConfig(ctx, keyspaceName, &pd.UpdateKeyspaceConfigParams{
Config: map[string]*string{
configKey: nil,
},
Preconditions: map[string]*string{
configKey: &initialValue,
},
})
re.NoError(err)
re.NotNil(updatedMeta)
_, ok = updatedMeta.Config[configKey]
re.False(ok)

keyspaceMetaRes, err = client.GetKeyspaceMetaByName(ctx, keyspaceName)
re.NoError(err)
_, ok = keyspaceMetaRes.Config[configKey]
re.False(ok)
}

func (suite *httpClientTestSuite) TestGetKeyspaceMetaByID() {
re := suite.Require()
client := suite.client
Expand Down
Loading