private async Task SendUpdatePayloadsAsync(CancellationToken token = default)
        {
            ExtensionPayload updateReplayPayload = Data.Payloads.Update.Find(p => p.Step == ExtensionStep.UpdateReplayData);

            if (updateReplayPayload != null)
            {
                bool success = await extensionService.UpdateReplayDataAsync(updateReplayPayload, SessionId, token).ConfigureAwait(false);

                if (success && Data.Payloads.Update.Remove(updateReplayPayload))
                {
                    logger.LogDebug($"removed update replay payload.");
                }
            }
            else
            {
                ExtensionPayload updatePlayerPayload = Data.Payloads.Update.Find(p => p.Step == ExtensionStep.UpdatePlayerData);

                if (updatePlayerPayload != null)
                {
                    bool success = await extensionService.UpdatePlayerDataAsync(updatePlayerPayload, SessionId, token).ConfigureAwait(false);

                    if (success)
                    {
                        Data.Payloads.Update.Remove(updatePlayerPayload);
                        logger.LogDebug($"removed update player payload.");
                    }
                }
            }
        }
        private async Task SendCreatePayloadsAsync(CancellationToken token = default)
        {
            ExtensionPayload createReplayPayload = Data.Payloads.Create.Find(p => p.Step == ExtensionStep.CreateReplayData);

            if (createReplayPayload != null)
            {
                string session = await extensionService.CreateReplaySessionAsync(createReplayPayload, token).ConfigureAwait(false);

                bool success = !string.IsNullOrWhiteSpace(session);

                if (success && Data.Payloads.Create.Remove(createReplayPayload))
                {
                    logger.LogDebug($"removed create replay payload.");
                    logger.LogDebug($"create replay session id: {SessionId}");
                }

                SessionId = session;
            }
            else
            {
                ExtensionPayload createPlayerPayload = Data.Payloads.Create.Find(p => p.Step == ExtensionStep.CreatePlayerData);

                if (createPlayerPayload != null)
                {
                    bool success = await extensionService.CreatePlayerDataAsync(createPlayerPayload, SessionId, token).ConfigureAwait(false);

                    if (success && Data.Payloads.Create.Remove(createPlayerPayload))
                    {
                        logger.LogDebug("Removed create player payload.");
                    }
                }
            }
        }
        public async Task <bool> CreatePlayerDataAsync(ExtensionPayload payload, string sessionId, CancellationToken token)
        {
            if (payload == null)
            {
                throw new ArgumentNullException(nameof(payload));
            }

            if (sessionId == null)
            {
                throw new ArgumentNullException(nameof(sessionId));
            }

            List <HttpResponseMessage> responses = new List <HttpResponseMessage>();

            try
            {
                payload.SetGameSessionReplayId(sessionId);

                using (CancellationTokenSource cancellationSource = CancellationTokenSource.CreateLinkedTokenSource(token, tokenProvider.Token))
                {
                    foreach (var content in payload.Content)
                    {
                        HttpResponseMessage response = await Policy
                                                       .Handle <Exception>()
                                                       .OrResult <HttpResponseMessage>(msg => !msg.IsSuccessStatusCode)
                                                       .WaitAndRetryAsync(retryCount: 5, sleepDurationProvider: GetSleepDuration, onRetry: OnRetry)
                                                       .ExecuteAsync(async(context, token) => await httpClient.PostAsync(SavePlayerUrl, new FormUrlEncodedContent(content), token), new Context(), cancellationSource.Token)
                                                       .ConfigureAwait(false);

                        responses.Add(response);
                    }
                }
            }
            catch (OperationCanceledException)
            {
                logger.LogWarning("Could not create twitch extension player data because the task was cancelled.");
            }
            catch (Exception e)
            {
                logger.LogError(e, "Could not create player data.");
            }

            return(responses.All(response => response.IsSuccessStatusCode));
        }
        public async Task <string> CreateReplaySessionAsync(ExtensionPayload payload, CancellationToken token)
        {
            if (payload == null)
            {
                throw new ArgumentNullException(nameof(payload));
            }

            try
            {
                using (CancellationTokenSource cancellationSource = CancellationTokenSource.CreateLinkedTokenSource(token, tokenProvider.Token))
                {
                    HttpResponseMessage response = await Policy
                                                   .Handle <Exception>()
                                                   .OrResult <HttpResponseMessage>(msg => !msg.IsSuccessStatusCode)
                                                   .WaitAndRetryAsync(retryCount: 10, sleepDurationProvider: GetSleepDuration, onRetry: OnRetry)
                                                   .ExecuteAsync(async(context, token) => await httpClient.PostAsync(SaveReplayUrl, new FormUrlEncodedContent(payload.Content.Single()), cancellationSource.Token), new Context(), tokenProvider.Token)
                                                   .ConfigureAwait(false);

                    if (response.IsSuccessStatusCode)
                    {
                        string result = await response.Content.ReadAsStringAsync();

                        if (int.TryParse(result, out _))
                        {
                            return(result);
                        }
                    }
                    else
                    {
                        logger.LogError($"{response.StatusCode} ({response.ReasonPhrase})");
                    }
                }
            }
            catch (TaskCanceledException)
            {
                logger.LogWarning("Could not create twitch extension replay session because the task was cancelled.");
            }
            catch (Exception e)
            {
                logger.LogError(e, "Could not create session.");
            }

            return(null);
        }