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  }