package app import ( "context" "fmt" "os" "route256/notifier/internal/app/controller" "route256/notifier/internal/domain/service" "route256/notifier/internal/infra/config" "route256/notifier/internal/infra/messaging/kafka" "github.com/IBM/sarama" "github.com/rs/zerolog" "github.com/rs/zerolog/log" ) type App struct { config *config.Config controller *controller.Controller } func NewApp(configPath string) (*App, error) { cfg, err := config.LoadConfig(configPath) if err != nil { return nil, fmt.Errorf("unable to load config: %w", err) } log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) zerolog.SetGlobalLevel(zerolog.InfoLevel) if cfg.Service.LogLevel != "" { level, logErr := zerolog.ParseLevel(cfg.Service.LogLevel) if logErr != nil { return nil, fmt.Errorf("unknown log level `%s` provided: %w", cfg.Service.LogLevel, logErr) } zerolog.SetGlobalLevel(level) } log.WithLevel(zerolog.GlobalLevel()).Msgf("using logging level=`%s`", zerolog.GlobalLevel().String()) consumer, err := setupSaramaConsumerGroup([]string{cfg.Kafka.Brokers}, cfg.Kafka.ConsumerGroupID) if err != nil { return nil, err } kafkaConsumer, err := kafka.NewStatusConsumer(cfg.Kafka.OrderTopic, consumer) if err != nil { return nil, fmt.Errorf("NewKafkaStatusConsumer: %w", err) } notifierService := service.NewNotifierService(kafkaConsumer) controller := controller.NewController(notifierService) return &App{ config: cfg, controller: controller, }, err } func (a *App) Run(ctx context.Context) { a.controller.Run(ctx) } func (a *App) Shutdown(ctx context.Context) error { return a.controller.Stop(ctx) } func setupSaramaConsumerGroup(brokers []string, groupID string) (sarama.ConsumerGroup, error) { cfg := sarama.NewConfig() cfg.Consumer.Group.Rebalance.Strategy = sarama.NewBalanceStrategyRange() cfg.Consumer.Offsets.Initial = sarama.OffsetNewest cfg.Metadata.AllowAutoTopicCreation = false group, err := sarama.NewConsumerGroup(brokers, groupID, cfg) if err != nil { return nil, fmt.Errorf("sarama.NewConsumerGroup: %w", err) } return group, nil }