private void InitializeProperties(BackgroundJob instance, Dictionary<string, string> arguments)
        {
            foreach (var arg in arguments)
            {
                var propertyInfo = _methodData.Type.GetProperty(arg.Key);
                if (propertyInfo != null)
                {
                    var converter = TypeDescriptor.GetConverter(propertyInfo.PropertyType);

                    try
                    {
                        var value = converter.ConvertFromInvariantString(arg.Value);
                        propertyInfo.SetValue(instance, value, null);
                    }
                    catch (Exception ex)
                    {
                        throw new InvalidOperationException(
                            String.Format(
                                "Could not set the property '{0}' of the instance of class '{1}'. See the inner exception for details.",
                                propertyInfo.Name,
                                _methodData.Type),
                            ex);
                    }
                }
            }
        }
        public BackgroundJob Create(CreateContext context)
        {
            var parameters = context.Parameters.ToDictionary(x => x.Key, x => JobHelper.ToJson(x.Value));

            var createdAt = DateTime.UtcNow;
            var jobId = context.Connection.CreateExpiredJob(
                context.Job,
                parameters,
                createdAt,
                TimeSpan.FromHours(1));

            var backgroundJob = new BackgroundJob(jobId, context.Job, createdAt);

            if (context.InitialState != null)
            {
                using (var transaction = context.Connection.CreateWriteTransaction())
                {
                    var applyContext = new ApplyStateContext(
                        context.Storage,
                        context.Connection,
                        transaction,
                        backgroundJob,
                        context.InitialState,
                        null);

                    _stateMachine.ApplyState(applyContext);

                    transaction.Commit();
                }
            }

            return backgroundJob;
        }
Example #3
0
        public ApplyStateContext(
            [NotNull] JobStorage storage,
            [NotNull] IStorageConnection connection,
            [NotNull] IWriteOnlyTransaction transaction,
            [NotNull] BackgroundJob backgroundJob,
            [NotNull] IState newState, 
            [CanBeNull] string oldStateName)
        {
            if (storage == null) throw new ArgumentNullException("storage");
            if (connection == null) throw new ArgumentNullException("connection");
            if (transaction == null) throw new ArgumentNullException("transaction");
            if (backgroundJob == null) throw new ArgumentNullException("backgroundJob");
            if (newState == null) throw new ArgumentNullException("newState");
            
            _backgroundJob = backgroundJob;

            Storage = storage;
            Connection = connection;
            Transaction = transaction;
            OldStateName = oldStateName;
            NewState = newState;
            JobExpirationTimeout = TimeSpan.FromDays(1);
        }
Example #4
0
        public Workflow Upsert(IEnumerable <Flow> flows, string dataId, AppReminderTypes type)
        {
            var typeStr = type.ToString();

            var tomorrow         = Tomorrow;
            var notifBeforecount = context.Flows.Count(t =>
                                                       t.IsDeleted != true &&
                                                       t.IsDraft == false
                                                       &&
                                                       (System.Data.Entity.DbFunctions.TruncateTime(t.DueDate) == Today && t.DueDate < tomorrow)
                                                       );



            var form = context.Workflows
                       .Include("Flows")
                       .FirstOrDefault(t => t.Type == typeStr && t.DataId == dataId);

            if (form == null)
            {
                form = new Workflow();
                form.Init();
                form.SetCreated();
                form.Flows  = new List <Flow>();
                form.DataId = dataId;
                form.Type   = typeStr;


                form.Flows = flows?.ToList() ?? new List <Flow>();
                foreach (var item in form.Flows)
                {
                    item.Type            = typeStr;
                    item.Status          = WorkflowForm.WF_STATUS_CREATED;
                    item.DisplayGrouping = item.DisplayGrouping ?? item.Type;
                }

                //form.Flows = flows.Select(t => {
                //    var flow = Mapper.Map<Flow>(t);
                //    flow.DueDate = flow.DueDate?.Date;
                //    flow.Status = WorkflowForm.WF_STATUS_CREATED;
                //    flow.Type = typeStr;
                //    //flow.Init();
                //    return flow;
                //}).ToList();


                context.Workflows.Add(form);
            }
            else
            {
                form.SetUpdated();
                if (form.Flows != null)
                {
                    var toDelete = form.Flows.ToList();

                    //try {
                    //    foreach (var item in toDelete) {
                    //        BackgroundJob.Enqueue(() => CancelMail(item));
                    //    }
                    //} catch (Exception exc) {
                    //    ErrorLog(exc);
                    //}

                    toDelete.ForEach(t => {
                        context.Flows.Remove(t);
                    });
                }

                form.Flows = flows?.ToList() ?? new List <Flow>();
                foreach (var item in form.Flows)
                {
                    item.Type            = typeStr;
                    item.Status          = WorkflowForm.WF_STATUS_CREATED;
                    item.DisplayGrouping = item.DisplayGrouping ?? item.Type;
                }
            }

            context.SaveChanges();

            try {
                var notifAftercount = context.Flows.Count(t =>
                                                          t.IsDeleted != true &&
                                                          t.IsDraft == false
                                                          &&
                                                          (System.Data.Entity.DbFunctions.TruncateTime(t.DueDate) == Today && t.DueDate < tomorrow)
                                                          );

                if (notifAftercount != notifBeforecount)
                {
                    BackgroundJob.Enqueue(() => _reminderSvc.DistributeReminder(false));
                }
            } catch (Exception exc) {
                ErrorLog(exc);
            }

            return(form);
        }
Example #5
0
        public string Job(string id)
        {
            var jobId = BackgroundJob.Enqueue(() => Console.Write(id));

            return(jobId);
        }
Example #6
0
        public ActionResult NewTask()
        {
            BackgroundJob.Enqueue(() => TaskType1.Execute("Worker role executed a task queued by FRONT!"));

            return(RedirectToAction("Index"));
        }
        public async Task <ActionResult> Submit(CommentCommand dto)
        {
            if (Regex.Match(dto.Content, CommonHelper.BanRegex).Length > 0)
            {
                return(ResultData(null, false, "您提交的内容包含敏感词,被禁止发表,请检查您的内容后尝试重新提交!"));
            }

            Post post = await PostService.GetByIdAsync(dto.PostId) ?? throw new NotFoundException("评论失败,文章未找到");

            if (post.DisableComment)
            {
                return(ResultData(null, false, "本文已禁用评论功能,不允许任何人回复!"));
            }

            dto.Content = dto.Content.Trim().Replace("<p><br></p>", string.Empty);
            if (dto.Content.RemoveHtmlTag().Trim().Equals(HttpContext.Session.Get <string>("comment" + dto.PostId)))
            {
                return(ResultData(null, false, "您刚才已经在这篇文章发表过一次评论了,换一篇文章吧,或者换一下评论内容吧!"));
            }

            var comment = dto.Mapper <Comment>();

            if (Regex.Match(dto.Content, CommonHelper.ModRegex).Length <= 0)
            {
                comment.Status = Status.Published;
            }

            comment.CommentDate = DateTime.Now;
            var user = HttpContext.Session.Get <UserInfoDto>(SessionKey.UserInfo);

            if (user != null)
            {
                comment.NickName   = user.NickName;
                comment.QQorWechat = user.QQorWechat;
                comment.Email      = user.Email;
                if (user.IsAdmin)
                {
                    comment.Status   = Status.Published;
                    comment.IsMaster = true;
                }
            }
            comment.Content  = dto.Content.HtmlSantinizerStandard().ClearImgAttributes();
            comment.Browser  = dto.Browser ?? Request.Headers[HeaderNames.UserAgent];
            comment.IP       = ClientIP;
            comment.Location = comment.IP.GetIPLocation().Split("|").Where(s => !int.TryParse(s, out _)).ToHashSet().Join("|");
            comment          = CommentService.AddEntitySaved(comment);
            if (comment == null)
            {
                return(ResultData(null, false, "评论失败"));
            }

            HttpContext.Session.Set("comment" + comment.PostId, comment.Content.RemoveHtmlTag().Trim());
            var emails = new HashSet <string>();
            var email  = CommonHelper.SystemSettings["ReceiveEmail"]; //站长邮箱

            emails.Add(email);
            var content = (await System.IO.File.ReadAllTextAsync(HostEnvironment.WebRootPath + "/template/notify.html"))
                          .Replace("{{title}}", post.Title)
                          .Replace("{{time}}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
                          .Replace("{{nickname}}", comment.NickName)
                          .Replace("{{content}}", comment.Content);

            if (comment.Status == Status.Published)
            {
                if (!comment.IsMaster)
                {
                    await MessageService.AddEntitySavedAsync(new InternalMessage()
                    {
                        Title   = $"来自【{comment.NickName}】的新文章评论",
                        Content = comment.Content,
                        Link    = Url.Action("Details", "Post", new { id = comment.PostId, cid = comment.Id }, Request.Scheme) + "#comment"
                    });
                }
#if !DEBUG
                if (comment.ParentId == 0)
                {
                    emails.Add(post.Email);
                    emails.Add(post.ModifierEmail);
                    //新评论,只通知博主和楼主
                    foreach (var s in emails)
                    {
                        BackgroundJob.Enqueue(() => CommonHelper.SendMail(Request.Host + "|博客文章新评论:", content.Replace("{{link}}", Url.Action("Details", "Post", new { id = comment.PostId, cid = comment.Id }, Request.Scheme) + "#comment"), s));
                    }
                }
                else
                {
                    //通知博主和上层所有关联的评论访客
                    var pid = CommentService.GetParentCommentIdByChildId(comment.Id);
                    emails.AddRange(CommentService.GetSelfAndAllChildrenCommentsByParentId(pid).Select(c => c.Email).ToArray());
                    emails.AddRange(post.Email, post.ModifierEmail);
                    emails.Remove(comment.Email);
                    string link = Url.Action("Details", "Post", new { id = comment.PostId, cid = comment.Id }, Request.Scheme) + "#comment";
                    foreach (var s in emails)
                    {
                        BackgroundJob.Enqueue(() => CommonHelper.SendMail($"{Request.Host}{CommonHelper.SystemSettings["Title"]}文章评论回复:", content.Replace("{{link}}", link), s));
                    }
                }
#endif
                return(ResultData(null, true, "评论发表成功,服务器正在后台处理中,这会有一定的延迟,稍后将显示到评论列表中"));
            }

            foreach (var s in emails)
            {
                BackgroundJob.Enqueue(() => CommonHelper.SendMail(Request.Host + "|博客文章新评论(待审核):", content.Replace("{{link}}", Url.Action("Details", "Post", new { id = comment.PostId, cid = comment.Id }, Request.Scheme) + "#comment") + "<p style='color:red;'>(待审核)</p>", s));
            }

            return(ResultData(null, true, "评论成功,待站长审核通过以后将显示"));
        }
Example #8
0
        public ActionResult Edit(PostInputDto post, bool notify = true, bool reserve = true)
        {
            post.Content = ReplaceImgSrc(Regex.Replace(post.Content.Trim(), @"<img\s+[^>]*\s*src\s*=\s*['""]?(\S+\.\w{3,4})['""]?[^/>]*/>", "<img src=\"$1\"/>")).Replace("/thumb150/", "/large/");
            if (!CategoryBll.Any(c => c.Id == post.CategoryId && c.Status == Status.Available))
            {
                return(ResultData(null, message: "请选择一个分类"));
            }
            if (string.IsNullOrEmpty(post.Label?.Trim()) || post.Label.Equals("null"))
            {
                post.Label = null;
            }
            else if (post.Label.Trim().Length > 50)
            {
                post.Label = post.Label.Replace(",", ",");
                post.Label = post.Label.Trim().Substring(0, 50);
            }
            else
            {
                post.Label = post.Label.Replace(",", ",");
            }
            if (!post.IsWordDocument)
            {
                post.ResourceName = null;
            }

            if (string.IsNullOrEmpty(post.ProtectContent) || post.ProtectContent.Equals("null", StringComparison.InvariantCultureIgnoreCase))
            {
                post.ProtectContent = null;
            }
            post.ModifyDate = DateTime.Now;
            Post p = PostBll.GetById(post.Id);

            if (reserve)
            {
                var history = p.Mapper <PostHistoryVersion>();
                p.PostHistoryVersion.Add(history);
            }
            Mapper.Map(post, p);
            if (!string.IsNullOrEmpty(post.Seminars))
            {
                var tmp = post.Seminars.Split(',').Distinct();
                p.Seminar.Clear();
                tmp.ForEach(s =>
                {
                    p.Seminar.Add(SeminarBll.GetFirstEntity(e => e.Title.Equals(s)));
                });
            }

            bool b = PostBll.UpdateEntitySaved(p);

            if (b)
            {
#if !DEBUG
                if (notify && "false" == GetSettings("DisabledEmailBroadcast"))
                {
                    var    cast = BroadcastBll.LoadEntities(c => c.Status == Status.Subscribed).ToList();
                    string link = Request.Url?.Scheme + "://" + Request.Url?.Authority + "/" + p.Id;
                    cast.ForEach(c =>
                    {
                        var ts         = DateTime.Now.GetTotalMilliseconds();
                        string content = System.IO.File.ReadAllText(Request.MapPath("/template/broadcast.html")).Replace("{{link}}", link + "?email=" + c.Email).Replace("{{time}}", post.ModifyDate.ToString("yyyy-MM-dd HH:mm:ss")).Replace("{{title}}", post.Title).Replace("{{author}}", post.Author).Replace("{{content}}", post.Content.RemoveHtmlTag(150)).Replace("{{cancel}}", Url.Action("Subscribe", "Subscribe", new
                        {
                            c.Email,
                            act      = "cancel",
                            validate = c.ValidateCode,
                            timespan = ts,
                            hash     = (c.Email + "cancel" + c.ValidateCode + ts).AESEncrypt(ConfigurationManager.AppSettings["BaiduAK"])
                        }, Request.Url.Scheme));
                        BackgroundJob.Schedule(() => SendMail(GetSettings("Title") + "博客有新文章发布了", content, c.Email), (p.ModifyDate - DateTime.Now));
                    });
                }
#endif
                HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.UpdateLucene));
                return(ResultData(p.Mapper <PostOutputDto>(), message: "文章修改成功!"));
            }
            return(ResultData(null, false, "文章修改失败!"));
        }
Example #9
0
        public ActionResult <ModuleAutoInstallPushNotification> TryToAutoInstallModules()
        {
            var notification = new ModuleAutoInstallPushNotification(User.Identity.Name)
            {
                Title = "Modules installation",
                //set completed by default
                Finished = DateTime.UtcNow
            };

            if (!_settingsManager.GetValue(PlatformConstants.Settings.Setup.ModulesAutoInstalled.Name, false))
            {
                lock (_lockObject)
                {
                    if (!_settingsManager.GetValue(PlatformConstants.Settings.Setup.ModulesAutoInstalled.Name, false))
                    {
                        var moduleBundles = _externalModuleCatalogOptions.AutoInstallModuleBundles;
                        if (!moduleBundles.IsNullOrEmpty())
                        {
                            _settingsManager.SetValue(PlatformConstants.Settings.Setup.ModulesAutoInstalled.Name, true);
                            _settingsManager.SetValue(PlatformConstants.Settings.Setup.ModulesAutoInstallState.Name, AutoInstallState.Processing);

                            EnsureModulesCatalogInitialized();

                            var modules             = new List <ManifestModuleInfo>();
                            var moduleVersionGroups = _externalModuleCatalog.Modules
                                                      .OfType <ManifestModuleInfo>()
                                                      .Where(x => x.Groups.Intersect(moduleBundles, StringComparer.OrdinalIgnoreCase).Any())
                                                      .GroupBy(x => x.Id);

                            //Need install only latest versions
                            foreach (var moduleVersionGroup in moduleVersionGroups)
                            {
                                var alreadyInstalledModule = _externalModuleCatalog.Modules.OfType <ManifestModuleInfo>().FirstOrDefault(x => x.IsInstalled && x.Id.EqualsInvariant(moduleVersionGroup.Key));
                                //skip already installed modules
                                if (alreadyInstalledModule == null)
                                {
                                    var latestVersion = moduleVersionGroup.OrderBy(x => x.Version).LastOrDefault();
                                    if (latestVersion != null)
                                    {
                                        modules.Add(latestVersion);
                                    }
                                }
                            }

                            var modulesWithDependencies = _externalModuleCatalog.CompleteListWithDependencies(modules)
                                                          .OfType <ManifestModuleInfo>()
                                                          .Where(x => !x.IsInstalled)
                                                          .Select(x => new ModuleDescriptor(x))
                                                          .ToArray();

                            if (modulesWithDependencies.Any())
                            {
                                var options = new ModuleBackgroundJobOptions
                                {
                                    Action  = ModuleAction.Install,
                                    Modules = modulesWithDependencies
                                };
                                //reset finished date
                                notification.Finished = null;
                                BackgroundJob.Enqueue(() => ModuleBackgroundJob(options, notification));
                            }
                        }
                    }
                }
            }
            return(Ok(notification));
        }
 private void BackgroundThreadMain(BackgroundJob job)
 {
     try
     {
         Step[][] solutions = this.boardSolverService.GetSolution(job.StateToSolve, job.Goal, job.CancellationTokenSource.Token);
         this.dispatcher.BeginInvoke(() => this.OnSolved(job, solutions));
     }
     catch (OperationCanceledException)
     {
     }
 }
Example #11
0
        public async Task TempBanMemberAsync(CommandContext context,
                                             DiscordMember member,
                                             [Description("Duration to ban the member for (must be quoted if there are any spaces, however it should work with colloquial language)")]
                                             string durationOfBan,
                                             [Description("Number of days worth of messages to delete (max of 7 days)")]
                                             int numDays = 0,
                                             [RemainingText]
                                             string?reason = null)
        {
            if (numDays < 0 || numDays > 7)
            {
                await context.RespondAsync("You provided an invalid number of days worth of messages to delete");

                return;
            }

            DateTimeV2ModelResult?durationResult = DateTimeRecognizer
                                                   .RecognizeDateTime(durationOfBan, culture: Culture.English)
                                                   .Select(model => model.ToDateTimeV2ModelResult())
                                                   .Where(result => result.TypeName is DateTimeV2Type.Duration)
                                                   .FirstOrDefault();

            if (durationResult == null)
            {
                await context.RespondAsync("There was an error parsing the duration");

                return;
            }

            Duration duration       = (Duration?)durationResult.Values.FirstOrDefault()?.Value ?? Duration.FromMinutes(5);
            string   durationString = Period.FromSeconds((long)duration.TotalSeconds).AsHumanReadableString();

            DiscordEmbedBuilder messageEmbed = new DiscordEmbedBuilder()
                                               .WithTitle($"You have been temporarily banned from {context.Guild.Name}!")
                                               .AddField("Duration", durationString);

            if (reason != null)
            {
                messageEmbed.AddField("Reason:", reason);
            }

            DiscordChannel?logChannel = await this.SendModerationEmbedAndGetLogChannel(messageEmbed, member, context.Member, context.Guild);

            await member.BanAsync(numDays, reason);

            await context.Message.CreateReactionAsync(DiscordEmoji.FromName(context.Client, ":white_check_mark:"));

            await this.mediator.Send(new GuildModerationAuditRecords.Add(context.Guild.Id, context.User.Id, member.Id, ModerationActionType.TEMPBAN, reason));

            if (logChannel == null)
            {
                return;
            }

            DiscordEmbedBuilder successEmbed = new DiscordEmbedBuilder()
                                               .WithTitle($"{member.Username} was temporarily banned")
                                               .AddField("Moderator", context.User.Username)
                                               .AddField("Time Banned", durationString)
                                               .WithFooter($"{this.clock.GetCurrentInstant():g}");

            if (reason != null)
            {
                successEmbed.AddField("Reason:", reason);
            }

            await logChannel.SendMessageAsync(embed : successEmbed);

            string jobId = BackgroundJob.Schedule <ModerationService>((service) =>
                                                                      service.UnbanAsync(context.Guild.Id, member.Id),
                                                                      duration.ToTimeSpan()
                                                                      );

            await this.mediator.Send(new GuildBackgroundJobs.Add(jobId, context.Guild.Id, $"Unban - {member.DisplayName}", this.clock.GetCurrentInstant() + duration, GuildJobType.TEMP_BAN));
        }
Example #12
0
        public async Task TempMuteMemberAsync(CommandContext context,
                                              [Description("The member to mute")]
                                              DiscordMember member,
                                              [Description("Duration to mute the member for (must be quoted if there are any spaces, however it should work with colloquial language)")]
                                              string durationOfMute,
                                              [RemainingText]
                                              [Description("The reason for the mute")]
                                              string?reason = null)
        {
            DateTimeV2ModelResult?durationResult = DateTimeRecognizer
                                                   .RecognizeDateTime(durationOfMute, culture: Culture.English)
                                                   .Select(model => model.ToDateTimeV2ModelResult())
                                                   .Where(result => result.TypeName is DateTimeV2Type.Duration)
                                                   .FirstOrDefault();

            if (durationResult == null)
            {
                await context.RespondAsync("There was an error parsing the duration");

                return;
            }

            Duration duration       = (Duration?)durationResult.Values.FirstOrDefault()?.Value ?? Duration.FromMinutes(5);
            string   durationString = Period.FromSeconds((long)duration.TotalSeconds).AsHumanReadableString();

            DiscordRole mutedRole = await GetOrCreateMutedRole(context);

            DiscordEmbedBuilder successEmbed = new DiscordEmbedBuilder()
                                               .WithTitle($"You have been temporarily muted in {context.Guild.Name}!")
                                               .AddField("Duration", durationString);

            if (reason != null)
            {
                successEmbed.AddField("Reason:", reason);
            }

            DiscordChannel?logChannel = await this.SendModerationEmbedAndGetLogChannel(successEmbed, member, context.Member, context.Guild);

            await member.GrantRoleAsync(mutedRole, reason);

            await this.mediator.Send(new GuildModerationAuditRecords.Add(context.Guild.Id, context.User.Id, member.Id, ModerationActionType.TEMPMUTE, reason));

            await context.Message.CreateReactionAsync(DiscordEmoji.FromName(context.Client, ":white_check_mark:"));

            string jobId = BackgroundJob.Schedule <ModerationService>(service => service.RemoveRole(context.Guild.Id, member.Id, mutedRole.Id), duration.ToTimeSpan());

            await this.mediator.Send(new GuildBackgroundJobs.Add(jobId, context.Guild.Id, $"Unmute - {member.DisplayName}", this.clock.GetCurrentInstant() + duration, GuildJobType.TEMP_MUTE));

            if (logChannel == null)
            {
                return;
            }

            successEmbed = new DiscordEmbedBuilder()
                           .WithTitle($"{member.DisplayName} was muted")
                           .AddField("Moderator", context.Member.DisplayName)
                           .AddField("Duration", durationString)
                           .WithFooter($"{this.clock.GetCurrentInstant():g}");

            if (reason != null)
            {
                successEmbed.AddField("Reason", reason);
            }

            await logChannel.SendMessageAsync(embed : successEmbed);
        }
Example #13
0
        public string Delete([FromBody] DeleteDocument document)
        {
            var jobId = BackgroundJob.Enqueue <Deployment>(x => x.DeleteSync(document.deploymentLog, document.accountDetails));

            return(jobId);
        }
Example #14
0
        public string Deploy([FromBody] DeploymentDocument document)
        {
            var jobId = BackgroundJob.Enqueue <Deployment>(x => x.DeploySync(document.template, document.parameterValues, document.accountDetails));

            return(jobId);
        }
Example #15
0
        public IActionResult BemVimdos()
        {
            var jobId = BackgroundJob.Enqueue(() => SendBemVimdosEmail("Bem vimdos entre com seu email"));

            return(Ok($"Job ID:{jobId}. Bem vimdos entre com seu email!"));
        }
        private IState ChangeState(
            StateChangeContext context, BackgroundJob backgroundJob, IState toState, string oldStateName)
        {
            using (var transaction = context.Connection.CreateWriteTransaction())
            {
                var applyContext = new ApplyStateContext(
                    context.Storage,
                    context.Connection,
                    transaction,
                    backgroundJob,
                    toState,
                    oldStateName);

                var appliedState = _stateMachine.ApplyState(applyContext);

                transaction.Commit();

                return appliedState;
            }
        }
 public static string StartJobService <TEntity>(this TEntity entity) where TEntity : IEntity =>
 BackgroundJob.Enqueue <IJobService <TEntity> >(jobService => jobService.Execute(entity));
Example #18
0
        public IActionResult ImportProduct([FromBody] ImportProductDto product)
        {
            var jobId = BackgroundJob.Enqueue(() => _importJobHelper.Import(product));

            return(Ok($"Job Id {jobId} for Import Completed."));
        }
        private void OnSolved(BackgroundJob job, Step[][] solutions)
        {
            if (job.CancellationTokenSource.IsCancellationRequested)
            {
                return;
            }

            this.Status = SolverServiceStatus.Solved;
            this.Solutions = solutions
                .OrderBy(solution => string.Join(",", solution))
                .Select(solution => solution.Select(step => new SolutionStep(step, SolutionStepStatus.NotSteppedYet)).ToList())
                .ToList();

            this.SolutionLength = solutions[0].Length;
            this.nextStepIndex = 0;
            this.solvedBoardState = job.StateToSolve;

            this.messageBus.Publish(new SolutionsFound(job.InitialState, job.StateToSolve, solutions));
        }
Example #20
0
 public async Task Get([FromQuery] int start, [FromQuery] int end)
 {
     BackgroundJob.Enqueue <GetRangedShowsJob>(e => e.Handle(start, end));
 }
Example #21
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment() || env.IsEnvironment("Test"))
            {
                app.UseDeveloperExceptionPage();

                #region init swagger

                app.UseStaticFiles();
                // Enable the Swagger UI middleware and the Swagger generator

                app.UseAuthentication();

                app.UseSwaggerUi3(typeof(Startup).GetTypeInfo().Assembly, settings =>
                {
                    settings.SwaggerRoute            = "/api/swagger/v1/swagger.json2";
                    settings.SwaggerUiRoute          = "/api/swagger";
                    settings.GeneratorSettings.Title = "8a.nu API";
                    settings.GeneratorSettings.DefaultPropertyNameHandling = PropertyNameHandling.CamelCase;

                    // let's add correct scheme so swagger points to right locations
                    settings.PostProcess = document =>
                    {
                        document.Schemes.Clear();
                        if (!env.IsDevelopment())
                        {
                            document.Schemes.Add(NSwag.SwaggerSchema.Https);
                        }
                        else
                        {
                            document.Schemes.Add(NSwag.SwaggerSchema.Http);
                        }
                    };
                });

                Debug.WriteLine("see swagger at: /api/swagger");

                #endregion init swagger
            }

            // Shows UseCors with CorsPolicyBuilder.
            // TODO: change this!
            // https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.1
            app.UseCors("AllowAllHeaders");

            app.UseAuthentication();
            app.UseMvc();

            app.UseHangfireDashboard();
            app.UseHangfireServer();

            Console.WriteLine("start loading cache...");
            using (var serviceScope = app.ApplicationServices.CreateScope())
            {
                try
                {
                    // todo: change this to hosted service
                    // https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.1
                    var statisticsService = serviceScope.ServiceProvider.GetService <IStatisticsService>();
                    var elasticService    = serviceScope.ServiceProvider.GetService <IElasticService>();

                    // start only if needed
                    if (!elasticService.AreIndexesCreated)
                    {
                        BackgroundJob.Enqueue(() => statisticsService.CreateStatistics());
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("error loading cache...");
                    Console.Write(ex);
                }
            }
        }
Example #22
0
 public IActionResult Enqueue([FromBody] CommandRequest commandRequest)
 {
     BackgroundJob.Enqueue(() => JobJob.DoJob(commandRequest.Command));
     return(Json("Ok"));
 }
        private bool EnqueueBackgroundJob(
            BackgroundProcessContext context,
            IStorageConnection connection,
            string recurringJobId,
            DateTime now)
        {
            using (connection.AcquireDistributedRecurringJobLock(recurringJobId, LockTimeout))
            {
                try
                {
                    var recurringJob = connection.GetRecurringJob(recurringJobId, _timeZoneResolver, now);

                    if (recurringJob == null)
                    {
                        using (var transaction = connection.CreateWriteTransaction())
                        {
                            transaction.RemoveFromSet("recurring-jobs", recurringJobId);
                            transaction.Commit();
                        }

                        return(false);
                    }

                    // If a recurring job has the "V" field, then it was created by a newer
                    // version. Despite we can handle 1.7.0-based recurring jobs just fine,
                    // future versions may introduce new features anyway, so it's safer to
                    // let other servers to handle this recurring job.
                    if (recurringJob.Version.HasValue && recurringJob.Version > 2)
                    {
                        return(false);
                    }

                    BackgroundJob backgroundJob = null;
                    IReadOnlyDictionary <string, string> changedFields;

                    if (recurringJob.TrySchedule(out var nextExecution, out var error))
                    {
                        if (nextExecution.HasValue && nextExecution <= now)
                        {
                            backgroundJob = _factory.TriggerRecurringJob(context.Storage, connection, _profiler, recurringJob, now);

                            if (String.IsNullOrEmpty(backgroundJob?.Id))
                            {
                                _logger.Debug($"Recurring job '{recurringJobId}' execution at '{nextExecution}' has been canceled.");
                            }
                        }

                        recurringJob.IsChanged(out changedFields, out nextExecution);
                    }
                    else
                    {
                        _logger.ErrorException($"Recurring job '{recurringJobId}' can't be scheduled due to an error and will be disabled.", error);
                        recurringJob.Disable(error, out changedFields, out nextExecution);
                    }

                    // We always start a transaction, regardless our recurring job was updated or not,
                    // to prevent from infinite loop, when there's an old processing server (pre-1.7.0)
                    // in our environment that doesn't know it should modify the score for entries in
                    // the recurring jobs set.
                    using (var transaction = connection.CreateWriteTransaction())
                    {
                        if (backgroundJob != null)
                        {
                            _factory.StateMachine.EnqueueBackgroundJob(
                                context.Storage,
                                connection,
                                transaction,
                                recurringJob,
                                backgroundJob,
                                "Triggered by recurring job scheduler",
                                _profiler);
                        }

                        transaction.UpdateRecurringJob(recurringJobId, changedFields, nextExecution);

                        transaction.Commit();
                        return(true);
                    }
                }
#if !NETSTANDARD1_3
                catch (TimeZoneNotFoundException ex)
                {
#else
                catch (Exception ex)
                {
                    // https://github.com/dotnet/corefx/issues/7552
                    if (!ex.GetType().Name.Equals("TimeZoneNotFoundException"))
                    {
                        throw;
                    }
#endif

                    _logger.ErrorException(
                        $"Recurring job '{recurringJobId}' was not triggered: {ex.Message}.",
                        ex);
                }

                return(false);
            }
        }
Example #24
0
        public async Task <HttpResponseMessage> Patch([FromUri] Guid id, [FromBody] Card card)
        {
            var principal = HttpContext.Current.User as Principal;

            using (var repository = new Repository(principal.UserId))
            {
                if (repository.ServiceUser == null)
                {
                    return(Request.CreateResponse(HttpStatusCode.Forbidden));
                }
                var cardModel = await repository.Context.Cards.FindByGuidAsync(id);

                await repository.Context.Entry(cardModel).Reference(x => x.Status).LoadAsync();

                await repository.Context.Entry(cardModel).Reference(x => x.Creator).LoadAsync();

                if (repository.ServiceUser != null)
                {
                    await repository.Context.Entry(repository.ServiceUser).Reference(x => x.Role).LoadAsync();

                    if (cardModel.Status.Guid == PredefinedGuids.Final)
                    {
                        if (repository.ServiceUser.Role.Guid == PredefinedGuids.Developer ||
                            repository.ServiceUser.Role.Guid != PredefinedGuids.Administrator ||
                            repository.ServiceUser.Role.Guid != PredefinedGuids.ServiceUser)
                        {
                            return(Request.CreateResponse(HttpStatusCode.Forbidden, "Card is marked as final"));
                        }
                    }
                }



                await repository.Context.Entry(cardModel).Reference(x => x.Faction).LoadAsync();

                await repository.Context.Entry(cardModel).Reference(x => x.Serie).LoadAsync();

                await repository.Context.Entry(cardModel).Reference(x => x.Type).LoadAsync();

                await repository.Context.Entry(cardModel).Reference(x => x.Status).LoadAsync();

                var serieModel = await repository.Context.Series.FindByGuidAsync(card.Serie.Guid);

                var factionModel = await repository.Context.Factions.FindByGuidAsync(card.Faction.Guid);

                var cardTypeModel = await repository.Context.CardTypes.FindByGuidAsync(card.Type.Guid);

                var statusModel = await repository.Context.Statuses.FindByGuidAsync(card.Status.Guid);

                var ruleSetModel = await repository.Context.RuleSets.FindByGuidAsync(card.RuleSet.Guid);

                var hasLayoutChanges = false;

                if (card.Name != cardModel.Name)
                {
                    hasLayoutChanges = true;
                }
                if (card.Faction.Guid != cardModel.Faction.Guid)
                {
                    hasLayoutChanges = true;
                }
                if (card.Type.Guid != cardModel.Type.Guid)
                {
                    hasLayoutChanges = true;
                }

                if (card.FirstName != cardModel.FirstName)
                {
                    hasLayoutChanges = true;
                }
                if (card.LastName != cardModel.LastName)
                {
                    hasLayoutChanges = true;
                }
                if (card.Artist != cardModel.Artist)
                {
                    hasLayoutChanges = true;
                }
                if (card.SubType != cardModel.SubType)
                {
                    hasLayoutChanges = true;
                }
                if (card.Cost != cardModel.Cost)
                {
                    hasLayoutChanges = true;
                }
                if (card.Loyalty != cardModel.Loyalty)
                {
                    hasLayoutChanges = true;
                }
                if (card.Attack != cardModel.Attack)
                {
                    hasLayoutChanges = true;
                }
                if (card.Defense != cardModel.Defense)
                {
                    hasLayoutChanges = true;
                }
                if (card.Info != cardModel.Info)
                {
                    hasLayoutChanges = true;
                }
                if (card.LayoutText != cardModel.LayoutText)
                {
                    hasLayoutChanges = true;
                }

                cardModel.Patch(card, serieModel, factionModel, cardTypeModel, statusModel, ruleSetModel, repository.ServiceUser);



                if (hasLayoutChanges)
                {
                    var jobId = cardModel.PngCreationJobId;
                    if (!string.IsNullOrEmpty(jobId))
                    {
                        BackgroundJob.Delete(jobId);
                    }

                    var cardGenerator = new CardGenerator(card);
                    await cardGenerator.Generate();

                    await cardGenerator.Generate(false);

                    cardModel.PngCreationJobId = BackgroundJob.Schedule(() => CardGenerator.CreatePngJob(card.Guid, card.Faction.Name, card.Type.Name), TimeSpan.FromMinutes(1));
                    //CardGenerator.CreatePngJob(card.Guid, card.Faction.Name, card.Type.Name);
                }
                await repository.Context.SaveChangesAsync();

                return(Request.CreateResponse(cardModel.FromDal()));
            }
        }
Example #25
0
        public virtual IActionResult AnnualRolloverGet([FromRoute] int id)
        {
            bool exists = _context.HetDistrict.Any(a => a.DistrictId == id);

            // not found
            if (!exists)
            {
                return(new ObjectResult(new HetsResponse("HETS-01", ErrorViewModel.GetDescription("HETS-01", _configuration))));
            }

            // determine the current fiscal year
            DateTime fiscalStart;

            if (DateTime.UtcNow.Month == 1 || DateTime.UtcNow.Month == 2 || DateTime.UtcNow.Month == 3)
            {
                fiscalStart = new DateTime(DateTime.UtcNow.AddYears(-1).Year, 4, 1);
            }
            else
            {
                fiscalStart = new DateTime(DateTime.UtcNow.Year, 4, 1);
            }

            // get record and ensure it isn't already processing
            HetDistrictStatus status = AnnualRolloverHelper.GetRecord(id, _context);

            if (status == null)
            {
                return(new ObjectResult(new HetsResponse("HETS-01", ErrorViewModel.GetDescription("HETS-01", _configuration))));
            }

            if (status.CurrentFiscalYear == fiscalStart.Year)
            {
                // return - cannot rollover again
                return(new ObjectResult(status));
            }

            if (status.DisplayRolloverMessage == true ||
                (status.ProgressPercentage != null && status.ProgressPercentage > 0))
            {
                // return already active
                return(new ObjectResult(status));
            }

            // serialize scoring rules from config into json string
            IConfigurationSection scoringRules = _configuration.GetSection("SeniorityScoringRules");
            string seniorityScoringRules       = GetConfigJson(scoringRules);

            // get connection string
            string connectionString = GetConnectionString();

            // queue the job
            BackgroundJob.Enqueue(() => AnnualRolloverHelper.AnnualRolloverJob(null, id, seniorityScoringRules, connectionString));

            // get counts for this district
            int localAreaCount = _context.HetLocalArea
                                 .Count(a => a.ServiceArea.DistrictId == id);

            int equipmentCount = _context.HetDistrictEquipmentType
                                 .Count(a => a.DistrictId == id);

            // update status - job is kicked off
            status.LocalAreaCount             = localAreaCount;
            status.DistrictEquipmentTypeCount = equipmentCount;
            status.ProgressPercentage         = 1;
            status.DisplayRolloverMessage     = true;

            _context.HetDistrictStatus.Update(status);
            _context.SaveChanges();

            return(new ObjectResult(status));
        }
Example #26
0
        public ActionResult Write(PostInputDto post, DateTime?timespan, bool schedule = false)
        {
            post.Content = ReplaceImgSrc(Regex.Replace(post.Content.Trim(), @"<img\s+[^>]*\s*src\s*=\s*['""]?(\S+\.\w{3,4})['""]?[^/>]*/>", "<img src=\"$1\"/>")).Replace("/thumb150/", "/large/"); //提取img标签,提取src属性并重新创建个只包含src属性的img标签
            if (!CategoryBll.Any(c => c.Id == post.CategoryId && c.Status == Status.Available))
            {
                return(ResultData(null, message: "请选择一个分类"));
            }
            if (string.IsNullOrEmpty(post.Label?.Trim()) || post.Label.Equals("null"))
            {
                post.Label = null;
            }
            else if (post.Label.Trim().Length > 50)
            {
                post.Label = post.Label.Replace(",", ",");
                post.Label = post.Label.Trim().Substring(0, 50);
            }
            else
            {
                post.Label = post.Label.Replace(",", ",");
            }
            if (!post.IsWordDocument)
            {
                post.ResourceName = null;
            }
            if (string.IsNullOrEmpty(post.ProtectContent) || post.ProtectContent.Equals("null", StringComparison.InvariantCultureIgnoreCase))
            {
                post.ProtectContent = null;
            }
            post.Status     = Status.Pended;
            post.PostDate   = DateTime.Now;
            post.ModifyDate = DateTime.Now;
            Post p = post.Mapper <Post>();

            if (!string.IsNullOrEmpty(post.Seminars))
            {
                var tmp = post.Seminars.Split(',').Distinct();
                tmp.ForEach(s =>
                {
                    var id = s.ToInt32();
                    p.Seminar.Add(SeminarBll.GetById(id));
                });
            }
            p.PostAccessRecord.Add(new PostAccessRecord()
            {
                AccessTime = DateTime.Today,
                ClickCount = 0
            });
            if (schedule)
            {
                if (timespan.HasValue && timespan.Value > DateTime.Now)
                {
                    p.Status     = Status.Schedule;
                    p.PostDate   = timespan.Value;
                    p.ModifyDate = timespan.Value;
                    HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.PublishPost), args: p);
                    return(ResultData(p.Mapper <PostOutputDto>(), message: schedule ? $"文章于{timespan.Value:yyyy-MM-dd HH:mm:ss}将会自动发表!" : "文章发表成功!"));
                }
                return(ResultData(null, false, "如果要定时发布,请选择正确的一个将来时间点!"));
            }
            p = PostBll.AddEntitySaved(p);
            if (p != null)
            {
                if ("false" == GetSettings("DisabledEmailBroadcast"))
                {
                    var    cast = BroadcastBll.LoadEntities(c => c.Status == Status.Subscribed).ToList();
                    string link = Request.Url?.Scheme + "://" + Request.Url?.Authority + "/" + p.Id;
                    cast.ForEach(c =>
                    {
                        var ts         = DateTime.Now.GetTotalMilliseconds();
                        string content = System.IO.File.ReadAllText(Request.MapPath("/template/broadcast.html")).Replace("{{link}}", link + "?email=" + c.Email).Replace("{{time}}", post.ModifyDate.ToString("yyyy-MM-dd HH:mm:ss")).Replace("{{title}}", post.Title).Replace("{{author}}", post.Author).Replace("{{content}}", post.Content.RemoveHtmlTag(150)).Replace("{{cancel}}", Url.Action("Subscribe", "Subscribe", new
                        {
                            c.Email,
                            act      = "cancel",
                            validate = c.ValidateCode,
                            timespan = ts,
                            hash     = (c.Email + "cancel" + c.ValidateCode + ts).AESEncrypt(ConfigurationManager.AppSettings["BaiduAK"])
                        }, Request.Url.Scheme));
                        BackgroundJob.Schedule(() => SendMail(GetSettings("Title") + "博客有新文章发布了", content, c.Email), (p.ModifyDate - DateTime.Now));
                    });
                }
                HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.UpdateLucene));
                return(ResultData(null, true, "文章发表成功!"));
            }
            return(ResultData(null, false, "文章发表失败!"));
        }
Example #27
0
 public bool StartPlexContentCacher()
 {
     BackgroundJob.Enqueue(() => _plexContentSync.CacheContent(false));
     return(true);
 }
Example #28
0
        public async Task <IActionResult> LoginCallback(string returnUrl)
        {
            var authenticateResult = await HttpContext.AuthenticateAsync(FacebookDefaults.AuthenticationScheme);

            if (!authenticateResult.Succeeded)
            {
                return(BadRequest()); // TODO: Handle this better.
            }
            var token = string.Empty;
            var val   = authenticateResult.Ticket.Properties.Items.TryGetValue(".Token.access_token", out token);



            // check permission first #########################################################################
            var permissions = await _facebookHelper.GetPermissions(token);

            string      _msg_permission = string.Empty;
            Permissions list_permissions;

            if (permissions != null)
            {
                string data = JsonConvert.SerializeObject(permissions);
                list_permissions = JsonConvert.DeserializeObject <Permissions>(data);
                bool check_permission = true;
                foreach (var peritem in list_permissions.data)
                {
                    if (peritem.permission == "email" && peritem.status == "declined")
                    {
                        _msg_permission += "Địa chỉ email,";
                        check_permission = false;
                    }
                    if (peritem.permission == "user_link" && peritem.status == "declined")
                    {
                        _msg_permission += "Liên kết dòng thời gian,";
                        check_permission = false;
                    }
                    if (peritem.permission == "user_posts" && peritem.status == "declined")
                    {
                        _msg_permission += "Bài viết trên dòng thời gian,";
                        check_permission = false;
                    }
                    if (peritem.permission == "user_friends" && peritem.status == "declined")
                    {
                        _msg_permission += "Danh sách bạn bè,";
                        check_permission = false;
                    }
                }

                if (!string.IsNullOrEmpty(_msg_permission) && check_permission == false)
                {
                    this.AddAlertInfo($"Bạn cần cho phép Microkol quyền đọc {_msg_permission} để đăng nhập hệ thống!");
                    await SignOut();

                    return(RedirectToAction("Login"));
                }
            }
            //#################################################################################################


            var loginInfo = await _facebookHelper.GetLoginProviderAsync(token);

            if (loginInfo == null)
            {
                this.AddAlertDanger($"Lỗi khi lấy thông tin từ hệ thống. Xin vui lòng thử lại. Token {token}");
                return(RedirectToAction("Login"));
            }



            //var accountProvider = await _accountService.GetAccountProviderByProvider(AccountProviderNames.Facebook, loginInfo.ProviderId, token);
            //var accountProviderExist = accountProvider != null;

            var auth = await _accountService.GetAuth(loginInfo);

            if (auth == null)
            {
                await SignOut();

                this.AddAlertDanger("Lỗi khi lấy thông tin đăng nhập. Tài khoản đã bị khóa hoặc xóa. Xin vui lòng liên hệ quản trị hệ thống");
                return(RedirectToAction("Login"));
            }

            /*
             * Ko update token - lay pots fb nua
             *
             * BackgroundJob.Enqueue<IFacebookJob>(m => m.ExtendAccessToken());
             * if (!accountProviderExist)
             * {
             *  BackgroundJob.Enqueue<IFacebookJob>(m => m.UpdateFbPost(auth.Id, auth.Username, 1));
             * }
             */


            //update info facebook
            BackgroundJob.Enqueue <IFacebookJob>(m => m.UpdateFbInfo(auth.Id));
            BackgroundJob.Enqueue <IFacebookJob>(m => m.UpdateFbPost(auth.Id, "system", 1)); //update fb post

            await SignIn(auth);

            //CurrentUser.AccessToken = loginInfo.AccessToken; //gan accesstoken



            var accountProvider = await _accountService.GetAccountProviderByProvider(AccountProviderNames.Facebook, loginInfo.ProviderId, token);

            var status = await _accountService.GetAccountStatus(auth.Id);

            if (status == AccountStatus.NeedVerified || string.IsNullOrEmpty(accountProvider.FbProfileLink))//check influencer đã update profile link fb hay chưa
            {
                return(RedirectToAction("ChangeFacebookUrl", "Account"));
            }
            else
            {
                if (accountProvider.FbProfileLink.Contains("facebook.com/app_scoped_user_id"))
                {
                    return(RedirectToAction("ChangeFacebookUrl", "Account"));
                }
            }

            return(RedirectToAction("Index", "Home"));
        }
Example #29
0
 public bool StartRecentlyAdded()
 {
     BackgroundJob.Enqueue(() => _plexContentSync.CacheContent(true));
     return(true);
 }
Example #30
0
 // Using a timer to trigger the event since hangfire does not go below 1 minute intervals.
 private void LeagueTimer_Elapsed(object sender, ElapsedEventArgs e)
 {
     BackgroundJob.Enqueue <ILadderService>(ls => ls.UpdateLadders());
 }
Example #31
0
 public bool StartEmbyContentCacher()
 {
     BackgroundJob.Enqueue(() => _embyContentSync.Start());
     return(true);
 }
Example #32
0
        public string ScheduleJob(string id, double days)
        {
            var jobId = BackgroundJob.Schedule(() => Console.Write("Checking schedule"), TimeSpan.FromDays(days));

            return(jobId);
        }
Example #33
0
 public bool StartNewsletter()
 {
     BackgroundJob.Enqueue(() => _newsletterJob.Start());
     return(true);
 }
Example #34
0
 public bool ForceUpdate()
 {
     BackgroundJob.Enqueue(() => _updater.Update(null));
     return(true);
 }
Example #35
0
 public bool PlexUserImporter()
 {
     BackgroundJob.Enqueue(() => _plexUserImporter.Start());
     return(true);
 }
        public IState ChangeState(StateChangeContext context)
        {
            // To ensure that job state will be changed only from one of the
            // specified states, we need to ensure that other users/workers
            // are not able to change the state of the job during the
            // execution of this method. To guarantee this behavior, we are
            // using distributed application locks and rely on fact, that
            // any state transitions will be made only within a such lock.
            using (context.Connection.AcquireDistributedJobLock(context.BackgroundJobId, JobLockTimeout))
            {
                var jobData = GetJobData(context);

                if (jobData == null)
                {
                    // The job does not exist. This may happen, because not
                    // all storage backends support foreign keys.
                    return null;
                }

                if (context.ExpectedStates != null && !context.ExpectedStates.Contains(jobData.State, StringComparer.OrdinalIgnoreCase))
                {
                    return null;
                }
                
                var appliedState = context.NewState;

                try
                {
                    jobData.EnsureLoaded();
                }
                catch (JobLoadException ex)
                {
                    // If the job type could not be loaded, we are unable to
                    // load corresponding filters, unable to process the job
                    // and sometimes unable to change its state (the enqueued
                    // state depends on the type of a job).

                    if (!appliedState.IgnoreJobLoadException)
                    {
                        appliedState = new FailedState(ex.InnerException)
                        {
                            Reason = String.Format(
                                "Can not change the state to '{0}': target method was not found.",
                                appliedState.Name)
                        };
                    }
                }

                var backgroundJob = new BackgroundJob(context.BackgroundJobId, jobData.Job, jobData.CreatedAt);
                appliedState = ChangeState(context, backgroundJob, appliedState, jobData.State);

                return appliedState;
            }
        }
Example #37
0
 private void EmailTask(string toAddress, string username, string body)
 {
     BackgroundJob.Enqueue(() => Send(toAddress, username, body));
 }
Example #38
0
        private IState PerformJob(BackgroundProcessContext context, IStorageConnection connection, string jobId)
        {
            try
            {
                var jobData = connection.GetJobData(jobId);
                if (jobData == null)
                {
                    // Job expired just after moving to a processing state. This is an
                    // unreal scenario, but shit happens. Returning null instead of throwing
                    // an exception and rescuing from en-queueing a poisoned jobId back
                    // to a queue.
                    return null;
                }

                jobData.EnsureLoaded();

                var backgroundJob = new BackgroundJob(jobId, jobData.Job, jobData.CreatedAt);

                var jobToken = new ServerJobCancellationToken(connection, jobId, context.ServerId, _workerId, context.CancellationToken);
                var performContext = new PerformContext(connection, backgroundJob, jobToken);

                var latency = (DateTime.UtcNow - jobData.CreatedAt).TotalMilliseconds;
                var duration = Stopwatch.StartNew();

                var result = _performer.Perform(performContext);
                duration.Stop();

                return new SucceededState(result, (long) latency, duration.ElapsedMilliseconds);
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (JobPerformanceException ex)
            {
                return new FailedState(ex.InnerException)
                {
                    Reason = ex.Message
                };
            }
            catch (Exception ex)
            {
                return new FailedState(ex)
                {
                    Reason = "An exception occurred during processing of a background job."
                };
            }
        }
        public void StartSolveCurrentBoard()
        {
            if (this.Status != SolverServiceStatus.NotSolved)
            {
                return;
            }

            this.Status = SolverServiceStatus.Solving;
            this.Solutions = null;
            this.currentBackgroundJob = new BackgroundJob
            {
                InitialState = this.gameService.InitialState,
                StateToSolve = this.gameService.BoardState,
                Goal = this.gameService.Drill.Goal,
                CancellationTokenSource = new CancellationTokenSource()
            };

            Task.Factory.StartNew(() => this.BackgroundThreadMain(this.currentBackgroundJob), this.currentBackgroundJob.CancellationTokenSource.Token);
        }