github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/internal/pkg/gateway/commit/finder.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 // Package commit provides an implementation for finding transaction commit status that is specific to the Gateway 8 // embedded within a peer. 9 package commit 10 11 import ( 12 "context" 13 14 "github.com/hyperledger/fabric-protos-go/peer" 15 16 "github.com/pkg/errors" 17 ) 18 19 type Status struct { 20 BlockNumber uint64 21 TransactionID string 22 Code peer.TxValidationCode 23 } 24 25 // QueryProvider provides status of previously committed transactions on a given channel. An error is returned if the 26 // transaction is not present in the ledger. 27 type QueryProvider interface { 28 TransactionStatus(channelName string, transactionID string) (peer.TxValidationCode, uint64, error) 29 } 30 31 // Finder is used to obtain transaction status. 32 type Finder struct { 33 query QueryProvider 34 notifier *Notifier 35 } 36 37 func NewFinder(query QueryProvider, notifier *Notifier) *Finder { 38 return &Finder{ 39 query: query, 40 notifier: notifier, 41 } 42 } 43 44 // TransactionStatus provides status of a specified transaction on a given channel. If the transaction has already 45 // committed, the status is returned immediately; otherwise this call blocks waiting for the transaction to be 46 // committed or the context to be cancelled. 47 func (finder *Finder) TransactionStatus(ctx context.Context, channelName string, transactionID string) (*Status, error) { 48 // Set up notifier first to ensure no commit missed after completing query 49 notifyDone := make(chan struct{}) 50 defer close(notifyDone) 51 statusReceive, err := finder.notifier.notifyStatus(notifyDone, channelName, transactionID) 52 if err != nil { 53 return nil, err 54 } 55 56 if code, blockNumber, err := finder.query.TransactionStatus(channelName, transactionID); err == nil { 57 status := &Status{ 58 BlockNumber: blockNumber, 59 TransactionID: transactionID, 60 Code: code, 61 } 62 return status, nil 63 } 64 65 select { 66 case <-ctx.Done(): 67 return nil, ctx.Err() 68 case status, ok := <-statusReceive: 69 if !ok { 70 return nil, errors.New("unexpected close of commit notification channel") 71 } 72 return status, nil 73 } 74 }