private void RunJob(string name, WorkerJob job)
        {
            try
            {
                _logger.Debug("Executing Job '{0}'", name);

                DateTime before = DateTime.UtcNow;

                try
                {
                    job.RunOnce();

                    DateTime after = DateTime.UtcNow;
                }
                catch (Exception ex)
                {
                    DateTime after = DateTime.UtcNow;

                    _logger.ErrorException(String.Format("Error Executing Job '{0}': {1}", name, ex.Message), ex);
                }
            }
            catch (Exception ex)
            {
                _logger.ErrorException(String.Format("Infrastructure Error Executing Job '{0}': {1}", name, ex.Message), ex);
            }
        }
Exemple #2
0
        public async Task Handle(RefreshCalculations message, IMessageHandlerContext context)
        {
            Log.Info($"RefreshCalculations. ProcessId: '{Process.GetCurrentProcess().Id}'");

            var currentJob = new WorkerJob()
            {
                ProcessId = Process.GetCurrentProcess().Id, StartDate = DateTime.UtcNow
            };

            var lastJob = await _db.WorkerJobs.OrderByDescending(o => o.EndDate).FirstOrDefaultAsync();

            var lastJobEndDate = lastJob?.EndDate ?? DateTime.MinValue;

            var checkpoint = DateTime.UtcNow;

            var unprocessedSessionWords = await _db.SessionWords.Where(w => w.DateCreated > lastJobEndDate).ToListAsync();

            Log.Info($"{unprocessedSessionWords.Count} new words found.");

            await CalculateWordsPerSession(unprocessedSessionWords);

            await CalculateWordFrequency(unprocessedSessionWords);

            Log.Info($"Saving checkpoint. Next time will process words from date '{checkpoint:s}'.");
            currentJob.EndDate = DateTime.UtcNow;
            await _db.WorkerJobs.AddAsync(currentJob);

            await _db.SaveChangesAsync();
        }
Exemple #3
0
        public async UnaryResult <Nil> ReportResult(Guid jobId, Heroine heroine, IReadOnlyList <int> selectionIds)
        {
            var workerId = await this.WorkerInitializeAsync().ConfigureAwait(false);

            await this.RetryWhenLocked(() =>
            {
                this.RunInImmediateTransaction(conn =>
                {
                    var job = conn.FindWithQuery <WorkerJob>(
                        "SELECT Choices, SearchResultId FROM WorkerJob WHERE Id = ?",
                        jobId);

                    if (job.SearchResultId.HasValue)
                    {
                        // すでに結果報告済み
                        Utils.Log.WriteMessage($"報告が重複しています (Worker: {workerId})");
                        return;
                    }

                    var jobChoices = ModelUtils.ParseChoices(job.Choices);

                    // 実際に選択したものは、 job.Choices + ずっと上
                    var choices = jobChoices.Concat(
                        Enumerable.Repeat(ChoiceAction.SelectUpper, selectionIds.Count - jobChoices.Length));

                    var searchResult = new SearchResult()
                    {
                        Selections = ModelUtils.ToSelectionsString(selectionIds),
                        Choices    = ModelUtils.ToChoicesString(choices),
                        Heroine    = heroine,
                        Timestamp  = DateTimeOffset.Now,
                    };

                    conn.Insert(searchResult);

                    conn.Execute(
                        "UPDATE WorkerJob SET WorkerId = ?, SearchResultId = ? WHERE Id = ?",
                        workerId, searchResult.Id, jobId);

                    // このレポートで発見された未探索のジョブを作成
                    for (var i = jobChoices.Length; i < selectionIds.Count; i++)
                    {
                        // 未探索の下を選ぶ
                        var newChoices = choices.Take(i).Append(ChoiceAction.SelectLower);

                        var newJob = new WorkerJob()
                        {
                            Id         = Guid.NewGuid(),
                            Choices    = ModelUtils.ToChoicesString(newChoices),
                            EnqueuedAt = DateTimeOffset.Now,
                        };

                        conn.Insert(newJob);
                    }
                });
            }).ConfigureAwait(false);

            return(Nil.Default);
        }
Exemple #4
0
        public async UnaryResult <SeekDirectionResult> SeekDirection()
        {
            var workerId = await this.WorkerInitializeAsync().ConfigureAwait(false);

            return(await this.RetryWhenLocked(() =>
            {
                return this.RunInImmediateTransaction(conn =>
                {
                    // 未着手のジョブを取得する
                    // Choices が短いものから順に着手することで、新たなジョブを開拓していく
                    var job = conn.FindWithQuery <WorkerJob>(
                        "SELECT Id, Choices FROM WorkerJob WHERE WorkerId IS NULL ORDER BY length(Choices) LIMIT 1");

                    ChoiceAction[] actions;

                    if (job == null)
                    {
                        var incompletedJobCount = conn.ExecuteScalar <int>(
                            "SELECT count(*) FROM WorkerJob WHERE SearchResultId IS NULL");

                        if (incompletedJobCount > 0)
                        {
                            // 未完了のジョブがあるが、現在着手可能なジョブはない
                            return new SeekDirectionResult(SeekDirectionResultKind.NotAvailable);
                        }

                        if (conn.Table <SearchResult>().Count() > 0)
                        {
                            // 探索結果が揃っているので、探索完了とみなす
                            return new SeekDirectionResult(SeekDirectionResultKind.Finished);
                        }

                        // 初回ジョブを作成
                        job = new WorkerJob()
                        {
                            Id = Guid.NewGuid(),
                            Choices = "",
                            WorkerId = workerId,
                            EnqueuedAt = DateTimeOffset.Now,
                        };
                        conn.Insert(job);

                        actions = Array.Empty <ChoiceAction>();
                    }
                    else
                    {
                        actions = ModelUtils.ParseChoices(job.Choices);

                        conn.Execute(
                            "UPDATE WorkerJob SET WorkerId = ? WHERE Id = ?",
                            workerId, job.Id);
                    }

                    Utils.Log.WriteMessage($"ワーカー #{workerId} にジョブ {job.Id} を指示");

                    return new SeekDirectionResult(SeekDirectionResultKind.Ok, job.Id, actions);
                });
            }).ConfigureAwait(false));
        }
Exemple #5
0
        public override void MakeRequest(I input, UnityAction <O> onJobDone)
        {
            var request = new CancelableRequest()
            {
                input = input, onJobDone = onJobDone
            };

            _requests.Enqueue(request);

            var jobInfo = new JobInfo {
                request = request, responses = _responses, job = _job
            };

            if (!_jobInfos.TryAdd(jobInfo.GetHashCode(), jobInfo))
            {
                Debug.LogError($"Failed to add Request in {GetType()}.");
            }

            var workerJob = new WorkerJob {
                workerId = GetHashCode(), jobId = jobInfo.GetHashCode()
            };

            workerJob.Schedule();
        }