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 }