protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            var creds = await credentialsProvider.GetCredentialsAsync();

            var bot = new ChatBot(creds.Username, creds.SecretToken, logger);

            bot.ChatMessageReceived += (_, args) =>
            {
                bool success = true;
                var  metrics = metricsFactory.Create();
                try
                {
                    metrics.AddDimension("Provider", "Twitch");
                    metrics.AddCount("MessagesReceived", 1.0);
                    var messageJson = JsonConvert.SerializeObject(args);
                    var newMessage  = this.chatMessageStorage.PutMessageIfNotDuplicateAsync(new ChatMessageRow()
                    {
                        MessageId       = $"twitch:{args.MessageId}",
                        Metadata        = messageJson,
                        Sender          = args.User,
                        Provider        = "twitch",
                        Timestamp       = args.Timestamp,
                        MessageContents = args.Message
                    }).Result;
                    metrics.AddCount("SkippingDuplicate", newMessage ? 0.0 : 1.0);
                    if (!newMessage)
                    {
                        return;
                    }

                    logger.LogInformation($"Received message from {args.User}: {args.Message}\n");
                    string msg = args.Message.ToLower();

                    string cmd = msg.Split(' ').FirstOrDefault();
                    bool   handlerTriggered = false;
                    if (this.commandHandlers.ContainsKey(cmd))
                    {
                        handlerTriggered = true;
                        this.commandHandlers[cmd].RunCommandAsync(args).GetAwaiter().GetResult();
                    }

                    metrics.AddCount("HandlerTriggered", handlerTriggered ? 1.0 : 0.0);
                    metrics.AddCount("NoHandler", handlerTriggered ? 0.0 : 1.0);
                    this.messageArchiver.ArchiveMessageAsync(new MessageRecord()
                    {
                        Message         = msg,
                        Timestamp       = args.Timestamp,
                        SourceUsername  = args.User,
                        Source          = MessageSource.Twitch,
                        SourceMessageId = "twitch:" + args.MessageId
                    });
                }
                catch (Exception ex)
                {
                    logger.LogError("Failed to run message handler.\n" + ex.ToString(), ex);
                    success = false;
                }

                metrics.AddCount("ProcessSuccess", success ? 1.0 : 0.0);
                metrics.AddCount("ProcessSuccess", success ? 0.0 : 1.0);
                metrics.Close();
            };

            await Task.Delay(Timeout.Infinite, stoppingToken);
        }