Skip to content

Commit

Permalink
refactor: Reduce duplicated code in metamorph client (#653)
Browse files Browse the repository at this point in the history
  • Loading branch information
boecklim authored Nov 20, 2024
1 parent 176835c commit fb41eef
Showing 1 changed file with 62 additions and 99 deletions.
161 changes: 62 additions & 99 deletions pkg/metamorph/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,23 +244,10 @@ func (m *Metamorph) SubmitTransaction(ctx context.Context, tx *sdkTx.Transaction
}

var response *metamorph_api.TransactionStatus
var txStatus *TransactionStatus
var getStatusErr error
var err error

response, err = m.client.PutTransaction(ctx, request)
if err == nil {
return &TransactionStatus{
TxID: response.GetTxid(),
Status: response.GetStatus().String(),
ExtraInfo: response.GetRejectReason(),
CompetingTxs: response.GetCompetingTxs(),
BlockHash: response.GetBlockHash(),
BlockHeight: response.GetBlockHeight(),
MerklePath: response.GetMerklePath(),
Timestamp: m.now().Unix(),
}, nil
}
m.logger.ErrorContext(ctx, "Failed to put transaction", slog.String("err", err.Error()))

// in case of error try PutTransaction until timeout expires

maxTimeout := max(time.Duration(request.MaxTimeout)*time.Second, m.maxTimeout)
Expand All @@ -269,44 +256,42 @@ func (m *Metamorph) SubmitTransaction(ctx context.Context, tx *sdkTx.Transaction

timeoutTimer := time.NewTimer(maxTimeout)

retryLoop:
for {
select {
case <-timeoutTimer.C:
return nil, err

case <-retryTicker.C:
response, err = m.client.PutTransaction(ctx, request)
if err == nil {
break retryLoop
response, err = m.client.PutTransaction(ctx, request)
if err == nil {
txStatus = &TransactionStatus{
TxID: response.GetTxid(),
Status: response.GetStatus().String(),
ExtraInfo: response.GetRejectReason(),
CompetingTxs: response.GetCompetingTxs(),
BlockHash: response.GetBlockHash(),
BlockHeight: response.GetBlockHeight(),
MerklePath: response.GetMerklePath(),
Timestamp: m.now().Unix(),
}
break
}

m.logger.ErrorContext(ctx, "Failed to put transaction", slog.String("err", err.Error()))

if status.Code(err) != codes.Code(code.Code_DEADLINE_EXCEEDED) {
continue
}
m.logger.ErrorContext(ctx, "Failed to put transaction", slog.String("err", err.Error()))

if status.Code(err) == codes.Code(code.Code_DEADLINE_EXCEEDED) {
// if error is deadline exceeded, check tx status to avoid false negatives
txStatus, getStatusErr := m.GetTransactionStatus(ctx, tx.TxID())
if getStatusErr != nil {
continue
txStatus, getStatusErr = m.GetTransactionStatus(ctx, tx.TxID())
if getStatusErr == nil {
break
}
}

select {
case <-timeoutTimer.C:
return nil, err

return txStatus, nil
case <-retryTicker.C:
continue
}
}

return &TransactionStatus{
TxID: response.GetTxid(),
Status: response.GetStatus().String(),
ExtraInfo: response.GetRejectReason(),
CompetingTxs: response.GetCompetingTxs(),
BlockHash: response.GetBlockHash(),
BlockHeight: response.GetBlockHeight(),
MerklePath: response.GetMerklePath(),
Timestamp: m.now().Unix(),
}, nil
return txStatus, nil
}

// SubmitTransactions submits transactions to the bitcoin network and returns the transaction in raw format.
Expand Down Expand Up @@ -342,29 +327,9 @@ func (m *Metamorph) SubmitTransactions(ctx context.Context, txs sdkTx.Transactio
return ret, nil
}
var responses *metamorph_api.TransactionStatuses
var txStatuses []*TransactionStatus
var err error

responses, err = m.client.PutTransactions(ctx, in)
if err == nil {
// parse response and return to user
ret := make([]*TransactionStatus, 0)
for _, response := range responses.GetStatuses() {
ret = append(ret, &TransactionStatus{
TxID: response.GetTxid(),
MerklePath: response.GetMerklePath(),
Status: response.GetStatus().String(),
ExtraInfo: response.GetRejectReason(),
CompetingTxs: response.GetCompetingTxs(),
BlockHash: response.GetBlockHash(),
BlockHeight: response.GetBlockHeight(),
Timestamp: m.now().Unix(),
})
}

return ret, nil
}
m.logger.ErrorContext(ctx, "Failed to put transactions", slog.String("err", err.Error()))

// in case of error try PutTransaction until timeout expires

maxTimeout := max(time.Duration(in.Transactions[0].MaxTimeout)*time.Second, m.maxTimeout)
Expand All @@ -373,57 +338,55 @@ func (m *Metamorph) SubmitTransactions(ctx context.Context, txs sdkTx.Transactio

timeoutTimer := time.NewTimer(maxTimeout)

retryLoop:
for {
select {
case <-timeoutTimer.C:
return nil, err

case <-retryTicker.C:
responses, err = m.client.PutTransactions(ctx, in)
if err == nil {
break retryLoop
}

m.logger.ErrorContext(ctx, "Failed to put transactions", slog.String("err", err.Error()))

if status.Code(err) != codes.Code(code.Code_DEADLINE_EXCEEDED) {
continue
responses, err = m.client.PutTransactions(ctx, in)
if err == nil {
for _, response := range responses.GetStatuses() {
txStatuses = append(txStatuses, &TransactionStatus{
TxID: response.GetTxid(),
MerklePath: response.GetMerklePath(),
Status: response.GetStatus().String(),
ExtraInfo: response.GetRejectReason(),
CompetingTxs: response.GetCompetingTxs(),
BlockHash: response.GetBlockHash(),
BlockHeight: response.GetBlockHeight(),
Timestamp: m.now().Unix(),
})
}
break
}

// if error is deadline exceeded, check tx status to avoid false negatives
m.logger.ErrorContext(ctx, "Failed to put transactions", slog.String("err", err.Error()))

// Todo: Create and use here client.GetTransactionStatuses rpc function
txStatuses := make([]*TransactionStatus, 0)
// if error is deadline exceeded, check tx status to avoid false negatives
if status.Code(err) == codes.Code(code.Code_DEADLINE_EXCEEDED) {
completedErrorFree := true
for _, tx := range txs {
// Todo: Create and use here client.GetTransactionStatuses rpc function
txStatus, getStatusErr := m.GetTransactionStatus(ctx, tx.TxID())
if getStatusErr != nil {
continue retryLoop
completedErrorFree = false
break
}

txStatuses = append(txStatuses, txStatus)
}

return txStatuses, nil
if completedErrorFree {
break
}
}
}

// parse response and return to user
ret := make([]*TransactionStatus, 0)
for _, response := range responses.GetStatuses() {
ret = append(ret, &TransactionStatus{
TxID: response.GetTxid(),
MerklePath: response.GetMerklePath(),
Status: response.GetStatus().String(),
ExtraInfo: response.GetRejectReason(),
CompetingTxs: response.GetCompetingTxs(),
BlockHash: response.GetBlockHash(),
BlockHeight: response.GetBlockHeight(),
Timestamp: m.now().Unix(),
})
select {
case <-timeoutTimer.C:
return nil, err

case <-retryTicker.C:
continue
}
}

return ret, nil
return txStatuses, nil
}

func (m *Metamorph) ClearData(ctx context.Context, retentionDays int32) (int64, error) {
Expand Down

0 comments on commit fb41eef

Please sign in to comment.