refactored notificatoin / tgsettle responsibility boundaries

This commit is contained in:
Stephan D
2026-02-19 18:56:59 +01:00
parent 47f0a3d890
commit 2fd8a6ebb7
73 changed files with 3705 additions and 681 deletions

View File

@@ -5,6 +5,7 @@ import (
"errors"
"os"
"strings"
"sync"
"time"
gatewayoutbox "github.com/tech/sendico/gateway/common/outbox"
@@ -36,8 +37,9 @@ import (
)
const (
defaultConfirmationTimeoutSeconds = 259200
defaultConfirmationTimeoutSeconds = 345600
defaultTelegramSuccessReaction = "\U0001FAE1"
defaultConfirmationSweepInterval = 5 * time.Second
)
const (
@@ -73,7 +75,10 @@ type Service struct {
successReaction string
outbox gatewayoutbox.ReliableRuntime
consumers []msg.Consumer
consumers []msg.Consumer
timeoutCtx context.Context
timeoutCancel context.CancelFunc
timeoutWG sync.WaitGroup
connectorv1.UnimplementedConnectorServiceServer
}
@@ -103,6 +108,7 @@ func NewService(logger mlogger.Logger, repo storage.Repository, producer msg.Pro
}
svc.startConsumers()
svc.startAnnouncer()
svc.startConfirmationTimeoutWatcher()
return svc
}
@@ -125,6 +131,10 @@ func (s *Service) Shutdown() {
consumer.Close()
}
}
if s.timeoutCancel != nil {
s.timeoutCancel()
}
s.timeoutWG.Wait()
}
func (s *Service) startConsumers() {
@@ -136,6 +146,10 @@ func (s *Service) startConsumers() {
}
resultProcessor := confirmations.NewConfirmationResultProcessor(s.logger, string(mservice.PaymentGateway), s.rail, s.onConfirmationResult)
s.consumeProcessor(resultProcessor)
dispatchProcessor := confirmations.NewConfirmationDispatchProcessor(s.logger, string(mservice.PaymentGateway), s.rail, s.onConfirmationDispatch)
s.consumeProcessor(dispatchProcessor)
updateProcessor := tnotifications.NewTelegramUpdateProcessor(s.logger, s.onTelegramUpdate)
s.consumeProcessor(updateProcessor)
}
func (s *Service) consumeProcessor(processor np.EnvelopeProcessor) {
@@ -300,8 +314,13 @@ func (s *Service) onIntent(ctx context.Context, intent *model.PaymentGatewayInte
zap.String("idempotency_key", confirmReq.RequestID), zap.String("intent_ref", record.IntentRef))
return err
}
if err := s.persistPendingConfirmation(ctx, confirmReq); err != nil {
s.logger.Warn("Failed to persist pending confirmation", zap.Error(err), zap.String("request_id", confirmReq.RequestID))
return err
}
if err := s.sendConfirmationRequest(confirmReq); err != nil {
s.logger.Warn("Failed to publish confirmation request", zap.Error(err), zap.String("idempotency_key", confirmReq.RequestID))
_ = s.clearPendingConfirmation(ctx, confirmReq.RequestID)
// If the confirmation request was not sent, we keep the record in waiting
// (or it can be marked as failed — depending on your semantics).
// Here, failed is chosen to avoid it hanging indefinitely.
@@ -392,6 +411,10 @@ func (s *Service) onConfirmationResult(ctx context.Context, result *model.Confir
return err
}
if isFinalConfirmationStatus(result.Status) {
_ = s.clearPendingConfirmation(ctx, requestID)
}
s.publishTelegramReaction(result)
return nil