github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/cdc/owner/status_provider.go (about) 1 // Copyright 2021 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 owner 15 16 import ( 17 "context" 18 19 "github.com/pingcap/errors" 20 "github.com/pingcap/tiflow/cdc/model" 21 cerror "github.com/pingcap/tiflow/pkg/errors" 22 ) 23 24 // StatusProvider provide some func to get meta-information from owner 25 // The interface is thread-safe. 26 type StatusProvider interface { 27 // GetChangeFeedStatus returns a changefeeds' runtime status. 28 GetChangeFeedStatus(ctx context.Context, changefeedID model.ChangeFeedID) (*model.ChangeFeedStatusForAPI, error) 29 30 // GetChangeFeedSyncedStatus returns a changefeeds' synced status. 31 GetChangeFeedSyncedStatus(ctx context.Context, changefeedID model.ChangeFeedID) (*model.ChangeFeedSyncedStatusForAPI, error) 32 33 // GetChangeFeedInfo returns a changefeeds' info. 34 GetChangeFeedInfo(ctx context.Context, changefeedID model.ChangeFeedID) (*model.ChangeFeedInfo, error) 35 36 // GetAllTaskStatuses returns the task statuses for the specified changefeed. 37 GetAllTaskStatuses(ctx context.Context, changefeedID model.ChangeFeedID) (map[model.CaptureID]*model.TaskStatus, error) 38 39 // GetProcessors returns the statuses of all processors 40 GetProcessors(ctx context.Context) ([]*model.ProcInfoSnap, error) 41 42 // GetCaptures returns the information about all captures. 43 GetCaptures(ctx context.Context) ([]*model.CaptureInfo, error) 44 45 // IsHealthy return true if the cluster is healthy 46 IsHealthy(ctx context.Context) (bool, error) 47 // IsChangefeedOwner return true if this capture is the owner of the changefeed 48 IsChangefeedOwner(ctx context.Context, id model.ChangeFeedID) (bool, error) 49 } 50 51 // QueryType is the type of different queries. 52 type QueryType int32 53 54 const ( 55 // QueryAllTaskStatuses is the type of query all task statuses. 56 QueryAllTaskStatuses QueryType = iota 57 // QueryProcessors is the type of query processors. 58 QueryProcessors 59 // QueryCaptures is the type of query captures info. 60 QueryCaptures 61 // QueryHealth is the type of query cluster health info. 62 QueryHealth 63 // QueryOwner is the type of query changefeed owner 64 QueryOwner 65 // QueryChangefeedInfo is the type of query changefeed info 66 QueryChangefeedInfo 67 // QueryChangeFeedStatuses is the type of query changefeed status 68 QueryChangeFeedStatuses 69 // QueryChangeFeedSyncedStatus is the type of query changefeed synced status 70 QueryChangeFeedSyncedStatus 71 ) 72 73 // Query wraps query command and return results. 74 type Query struct { 75 Tp QueryType 76 ChangeFeedID model.ChangeFeedID 77 78 Data interface{} 79 } 80 81 // NewStatusProvider returns a new StatusProvider for the owner. 82 func NewStatusProvider(owner Owner) StatusProvider { 83 return &ownerStatusProvider{owner: owner} 84 } 85 86 type ownerStatusProvider struct { 87 owner Owner 88 } 89 90 func (p *ownerStatusProvider) GetChangeFeedStatus(ctx context.Context, 91 changefeedID model.ChangeFeedID, 92 ) (*model.ChangeFeedStatusForAPI, error) { 93 query := &Query{ 94 Tp: QueryChangeFeedStatuses, 95 ChangeFeedID: changefeedID, 96 } 97 if err := p.sendQueryToOwner(ctx, query); err != nil { 98 return nil, errors.Trace(err) 99 } 100 if query.Data == nil { 101 return nil, cerror.ErrChangeFeedNotExists.GenWithStackByArgs(changefeedID) 102 } 103 return query.Data.(*model.ChangeFeedStatusForAPI), nil 104 } 105 106 func (p *ownerStatusProvider) GetChangeFeedSyncedStatus(ctx context.Context, 107 changefeedID model.ChangeFeedID, 108 ) (*model.ChangeFeedSyncedStatusForAPI, error) { 109 query := &Query{ 110 Tp: QueryChangeFeedSyncedStatus, 111 ChangeFeedID: changefeedID, 112 } 113 if err := p.sendQueryToOwner(ctx, query); err != nil { 114 return nil, errors.Trace(err) 115 } 116 if query.Data == nil { 117 return nil, cerror.ErrChangeFeedNotExists.GenWithStackByArgs(changefeedID) 118 } 119 return query.Data.(*model.ChangeFeedSyncedStatusForAPI), nil 120 } 121 122 func (p *ownerStatusProvider) GetChangeFeedInfo(ctx context.Context, 123 changefeedID model.ChangeFeedID, 124 ) (*model.ChangeFeedInfo, error) { 125 query := &Query{ 126 Tp: QueryChangefeedInfo, 127 ChangeFeedID: changefeedID, 128 } 129 if err := p.sendQueryToOwner(ctx, query); err != nil { 130 return nil, errors.Trace(err) 131 } 132 if query.Data == nil { 133 return nil, cerror.ErrChangeFeedNotExists.GenWithStackByArgs(changefeedID) 134 } 135 return query.Data.(*model.ChangeFeedInfo), nil 136 } 137 138 func (p *ownerStatusProvider) GetAllTaskStatuses(ctx context.Context, 139 changefeedID model.ChangeFeedID, 140 ) (map[model.CaptureID]*model.TaskStatus, error) { 141 query := &Query{ 142 Tp: QueryAllTaskStatuses, 143 ChangeFeedID: changefeedID, 144 } 145 if err := p.sendQueryToOwner(ctx, query); err != nil { 146 return nil, errors.Trace(err) 147 } 148 return query.Data.(map[model.CaptureID]*model.TaskStatus), nil 149 } 150 151 func (p *ownerStatusProvider) GetProcessors(ctx context.Context) ([]*model.ProcInfoSnap, error) { 152 query := &Query{ 153 Tp: QueryProcessors, 154 } 155 if err := p.sendQueryToOwner(ctx, query); err != nil { 156 return nil, errors.Trace(err) 157 } 158 return query.Data.([]*model.ProcInfoSnap), nil 159 } 160 161 func (p *ownerStatusProvider) GetCaptures(ctx context.Context) ([]*model.CaptureInfo, error) { 162 query := &Query{ 163 Tp: QueryCaptures, 164 } 165 if err := p.sendQueryToOwner(ctx, query); err != nil { 166 return nil, errors.Trace(err) 167 } 168 return query.Data.([]*model.CaptureInfo), nil 169 } 170 171 func (p *ownerStatusProvider) IsHealthy(ctx context.Context) (bool, error) { 172 query := &Query{ 173 Tp: QueryHealth, 174 } 175 if err := p.sendQueryToOwner(ctx, query); err != nil { 176 return false, errors.Trace(err) 177 } 178 return query.Data.(bool), nil 179 } 180 181 func (p *ownerStatusProvider) IsChangefeedOwner(ctx context.Context, id model.ChangeFeedID) (bool, error) { 182 query := &Query{ 183 Tp: QueryOwner, 184 ChangeFeedID: id, 185 } 186 if err := p.sendQueryToOwner(ctx, query); err != nil { 187 return false, errors.Trace(err) 188 } 189 return query.Data.(bool), nil 190 } 191 192 func (p *ownerStatusProvider) sendQueryToOwner(ctx context.Context, query *Query) error { 193 doneCh := make(chan error, 1) 194 p.owner.Query(query, doneCh) 195 196 select { 197 case <-ctx.Done(): 198 return errors.Trace(ctx.Err()) 199 case err := <-doneCh: 200 if err != nil { 201 return errors.Trace(err) 202 } 203 } 204 205 return nil 206 }