public async Task StartAsync() { bool startSucceeded = false; await this.DoReadWriteActionOnCurrentTournamentAsync( async currentTournament => { if (currentTournament?.Stage != TournamentStage.AddPlayers) { // !start only applies once we've started adding players this.Logger.Debug("Start failed because we were in stage {stage}", currentTournament?.Stage); await this.SendChannelMessage(BotStrings.CommandOnlyUsedTournamentReadyStart); return; } await this.UpdateStageAsync(currentTournament, TournamentStage.BotSetup); try { // TODO: Add more messaging around the current status this.Logger.Debug("Generating tournament"); IScheduleFactory scheduleFactory = new RoundRobinScheduleFactory( currentTournament.RoundRobinsCount); currentTournament.Schedule = scheduleFactory.Generate( new HashSet <Team>(currentTournament.Teams), new HashSet <Reader>(currentTournament.Readers)); this.Logger.Debug("Tournament generated. Creating channels and roles"); await this.Context.Channel.SendMessageAsync( BotStrings.CreatingChannelsAndRoles, options: RequestOptionsSettings.Default); await this.CreateArtifactsAsync(currentTournament); IUserMessage updateMessage = await this.UpdateStageAsync( currentTournament, TournamentStage.RunningTournament); await updateMessage.PinAsync(RequestOptionsSettings.Default); currentTournament.PinnedStartMessageId = updateMessage.Id; startSucceeded = true; } catch (Exception ex) { // TODO: Make the exceptions we catch more defined. // Go back to the previous stage and undo any artifacts added. this.Logger.Error(ex, "Error starting the tournament. Cleaning up the tournament artifacts"); await this.CleanupTournamentArtifactsAsync(currentTournament); await this.UpdateStageAsync(currentTournament, TournamentStage.AddPlayers); throw; } }); if (startSucceeded) { await this.Context.Channel.SendMessageAsync( BotStrings.TournamentHasStarted( MentionUtils.MentionChannel(this.Context.Channel.Id)), options : RequestOptionsSettings.Default); } }