Treasury bot + ledger fix
This commit is contained in:
@@ -146,6 +146,7 @@ func (s *Service) onTelegramUpdate(ctx context.Context, update *model.TelegramWe
|
||||
message := update.Message
|
||||
replyToID := strings.TrimSpace(message.ReplyToMessageID)
|
||||
if replyToID == "" {
|
||||
s.handleTreasuryTelegramUpdate(ctx, update)
|
||||
return nil
|
||||
}
|
||||
replyFields := telegramReplyLogFields(update)
|
||||
@@ -154,6 +155,9 @@ func (s *Service) onTelegramUpdate(ctx context.Context, update *model.TelegramWe
|
||||
return err
|
||||
}
|
||||
if pending == nil {
|
||||
if s.handleTreasuryTelegramUpdate(ctx, update) {
|
||||
return nil
|
||||
}
|
||||
s.logger.Warn("Telegram confirmation reply dropped",
|
||||
append(replyFields,
|
||||
zap.String("outcome", "dropped"),
|
||||
@@ -272,6 +276,13 @@ func (s *Service) onTelegramUpdate(ctx context.Context, update *model.TelegramWe
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) handleTreasuryTelegramUpdate(ctx context.Context, update *model.TelegramWebhookUpdate) bool {
|
||||
if s == nil || s.treasury == nil || update == nil || update.Message == nil {
|
||||
return false
|
||||
}
|
||||
return s.treasury.HandleUpdate(ctx, update)
|
||||
}
|
||||
|
||||
func telegramReplyLogFields(update *model.TelegramWebhookUpdate) []zap.Field {
|
||||
if update == nil || update.Message == nil {
|
||||
return nil
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"time"
|
||||
|
||||
gatewayoutbox "github.com/tech/sendico/gateway/common/outbox"
|
||||
treasurysvc "github.com/tech/sendico/gateway/tgsettle/internal/service/treasury"
|
||||
treasuryledger "github.com/tech/sendico/gateway/tgsettle/internal/service/treasury/ledger"
|
||||
"github.com/tech/sendico/gateway/tgsettle/storage"
|
||||
storagemodel "github.com/tech/sendico/gateway/tgsettle/storage/model"
|
||||
"github.com/tech/sendico/pkg/api/routers"
|
||||
@@ -40,6 +42,9 @@ const (
|
||||
defaultConfirmationTimeoutSeconds = 345600
|
||||
defaultTelegramSuccessReaction = "\U0001FAE1"
|
||||
defaultConfirmationSweepInterval = 5 * time.Second
|
||||
defaultTreasuryExecutionDelay = 30 * time.Second
|
||||
defaultTreasuryPollInterval = 30 * time.Second
|
||||
defaultTreasuryLedgerTimeout = 5 * time.Second
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -59,6 +64,35 @@ type Config struct {
|
||||
SuccessReaction string
|
||||
InvokeURI string
|
||||
MessagingSettings pmodel.SettingsT
|
||||
DiscoveryRegistry *discovery.Registry
|
||||
Treasury TreasuryConfig
|
||||
}
|
||||
|
||||
type TelegramConfig struct {
|
||||
AllowedChats []string
|
||||
Users []TelegramUserBinding
|
||||
}
|
||||
|
||||
type TelegramUserBinding struct {
|
||||
TelegramUserID string
|
||||
LedgerAccount string
|
||||
}
|
||||
|
||||
type TreasuryConfig struct {
|
||||
ExecutionDelay time.Duration
|
||||
PollInterval time.Duration
|
||||
Telegram TelegramConfig
|
||||
Ledger LedgerConfig
|
||||
Limits TreasuryLimitsConfig
|
||||
}
|
||||
|
||||
type TreasuryLimitsConfig struct {
|
||||
MaxAmountPerOperation string
|
||||
MaxDailyAmount string
|
||||
}
|
||||
|
||||
type LedgerConfig struct {
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
@@ -80,6 +114,8 @@ type Service struct {
|
||||
timeoutCancel context.CancelFunc
|
||||
timeoutWG sync.WaitGroup
|
||||
|
||||
treasury *treasurysvc.Module
|
||||
|
||||
connectorv1.UnimplementedConnectorServiceServer
|
||||
}
|
||||
|
||||
@@ -112,6 +148,7 @@ func NewService(logger mlogger.Logger, repo storage.Repository, producer msg.Pro
|
||||
svc.startConsumers()
|
||||
svc.startAnnouncer()
|
||||
svc.startConfirmationTimeoutWatcher()
|
||||
svc.startTreasuryModule()
|
||||
return svc
|
||||
}
|
||||
|
||||
@@ -134,12 +171,91 @@ func (s *Service) Shutdown() {
|
||||
consumer.Close()
|
||||
}
|
||||
}
|
||||
if s.treasury != nil {
|
||||
s.treasury.Shutdown()
|
||||
}
|
||||
if s.timeoutCancel != nil {
|
||||
s.timeoutCancel()
|
||||
}
|
||||
s.timeoutWG.Wait()
|
||||
}
|
||||
|
||||
func (s *Service) startTreasuryModule() {
|
||||
if s == nil || s.repo == nil || s.repo.TreasuryRequests() == nil {
|
||||
return
|
||||
}
|
||||
if s.cfg.DiscoveryRegistry == nil {
|
||||
s.logger.Warn("Treasury module disabled: discovery registry is unavailable")
|
||||
return
|
||||
}
|
||||
if len(s.cfg.Treasury.Telegram.Users) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
ledgerTimeout := s.cfg.Treasury.Ledger.Timeout
|
||||
if ledgerTimeout <= 0 {
|
||||
ledgerTimeout = defaultTreasuryLedgerTimeout
|
||||
}
|
||||
ledgerClient, err := treasuryledger.NewDiscoveryClient(treasuryledger.DiscoveryConfig{
|
||||
Logger: s.logger,
|
||||
Registry: s.cfg.DiscoveryRegistry,
|
||||
Timeout: ledgerTimeout,
|
||||
})
|
||||
if err != nil {
|
||||
s.logger.Warn("Failed to initialise treasury ledger client", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
executionDelay := s.cfg.Treasury.ExecutionDelay
|
||||
if executionDelay <= 0 {
|
||||
executionDelay = defaultTreasuryExecutionDelay
|
||||
}
|
||||
pollInterval := s.cfg.Treasury.PollInterval
|
||||
if pollInterval <= 0 {
|
||||
pollInterval = defaultTreasuryPollInterval
|
||||
}
|
||||
|
||||
users := make([]treasurysvc.UserBinding, 0, len(s.cfg.Treasury.Telegram.Users))
|
||||
for _, binding := range s.cfg.Treasury.Telegram.Users {
|
||||
users = append(users, treasurysvc.UserBinding{
|
||||
TelegramUserID: binding.TelegramUserID,
|
||||
LedgerAccount: binding.LedgerAccount,
|
||||
})
|
||||
}
|
||||
|
||||
module, err := treasurysvc.NewModule(
|
||||
s.logger,
|
||||
s.repo.TreasuryRequests(),
|
||||
ledgerClient,
|
||||
treasurysvc.Config{
|
||||
AllowedChats: s.cfg.Treasury.Telegram.AllowedChats,
|
||||
Users: users,
|
||||
ExecutionDelay: executionDelay,
|
||||
PollInterval: pollInterval,
|
||||
MaxAmountPerOperation: s.cfg.Treasury.Limits.MaxAmountPerOperation,
|
||||
MaxDailyAmount: s.cfg.Treasury.Limits.MaxDailyAmount,
|
||||
},
|
||||
func(ctx context.Context, chatID string, text string) error {
|
||||
return s.sendTelegramText(ctx, &model.TelegramTextRequest{
|
||||
ChatID: chatID,
|
||||
Text: text,
|
||||
})
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
s.logger.Warn("Failed to initialise treasury module", zap.Error(err))
|
||||
_ = ledgerClient.Close()
|
||||
return
|
||||
}
|
||||
if !module.Enabled() {
|
||||
_ = ledgerClient.Close()
|
||||
return
|
||||
}
|
||||
module.Start()
|
||||
s.treasury = module
|
||||
s.logger.Info("Treasury module started", zap.Duration("execution_delay", executionDelay), zap.Duration("poll_interval", pollInterval))
|
||||
}
|
||||
|
||||
func (s *Service) startConsumers() {
|
||||
if s == nil || s.broker == nil {
|
||||
if s != nil && s.logger != nil {
|
||||
|
||||
@@ -80,6 +80,7 @@ type fakeRepo struct {
|
||||
payments *fakePaymentsStore
|
||||
tg *fakeTelegramStore
|
||||
pending *fakePendingStore
|
||||
treasury storage.TreasuryRequestsStore
|
||||
}
|
||||
|
||||
func (f *fakeRepo) Payments() storage.PaymentsStore {
|
||||
@@ -94,6 +95,10 @@ func (f *fakeRepo) PendingConfirmations() storage.PendingConfirmationsStore {
|
||||
return f.pending
|
||||
}
|
||||
|
||||
func (f *fakeRepo) TreasuryRequests() storage.TreasuryRequestsStore {
|
||||
return f.treasury
|
||||
}
|
||||
|
||||
type fakePendingStore struct {
|
||||
mu sync.Mutex
|
||||
records map[string]*storagemodel.PendingConfirmation
|
||||
|
||||
Reference in New Issue
Block a user