diff --git a/api/handler/default.go b/api/handler/default.go index f31cb643e..740e8a28b 100644 --- a/api/handler/default.go +++ b/api/handler/default.go @@ -10,6 +10,7 @@ import ( "log/slog" "net/http" "net/url" + "strconv" "time" "github.com/bitcoin-sv/arc/api" @@ -458,6 +459,13 @@ func (m ArcDefaultHandler) processTransaction(ctx context.Context, transaction * validateSpan.Finish() } + err := m.TransactionHandler.Health(tracingCtx) + if err != nil { + statusCode, arcError := m.handleError(tracingCtx, transaction, err) + m.logger.Error("metamorph not healthy") + return statusCode, arcError, err + } + tx, err := m.TransactionHandler.SubmitTransaction(tracingCtx, transaction.Bytes(), transactionOptions) if err != nil { statusCode, arcError := m.handleError(tracingCtx, transaction, err) @@ -493,6 +501,15 @@ func (m ArcDefaultHandler) processTransactions(ctx context.Context, transactions span, tracingCtx := opentracing.StartSpanFromContext(ctx, "ArcDefaultHandler:processTransactions") defer span.Finish() + err := m.TransactionHandler.Health(tracingCtx) + if err != nil { + statusCode, arcError := m.handleError(tracingCtx, nil, err) + m.logger.Error("metamorph not healthy") + return statusCode, []interface{}{arcError}, err + } + + m.logger.Info("Starting to process ", strconv.Itoa(len(transactions)), " transactions") + // validate before submitting array of transactions to metamorph transactionsInput := make([][]byte, 0, len(transactions)) txErrors := make([]interface{}, 0, len(transactions)) diff --git a/api/handler/default_test.go b/api/handler/default_test.go index cdc6d0ce8..f05dcee45 100644 --- a/api/handler/default_test.go +++ b/api/handler/default_test.go @@ -376,6 +376,10 @@ func TestPOSTTransaction(t *testing.T) { //nolint:funlen rec, ctx := createEchoPostRequest(inputTx, tc.contentType, "/v1/tx") txHandler := &mock.TransactionHandlerMock{ + HealthFunc: func(ctx context.Context) error { + return nil + }, + GetTransactionFunc: func(ctx context.Context, txID string) ([]byte, error) { return tc.getTx, nil }, @@ -517,6 +521,10 @@ func TestPOSTTransactions(t *testing.T) { //nolint:funlen GetTransactionFunc: func(ctx context.Context, txID string) ([]byte, error) { return nil, metamorph.ErrTransactionNotFound }, + + HealthFunc: func(ctx context.Context) error { + return nil + }, } defaultHandler, err := NewDefault(testLogger, txHandler, defaultPolicy) require.NoError(t, err) @@ -557,6 +565,10 @@ func TestPOSTTransactions(t *testing.T) { //nolint:funlen txStatuses := []*metamorph.TransactionStatus{txResult} return txStatuses, nil }, + + HealthFunc: func(ctx context.Context) error { + return nil + }, } defaultHandler, err := NewDefault(testLogger, txHandler, defaultPolicy) diff --git a/metamorph/callbacker.go b/metamorph/callbacker.go index ab0ec661c..9c3688f53 100644 --- a/metamorph/callbacker.go +++ b/metamorph/callbacker.go @@ -38,7 +38,7 @@ func (p *Processor) SendCallback(logger *slog.Logger, tx *store.StoreData) { for i := 0; i < CallbackTries; i++ { - logger.Info("Sending callback for transaction", slog.String("hash", tx.Hash.String()), slog.String("url", tx.CallbackUrl), slog.String("token", tx.CallbackToken), slog.String("status", statusString), slog.Uint64("block height", tx.BlockHeight), slog.String("block hash", blockHash)) + logger.Debug("Sending callback for transaction", slog.String("hash", tx.Hash.String()), slog.String("url", tx.CallbackUrl), slog.String("token", tx.CallbackToken), slog.String("status", statusString), slog.Uint64("block height", tx.BlockHeight), slog.String("block hash", blockHash)) status := &Callback{ BlockHash: &blockHash, diff --git a/metamorph/processor.go b/metamorph/processor.go index 2e659b963..be7a0ccce 100644 --- a/metamorph/processor.go +++ b/metamorph/processor.go @@ -570,7 +570,7 @@ func (p *Processor) ProcessTransaction(ctx context.Context, req *ProcessorReques p.stored.AddDuration(time.Since(processorResponse.Start)) - p.logger.Info("announcing transaction", slog.String("hash", req.Data.Hash.String())) + p.logger.Debug("announcing transaction", slog.String("hash", req.Data.Hash.String())) // STEP 2: ANNOUNCED_TO_NETWORK peers := p.pm.AnnounceTransaction(req.Data.Hash, nil) processorResponse.SetPeers(peers) @@ -618,6 +618,12 @@ func (p *Processor) Health() error { } if healthyConnections < minimumHealthyConnections { + p.logger.Warn("Less than expected healthy peers - ", slog.Int("number", healthyConnections)) + return nil + } + + if healthyConnections == 0 { + p.logger.Error("Metamorph not healthy") return ErrUnhealthy } diff --git a/metamorph/processor_test.go b/metamorph/processor_test.go index a285cc0ab..e8e94b881 100644 --- a/metamorph/processor_test.go +++ b/metamorph/processor_test.go @@ -693,7 +693,7 @@ func TestProcessorHealth(t *testing.T) { name: "1 healthy peer", peersAdded: 1, - expectedErr: metamorph.ErrUnhealthy, + expectedErr: nil, }, } diff --git a/test/endpoint_test.go b/test/endpoint_test.go index 20ce99892..81acdffd4 100644 --- a/test/endpoint_test.go +++ b/test/endpoint_test.go @@ -404,6 +404,8 @@ func TestPostCallbackToken(t *testing.T) { t.Logf("callback iteration %d", i) select { case callback := <-callbackReceivedChan: + t.Logf(*statusResponse.JSON200.TxStatus) + t.Logf(*callback.TxStatus) if *callback.TxStatus == "SEEN_ON_NETWORK" { seenOnNetworkReceived = true continue