1515package handlers
1616
1717import (
18- "fmt "
18+ "maps "
1919 "net/http"
2020 "sort"
2121
2222 "github.com/gin-gonic/gin"
2323 "github.com/tikv/pd/pkg/errs"
24+ "github.com/tikv/pd/pkg/keyspace"
2425 "github.com/tikv/pd/server"
2526 "github.com/tikv/pd/server/apiv2/middlewares"
2627)
2728
2829const (
2930 metaServiceGroupUninitializedErr = "meta-service groups manager is not initialized"
30- metaServiceGroupAlreadyExistsErr = "meta-service group %s already exists"
3131)
3232
3333// RegisterMetaServiceGroup registers meta-service group related handlers to router paths.
3434func RegisterMetaServiceGroup (r * gin.RouterGroup ) {
3535 router := r .Group ("meta-service-groups" )
3636 router .Use (middlewares .BootstrapChecker ())
3737 router .GET ("" , GetMetaServiceGroups )
38- router .POST ("" , AddMetaServiceGroups )
38+ router .PATCH ("" , PatchMetaServiceGroups )
3939}
4040
4141// MetaServiceGroupStatus represents the status of a meta-service group.
4242// NOTE: This type is exported by HTTP API. Please pay more attention when modifying it.
4343type MetaServiceGroupStatus struct {
44- ID string `json:"id"`
45- Addresses string `json:"addresses"`
46- AssignedKeyspaces int `json:"assigned_keyspaces"`
47- }
48-
49- // AddMetaServiceGroupRequest represents a request to add a meta-service group.
50- // NOTE: This type is exported by HTTP API. Please pay more attention when modifying it.
51- type AddMetaServiceGroupRequest struct {
52- ID string `json:"id"`
44+ // ID is the unique identifier of the meta-service group.
45+ ID string `json:"id"`
46+ // Addresses is a comma-separated list of addresses for the meta-service group.
5347 Addresses string `json:"addresses"`
48+ // AssignedKeyspaces is the number of keyspaces assigned to this meta-service group.
49+ AssignedKeyspaces int `json:"assigned_keyspaces"`
5450}
5551
56- // AddMetaServiceGroups adds one or more meta-service groups as specified in the request .
52+ // PatchMetaServiceGroups applies a JSON Merge Patch to the meta-service groups.
5753//
5854// @Tags meta-service-groups
59- // @Summary Adds new meta-service groups.
60- // @Param body body []AddMetaServiceGroupRequest true "List of meta-service groups to add"
55+ // @Summary Patch meta-service groups using JSON Merge Patch .
56+ // @Param body body object true "JSON Merge Patch for meta-service groups (string values for add/update, null for delete) "
6157// @Produce json
62- // @Success 200 {object} []MetaServiceGroupStatus "List of newly added plus existing groups "
63- // @Failure 400 {string} string "Bad request (invalid JSON or duplicate group )"
58+ // @Success 200 {object} []MetaServiceGroupStatus "List of all meta-service groups after patch "
59+ // @Failure 400 {string} string "Bad request (invalid JSON or invalid operation )"
6460// @Failure 500 {string} string "Internal server error"
65- // @Router /meta-service-groups [post ]
66- func AddMetaServiceGroups (c * gin.Context ) {
61+ // @Router /meta-service-groups [patch ]
62+ func PatchMetaServiceGroups (c * gin.Context ) {
6763 svr := c .MustGet (middlewares .ServerContextKey ).(* server.Server )
6864 manager := svr .GetMetaServiceGroupManager ()
6965 if manager == nil {
7066 c .AbortWithStatusJSON (http .StatusInternalServerError , metaServiceGroupUninitializedErr )
7167 return
7268 }
7369
74- var requests []AddMetaServiceGroupRequest
75- err := c .BindJSON (& requests )
76- if err != nil {
70+ var patch map [string ]* string
71+ if err := c .BindJSON (& patch ); err != nil {
7772 c .AbortWithStatusJSON (http .StatusBadRequest , errs .ErrBindJSON .Wrap (err ).GenWithStackByCause ())
7873 return
7974 }
80- // Constructs new meta-service groups.
75+
8176 currentGroups := manager .GetGroups ()
8277 newGroups := make (map [string ]string )
83- for _ , request := range requests {
84- // Update existing newGroups is not allowed via the post-method.
85- if _ , exists := currentGroups [request .ID ]; exists {
86- c .AbortWithStatusJSON (http .StatusBadRequest , fmt .Errorf (metaServiceGroupAlreadyExistsErr , request .ID ))
87- return
78+ maps .Copy (newGroups , currentGroups )
79+
80+ for id , addresses := range patch {
81+ if addresses == nil {
82+ // Remove operation
83+ delete (newGroups , id )
84+ } else {
85+ // Add or update operation
86+ newGroups [id ] = * addresses
8887 }
89- newGroups [request .ID ] = request .Addresses
9088 }
91- for id , addresses := range currentGroups {
92- newGroups [id ] = addresses
93- }
94- // Update persisted pd config.
89+
9590 keyspaceCfg := svr .GetConfig ().Keyspace
9691 keyspaceCfg .MetaServiceGroups = newGroups
97- if err = svr .SetKeyspaceConfig (keyspaceCfg ); err != nil {
92+ if err : = svr .SetKeyspaceConfig (keyspaceCfg ); err != nil {
9893 c .AbortWithStatusJSON (http .StatusInternalServerError , err .Error ())
9994 return
10095 }
10196
102- assignmentCounts , err := manager . GetAssignmentCounts ( )
97+ status , err := buildMetaServiceGroupStatus ( manager )
10398 if err != nil {
10499 c .AbortWithStatusJSON (http .StatusInternalServerError , err .Error ())
105100 return
106101 }
107- response := make ([]MetaServiceGroupStatus , 0 , len (newGroups ))
108- for id , addresses := range newGroups {
109- response = append (response , MetaServiceGroupStatus {
110- ID : id ,
111- Addresses : addresses ,
112- AssignedKeyspaces : assignmentCounts [id ],
113- })
114- }
115- c .IndentedJSON (http .StatusOK , response )
102+ c .IndentedJSON (http .StatusOK , status )
116103}
117104
118105// GetMetaServiceGroups returns a list of all meta-service groups and their assignment counts.
@@ -131,24 +118,32 @@ func GetMetaServiceGroups(c *gin.Context) {
131118 return
132119 }
133120
134- groups := manager .GetGroups ()
135- assignmentCounts , err := manager .GetAssignmentCounts ()
121+ status , err := buildMetaServiceGroupStatus (manager )
136122 if err != nil {
137123 c .AbortWithStatusJSON (http .StatusInternalServerError , err .Error ())
138124 return
139125 }
126+ c .IndentedJSON (http .StatusOK , status )
127+ }
140128
141- response := make ([]MetaServiceGroupStatus , 0 , len (groups ))
142- for id , addresses := range groups {
143- response = append (response , MetaServiceGroupStatus {
129+ func buildMetaServiceGroupStatus (manager * keyspace.MetaServiceGroupManager ) ([]MetaServiceGroupStatus , error ) {
130+ currentGroups := manager .GetGroups ()
131+ assignmentCounts , err := manager .GetAssignmentCounts ()
132+ if err != nil {
133+ return nil , err
134+ }
135+
136+ status := make ([]MetaServiceGroupStatus , 0 , len (currentGroups ))
137+ for id , addresses := range currentGroups {
138+ status = append (status , MetaServiceGroupStatus {
144139 ID : id ,
145140 Addresses : addresses ,
146141 AssignedKeyspaces : assignmentCounts [id ],
147142 })
148143 }
149144 // sort for deterministic output
150- sort .Slice (response , func (i , j int ) bool {
151- return response [i ].ID < response [j ].ID
145+ sort .Slice (status , func (i , j int ) bool {
146+ return status [i ].ID < status [j ].ID
152147 })
153- c . IndentedJSON ( http . StatusOK , response )
148+ return status , nil
154149}
0 commit comments