예제 #1
0
 public Program(ServiceProvider serviceProvider)
 {
     this.serviceProvider    = serviceProvider;
     this.statistics         = new EnoStatistics(nameof(EnoLauncher));
     this.updateDatabaseTask = Task.Run(async() => await this.UpdateDatabaseLoop());
     this.logger             = serviceProvider.GetRequiredService <ILogger <Program> >();
 }
예제 #2
0
 public EnoEngine(ILogger <EnoEngine> logger, IServiceProvider serviceProvider, EnoDbUtil databaseUtil, EnoStatistics enoStatistics)
 {
     this.logger          = logger;
     this.serviceProvider = serviceProvider;
     this.databaseUtil    = databaseUtil;
     this.statistics      = enoStatistics;
 }
예제 #3
0
 public EnoEngine(ILogger <EnoEngine> logger, Configuration configuration, IServiceProvider serviceProvider, EnoDatabaseUtil databaseUtil, EnoStatistics enoStatistics)
 {
     this.logger          = logger;
     this.configuration   = configuration;
     this.serviceProvider = serviceProvider;
     this.databaseUtil    = databaseUtil;
     this.statistics      = enoStatistics;
 }
예제 #4
0
    public async Task CalculateRoundTeamServiceStates(IServiceProvider serviceProvider, long roundId, EnoStatistics statistics)
    {
        var teams = await this.context.Teams.AsNoTracking().ToArrayAsync();

        var services = await this.context.Services.AsNoTracking().ToArrayAsync();

        var currentRoundWorstResults = new Dictionary <(long ServiceId, long TeamId), CheckerTask?>();
        var sw = new Stopwatch();

        sw.Start();
        var foo = await this.context.CheckerTasks
                  .TagWith("CalculateRoundTeamServiceStates:currentRoundTasks")
                  .Where(ct => ct.CurrentRoundId == roundId)
                  .Where(ct => ct.RelatedRoundId == roundId)
                  .OrderBy(ct => ct.CheckerResult)
                  .ThenBy(ct => ct.StartTime)
                  .ToListAsync();

        foreach (var e in foo)
        {
            if (!currentRoundWorstResults.ContainsKey((e.ServiceId, e.TeamId)))
            {
                currentRoundWorstResults[(e.ServiceId, e.TeamId)] = e;
예제 #5
0
    public async Task <FlagSubmissionResult[]> TryProcessSubmissionsBatch(
        FlagSubmissionRequest[] submissions,
        long flagValidityInRounds,
        EnoStatistics statistics)
    {
        var stopWatch = new Stopwatch();

        stopWatch.Start();

        var  results        = new FlagSubmissionResult?[submissions.Length];
        bool empty          = true;
        long okFlags        = 0;
        long duplicateFlags = 0;
        long oldFlags       = 0;
        long currentRoundId;

        try
        {
            currentRoundId = (await this.GetLastRound()) !.Id;
        }
        catch (Exception e)
        {
            this.logger.LogError($"TryProcessSubmissionsBatch could not get latest round: {e}");
            return(Array.ConvertAll(results, x => x ?? FlagSubmissionResult.Error));
        }

        var upsertStatement = new StringBuilder();

        upsertStatement.Append(
            @$ "INSERT INTO " "{nameof(EnoDbContext.SubmittedFlags)}" "
(
" "{nameof(SubmittedFlag.FlagServiceId)}" ",
" "{nameof(SubmittedFlag.FlagRoundId)}" ",
" "{nameof(SubmittedFlag.FlagOwnerId)}" ",
" "{nameof(SubmittedFlag.FlagRoundOffset)}" ",
" "{nameof(SubmittedFlag.AttackerTeamId)}" ",
" "{nameof(SubmittedFlag.RoundId)}" ",
" "{nameof(SubmittedFlag.SubmissionsCount)}" ",
" "{nameof(SubmittedFlag.Timestamp)}" "
)
VALUES");

        for (int i = 0; i < submissions.Length; i++)
        {
            var submission = submissions[i];
            if (submission.Flag.RoundId + flagValidityInRounds < currentRoundId)
            {
                results[i] = FlagSubmissionResult.Old;
                oldFlags  += 1;
            }
            else
            {
                empty = false;
                upsertStatement.Append($@"
(
{submission.Flag.ServiceId},
{submission.Flag.RoundId},
{submission.Flag.OwnerId},
{submission.Flag.RoundOffset},
{submission.AttackerTeamId},
{currentRoundId},
1,
NOW()
),");
            }
        }

        if (empty)
        {
            // TODO statistics
            return(Array.ConvertAll(results, x => x ?? throw new InvalidOperationException()));
        }

        upsertStatement.Length--; // Strip the final comma
        upsertStatement.Append($@"
ON CONFLICT
(
""{nameof(SubmittedFlag.FlagServiceId)}"",
""{nameof(SubmittedFlag.FlagRoundId)}"",
""{nameof(SubmittedFlag.FlagOwnerId)}"",
""{nameof(SubmittedFlag.FlagRoundOffset)}"",
""{nameof(SubmittedFlag.AttackerTeamId)}""
)
DO NOTHING
RETURNING
""{nameof(SubmittedFlag.FlagServiceId)}"",
""{nameof(SubmittedFlag.FlagOwnerId)}"",
""{nameof(SubmittedFlag.FlagRoundId)}"",
""{nameof(SubmittedFlag.FlagRoundOffset)}"",
""{nameof(SubmittedFlag.AttackerTeamId)}"",
""{nameof(SubmittedFlag.RoundId)}"",
""{nameof(SubmittedFlag.SubmissionsCount)}"",
""{nameof(SubmittedFlag.Timestamp)}""
;");

        List <SubmittedFlag> insertOrUpdateResults;

        try
        {
            insertOrUpdateResults = await this.context.SubmittedFlags.FromSqlRaw(upsertStatement.ToString()).ToListAsync();
        }
        catch (Exception e)
        {
            // TODO statistics
            this.logger.LogError($"{nameof(this.TryProcessSubmissionsBatch)} failed to execute: {e}");
            return(Array.ConvertAll(results, x => x ?? FlagSubmissionResult.Error));
        }

        for (int i = 0; i < submissions.Length; i++)
        {
            if (results[i] == null)
            {
                // The result entry has not been set to FlagSubmissionResult.Old, so it could be present in the upsert results
                var submissionRequest = submissions[i];
                if (insertOrUpdateResults.Count > 0 &&
                    submissionRequest.AttackerTeamId == insertOrUpdateResults[0].AttackerTeamId &&
                    submissionRequest.Flag.OwnerId == insertOrUpdateResults[0].FlagOwnerId &&
                    submissionRequest.Flag.ServiceId == insertOrUpdateResults[0].FlagServiceId &&
                    submissionRequest.Flag.RoundOffset == insertOrUpdateResults[0].FlagRoundOffset &&
                    submissionRequest.Flag.RoundId == insertOrUpdateResults[0].FlagRoundId)
                {
                    results[i] = FlagSubmissionResult.Ok;
                    insertOrUpdateResults.RemoveAt(0);
                    okFlags += 1;
                }
                else
                {
                    // It is not, so it was a duplicate
                    results[i]      = FlagSubmissionResult.Duplicate;
                    duplicateFlags += 1;
                }
            }
        }

        stopWatch.Stop();

        statistics.LogSubmissionBatchMessage(
            submissions.Length,
            okFlags,
            duplicateFlags,
            oldFlags,
            stopWatch.ElapsedMilliseconds);

        return(Array.ConvertAll(results, x => x ?? FlagSubmissionResult.Error));
    }