github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/framework/metadata/metadata.go (about)

     1  // Copyright 2022 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 metadata
    15  
    16  import (
    17  	"context"
    18  
    19  	"github.com/pingcap/log"
    20  	frameModel "github.com/pingcap/tiflow/engine/framework/model"
    21  	pkgOrm "github.com/pingcap/tiflow/engine/pkg/orm"
    22  	ormModel "github.com/pingcap/tiflow/engine/pkg/orm/model"
    23  	"github.com/pingcap/tiflow/pkg/errors"
    24  	"go.uber.org/zap"
    25  )
    26  
    27  // JobManagerUUID defines the global unique id for job manager
    28  const JobManagerUUID = "dataflow-engine-job-manager"
    29  
    30  // MasterMetadataClient provides all ways to manage the master metadata
    31  type MasterMetadataClient struct {
    32  	masterID   frameModel.MasterID
    33  	metaClient pkgOrm.Client
    34  }
    35  
    36  // NewMasterMetadataClient creates a new MasterMetadataClient
    37  func NewMasterMetadataClient(
    38  	masterID frameModel.MasterID,
    39  	metaClient pkgOrm.Client,
    40  ) *MasterMetadataClient {
    41  	return &MasterMetadataClient{
    42  		masterID:   masterID,
    43  		metaClient: metaClient,
    44  	}
    45  }
    46  
    47  // Load queries master metadata from metastore, if the metadata does not exist,
    48  // create a new one and return it.
    49  func (c *MasterMetadataClient) Load(ctx context.Context) (*frameModel.MasterMeta, error) {
    50  	masterMeta, err := c.metaClient.GetJobByID(ctx, c.masterID)
    51  	if err != nil {
    52  		if pkgOrm.IsNotFoundError(err) {
    53  			// TODO refine handling the situation where the mata key does not exist at this point
    54  			masterMeta := &frameModel.MasterMeta{
    55  				// TODO: projectID
    56  				ID:    c.masterID,
    57  				State: frameModel.MasterStateUninit,
    58  			}
    59  			return masterMeta, nil
    60  		}
    61  
    62  		return nil, errors.Trace(err)
    63  	}
    64  	return masterMeta, nil
    65  }
    66  
    67  // Insert inserts the metadata
    68  func (c *MasterMetadataClient) Insert(ctx context.Context, data *frameModel.MasterMeta) error {
    69  	return errors.Trace(c.metaClient.InsertJob(ctx, data))
    70  }
    71  
    72  // Store upsert the data
    73  func (c *MasterMetadataClient) Store(ctx context.Context, data *frameModel.MasterMeta) error {
    74  	return errors.Trace(c.metaClient.UpsertJob(ctx, data))
    75  }
    76  
    77  // Update update the data
    78  func (c *MasterMetadataClient) Update(
    79  	ctx context.Context, values ormModel.KeyValueMap,
    80  ) error {
    81  	return errors.Trace(c.metaClient.UpdateJob(ctx, c.masterID, values))
    82  }
    83  
    84  // Delete deletes the metadata of this master
    85  func (c *MasterMetadataClient) Delete(ctx context.Context) error {
    86  	_, err := c.metaClient.DeleteJob(ctx, c.masterID)
    87  	return errors.Trace(err)
    88  }
    89  
    90  // LoadAllMasters loads all job masters from metastore
    91  func (c *MasterMetadataClient) LoadAllMasters(ctx context.Context) ([]*frameModel.MasterMeta, error) {
    92  	meta, err := c.metaClient.QueryJobs(ctx)
    93  	if err != nil {
    94  		return nil, errors.Trace(err)
    95  	}
    96  	return meta, nil
    97  }
    98  
    99  // WorkerStatusClient provides all ways to manage metadata of all workers
   100  // belonging to a given master
   101  type WorkerStatusClient struct {
   102  	masterID   frameModel.MasterID
   103  	metaClient pkgOrm.Client
   104  }
   105  
   106  // NewWorkerStatusClient creates a new WorkerStatusClient instance
   107  func NewWorkerStatusClient(
   108  	masterID frameModel.MasterID,
   109  	metaClient pkgOrm.Client,
   110  ) *WorkerStatusClient {
   111  	return &WorkerStatusClient{
   112  		masterID:   masterID,
   113  		metaClient: metaClient,
   114  	}
   115  }
   116  
   117  // LoadAllWorkers queries all workers of this master
   118  func (c *WorkerStatusClient) LoadAllWorkers(ctx context.Context) (map[frameModel.WorkerID]*frameModel.WorkerStatus, error) {
   119  	resp, err := c.metaClient.QueryWorkersByMasterID(ctx, c.masterID)
   120  	if err != nil {
   121  		return nil, errors.Trace(err)
   122  	}
   123  
   124  	res := make(map[frameModel.WorkerID]*frameModel.WorkerStatus, len(resp))
   125  	for _, m := range resp {
   126  		res[m.ID] = m
   127  	}
   128  	return res, nil
   129  }
   130  
   131  // Load queries a worker by its worker id
   132  func (c *WorkerStatusClient) Load(ctx context.Context, workerID frameModel.WorkerID) (*frameModel.WorkerStatus, error) {
   133  	resp, err := c.metaClient.GetWorkerByID(ctx, c.masterID, workerID)
   134  	if err != nil {
   135  		return nil, errors.Trace(err)
   136  	}
   137  
   138  	return resp, nil
   139  }
   140  
   141  // Remove deletes a given worker from metastore
   142  func (c *WorkerStatusClient) Remove(ctx context.Context, id frameModel.WorkerID) (bool, error) {
   143  	_, err := c.metaClient.DeleteWorker(ctx, c.masterID, id)
   144  	if err != nil {
   145  		return false, errors.Trace(err)
   146  	}
   147  	return true, nil
   148  }
   149  
   150  // Store stores a worker metadata into metastore
   151  func (c *WorkerStatusClient) Store(ctx context.Context, data *frameModel.WorkerStatus) error {
   152  	return errors.Trace(c.metaClient.UpsertWorker(ctx, data))
   153  }
   154  
   155  // Update updates a worker metadata
   156  func (c *WorkerStatusClient) Update(ctx context.Context, data *frameModel.WorkerStatus) error {
   157  	return errors.Trace(c.metaClient.UpdateWorker(ctx, data))
   158  }
   159  
   160  // MasterID returns the master id of this metadata client
   161  func (c *WorkerStatusClient) MasterID() frameModel.MasterID {
   162  	return c.masterID
   163  }
   164  
   165  // StoreMasterMeta is exposed to job manager for job master meta persistence
   166  func StoreMasterMeta(
   167  	ctx context.Context,
   168  	metaClient pkgOrm.Client,
   169  	meta *frameModel.MasterMeta,
   170  ) error {
   171  	metaCli := NewMasterMetadataClient(meta.ID, metaClient)
   172  	masterMeta, err := metaCli.Load(ctx)
   173  	if err != nil {
   174  		return err
   175  	}
   176  	log.Warn("master meta exists, will be overwritten", zap.Any("old-meta", masterMeta), zap.Any("meta", meta))
   177  
   178  	return metaCli.Store(ctx, meta)
   179  }
   180  
   181  // DeleteMasterMeta deletes given maste meta from meta store
   182  func DeleteMasterMeta(
   183  	ctx context.Context,
   184  	metaClient pkgOrm.Client,
   185  	masterID frameModel.MasterID,
   186  ) error {
   187  	metaCli := NewMasterMetadataClient(masterID, metaClient)
   188  	return metaCli.Delete(ctx)
   189  }