github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/cdc/api/v2/processor.go (about) 1 // Copyright 2023 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package v2 15 16 import ( 17 "fmt" 18 "net/http" 19 20 "github.com/gin-gonic/gin" 21 "github.com/pingcap/tiflow/cdc/api" 22 "github.com/pingcap/tiflow/cdc/model" 23 cerror "github.com/pingcap/tiflow/pkg/errors" 24 ) 25 26 // getProcessor gets the detailed info of a processor 27 // @Summary Get processor detail information 28 // @Description get the detail information of a processor 29 // @Tags processor,v2 30 // @Produce json 31 // @Success 200 {object} ProcessorDetail 32 // @Failure 500,400 {object} model.HTTPError 33 // @Param changefeed_id path string true "changefeed ID" 34 // @Param namespace query string false "default" 35 // @Param capture_id path string true "capture ID" 36 // @Router /api/v2/processors/{changefeed_id}/{capture_id} [get] 37 func (h *OpenAPIV2) getProcessor(c *gin.Context) { 38 ctx := c.Request.Context() 39 namespace := getNamespaceValueWithDefault(c) 40 changefeedID := model.ChangeFeedID{Namespace: namespace, ID: c.Param(api.APIOpVarChangefeedID)} 41 if err := model.ValidateChangefeedID(changefeedID.ID); err != nil { 42 _ = c.Error( 43 cerror.ErrAPIInvalidParam.GenWithStack( 44 "invalid changefeed_id: %s", 45 changefeedID.ID, 46 ), 47 ) 48 return 49 } 50 51 captureID := c.Param(apiOpVarCaptureID) 52 if err := model.ValidateChangefeedID(captureID); err != nil { 53 _ = c.Error( 54 cerror.ErrAPIInvalidParam.GenWithStack( 55 "invalid capture_id: %s", 56 captureID, 57 ), 58 ) 59 return 60 } 61 62 info, err := h.capture.StatusProvider().GetChangeFeedInfo( 63 ctx, 64 changefeedID, 65 ) 66 if err != nil { 67 _ = c.Error(err) 68 return 69 } 70 if !info.State.IsRunning() { 71 _ = c.Error( 72 cerror.WrapError( 73 cerror.ErrAPIInvalidParam, 74 fmt.Errorf("changefeed in abnormal state: %s, "+ 75 "can'duration get processor of an abnormal changefeed", 76 string(info.State), 77 ), 78 ), 79 ) 80 return 81 } 82 83 // check if this captureID exist 84 procInfos, err := h.capture.StatusProvider().GetProcessors(ctx) 85 if err != nil { 86 _ = c.Error(err) 87 return 88 } 89 var found bool 90 for _, info := range procInfos { 91 if info.CaptureID == captureID { 92 found = true 93 break 94 } 95 } 96 if !found { 97 _ = c.Error(cerror.ErrCaptureNotExist.GenWithStackByArgs(captureID)) 98 return 99 } 100 101 statuses, err := h.capture.StatusProvider().GetAllTaskStatuses( 102 ctx, 103 changefeedID, 104 ) 105 if err != nil { 106 _ = c.Error(err) 107 return 108 } 109 status, captureExist := statuses[captureID] 110 111 // Note: for the case that no tables are attached to a newly created 112 // changefeed, we just do not report an error. 113 var processorDetail ProcessorDetail 114 if captureExist { 115 tables := make([]int64, 0) 116 for tableID := range status.Tables { 117 tables = append(tables, tableID) 118 } 119 processorDetail.Tables = tables 120 } 121 c.JSON(http.StatusOK, &processorDetail) 122 } 123 124 // listProcessors lists all processors in the TiCDC cluster 125 // @Summary List processors 126 // @Description list all processors in the TiCDC cluster 127 // @Tags processor,v2 128 // @Produce json 129 // @Success 200 {array} ProcessorCommonInfo 130 // @Failure 500,400 {object} model.HTTPError 131 // @Router /api/v2/processors [get] 132 func (h *OpenAPIV2) listProcessors(c *gin.Context) { 133 ctx := c.Request.Context() 134 controller, err := h.capture.GetController() 135 if err != nil { 136 _ = c.Error(err) 137 return 138 } 139 infos, err := controller.GetProcessors(ctx) 140 if err != nil { 141 _ = c.Error(err) 142 return 143 } 144 prcInfos := make([]ProcessorCommonInfo, len(infos)) 145 for i, info := range infos { 146 resp := ProcessorCommonInfo{ 147 Namespace: info.CfID.Namespace, 148 ChangeFeedID: info.CfID.ID, 149 CaptureID: info.CaptureID, 150 } 151 prcInfos[i] = resp 152 } 153 resp := &ListResponse[ProcessorCommonInfo]{ 154 Total: len(prcInfos), 155 Items: prcInfos, 156 } 157 158 c.JSON(http.StatusOK, resp) 159 }