github.com/weaviate/weaviate@v1.24.6/adapters/repos/classifications/distributed_repo.go (about)

     1  //                           _       _
     2  // __      _____  __ ___   ___  __ _| |_ ___
     3  // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
     4  //  \ V  V /  __/ (_| |\ V /| | (_| | ||  __/
     5  //   \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
     6  //
     7  //  Copyright © 2016 - 2024 Weaviate B.V. All rights reserved.
     8  //
     9  //  CONTACT: hello@weaviate.io
    10  //
    11  
    12  package classifications
    13  
    14  import (
    15  	"context"
    16  	"sync"
    17  	"time"
    18  
    19  	"github.com/go-openapi/strfmt"
    20  	"github.com/pkg/errors"
    21  	"github.com/sirupsen/logrus"
    22  	"github.com/weaviate/weaviate/entities/models"
    23  	"github.com/weaviate/weaviate/usecases/classification"
    24  	"github.com/weaviate/weaviate/usecases/cluster"
    25  )
    26  
    27  const DefaultTxTTL = 60 * time.Second
    28  
    29  type DistributedRepo struct {
    30  	sync.RWMutex
    31  	txRemote  *cluster.TxManager
    32  	localRepo localRepo
    33  }
    34  
    35  type localRepo interface {
    36  	Get(ctx context.Context, id strfmt.UUID) (*models.Classification, error)
    37  	Put(ctx context.Context, classification models.Classification) error
    38  }
    39  
    40  func NewDistributeRepo(remoteClient cluster.Client,
    41  	memberLister cluster.MemberLister, localRepo localRepo,
    42  	logger logrus.FieldLogger,
    43  ) *DistributedRepo {
    44  	broadcaster := cluster.NewTxBroadcaster(memberLister, remoteClient, logger)
    45  	txRemote := cluster.NewTxManager(broadcaster, &dummyTxPersistence{}, logger)
    46  	txRemote.StartAcceptIncoming()
    47  	repo := &DistributedRepo{
    48  		txRemote:  txRemote,
    49  		localRepo: localRepo,
    50  	}
    51  
    52  	repo.txRemote.SetCommitFn(repo.incomingCommit)
    53  
    54  	return repo
    55  }
    56  
    57  func (r *DistributedRepo) Get(ctx context.Context,
    58  	id strfmt.UUID,
    59  ) (*models.Classification, error) {
    60  	r.RLock()
    61  	defer r.RUnlock()
    62  
    63  	return r.localRepo.Get(ctx, id)
    64  }
    65  
    66  func (r *DistributedRepo) Put(ctx context.Context,
    67  	pl models.Classification,
    68  ) error {
    69  	r.Lock()
    70  	defer r.Unlock()
    71  
    72  	tx, err := r.txRemote.BeginTransaction(ctx, classification.TransactionPut,
    73  		classification.TransactionPutPayload{
    74  			Classification: pl,
    75  		}, DefaultTxTTL)
    76  	if err != nil {
    77  		return errors.Wrap(err, "open cluster-wide transaction")
    78  	}
    79  
    80  	err = r.txRemote.CommitWriteTransaction(ctx, tx)
    81  	if err != nil {
    82  		return errors.Wrap(err, "commit cluster-wide transaction")
    83  	}
    84  
    85  	return r.localRepo.Put(ctx, pl)
    86  }
    87  
    88  func (r *DistributedRepo) incomingCommit(ctx context.Context,
    89  	tx *cluster.Transaction,
    90  ) error {
    91  	if tx.Type != classification.TransactionPut {
    92  		return errors.Errorf("unrecognized tx type: %s", tx.Type)
    93  	}
    94  
    95  	return r.localRepo.Put(ctx, tx.Payload.(classification.TransactionPutPayload).
    96  		Classification)
    97  }
    98  
    99  func (r *DistributedRepo) TxManager() *cluster.TxManager {
   100  	return r.txRemote
   101  }
   102  
   103  // NOTE: classifications do not yet make use of the new durability guarantees
   104  // introduced by the txManager as part of v1.21.3. The reasoning behind this is
   105  // that the classification itself is not crash-safe anyway, so there is no
   106  // point. We need to decide down the line what to do with this? It is a rarely
   107  // used, but not used feature. For now we are not aware of anyone having any
   108  // issues with its stability.
   109  type dummyTxPersistence struct{}
   110  
   111  func (d *dummyTxPersistence) StoreTx(ctx context.Context, tx *cluster.Transaction) error {
   112  	return nil
   113  }
   114  
   115  func (d *dummyTxPersistence) DeleteTx(ctx context.Context, txID string) error {
   116  	return nil
   117  }
   118  
   119  func (d *dummyTxPersistence) IterateAll(ctx context.Context, cb func(tx *cluster.Transaction)) error {
   120  	return nil
   121  }