package callback import ( "context" "sync" "go.uber.org/zap" "gitea.pena/PenaSide/treasurer/internal/errors" "gitea.pena/PenaSide/treasurer/internal/models" ) type CallbackClient interface { SendOnSuccess(ctx context.Context, host string, event *models.Event) errors.Error SendOnFailure(ctx context.Context, host string, event *models.Event) errors.Error } type PaymentRepository interface { SetPaymentComplete(ctx context.Context, paymentID string) (*models.Payment, errors.Error) } type Deps struct { Logger *zap.Logger CallbackClient CallbackClient PaymentRepository PaymentRepository } type Service struct { logger *zap.Logger callbackClient CallbackClient paymentRepository PaymentRepository } func New(deps Deps) (*Service, errors.Error) { if deps.Logger == nil { return nil, errors.NewWithMessage("logger is nil on ", errors.ErrInvalidArgs) } if deps.CallbackClient == nil { return nil, errors.NewWithMessage("CallbackClient is nil on ", errors.ErrInvalidArgs) } if deps.PaymentRepository == nil { return nil, errors.NewWithMessage("PaymentRepository is nil on ", errors.ErrInvalidArgs) } return &Service{ logger: deps.Logger, callbackClient: deps.CallbackClient, paymentRepository: deps.PaymentRepository, }, nil } func (receiver *Service) OnSuccess(ctx context.Context, event *models.Event) errors.Error { waitGroup := sync.WaitGroup{} mutex := sync.Mutex{} executeErrors := make([]error, 0) for _, callbackURL := range event.Payment.CallbackHostGRPC { waitGroup.Add(1) go func(url string) { defer waitGroup.Done() if err := receiver.callbackClient.SendOnSuccess(ctx, url, event); err != nil { receiver.logger.Error("failid to send callback on of ") mutex.Lock() executeErrors = append(executeErrors, err) mutex.Unlock() return } if _, err := receiver.paymentRepository.SetPaymentComplete(ctx, event.Payment.PaymentID); err != nil { receiver.logger.Error("failid to set payment complete on of ") mutex.Lock() executeErrors = append(executeErrors, err) mutex.Unlock() return } }(callbackURL) } waitGroup.Wait() if len(executeErrors) >= len(event.Payment.CallbackHostGRPC) { receiver.logger.Error("failid to success payment on of ", zap.Errors("errors", executeErrors)) return errors.NewWithMessage("failed to success payment: all operations failed", errors.ErrInternalError) } return nil } func (receiver *Service) OnFailure(ctx context.Context, event *models.Event) errors.Error { waitGroup := sync.WaitGroup{} mutex := sync.Mutex{} executeErrors := make([]error, 0) for _, callbackURL := range event.Payment.CallbackHostGRPC { waitGroup.Add(1) go func(url string) { defer waitGroup.Done() if err := receiver.callbackClient.SendOnFailure(ctx, url, event); err != nil { receiver.logger.Error("failid to send callback on of ") mutex.Lock() executeErrors = append(executeErrors, err) mutex.Unlock() return } }(callbackURL) } waitGroup.Wait() if len(executeErrors) >= len(event.Payment.CallbackHostGRPC) { receiver.logger.Error("failid to success payment on of ", zap.Errors("errors", executeErrors)) return errors.NewWithMessage("failed to success payment: all operations failed", errors.ErrInternalError) } return nil }