Skip to content

Commit

Permalink
Saeve pending tasks in database.
Browse files Browse the repository at this point in the history
  • Loading branch information
SeriaWei committed Mar 11, 2023
1 parent a536c4f commit 4d2a66a
Show file tree
Hide file tree
Showing 24 changed files with 316 additions and 45 deletions.
2 changes: 0 additions & 2 deletions src/EasyFrameWork/Notification/EmailContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@ public EmailContext(EmailMessage emailMessage, SmtpSetting smtpSetting)
{
EmailMessage = emailMessage;
SmtpSetting = smtpSetting;
RetryCount = 0;
}
public EmailMessage EmailMessage { get; set; }
public SmtpSetting SmtpSetting { get; set; }
public int RetryCount { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public ServiceResult Execute(Dictionary<string, string> args, object model, Even
}
private void PushRequestInQueue(HttpRequestContent httpRequest)
{
_pendingTaskService.Add(HttpRequesetTaskHandler.Name, httpRequest);
_pendingTaskService.Add(httpRequest.Url, HttpRequesetTaskHandler.Name, httpRequest);
}
}
}
46 changes: 46 additions & 0 deletions src/ZKEACMS.EventAction/Controllers/PendingTaskController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* http://www.zkea.net/
* Copyright (c) ZKEASOFT. All rights reserved.
* http://www.zkea.net/licenses */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Easy.Mvc.Controllers;
using ZKEACMS.EventAction.Service;
using Easy.Mvc.Authorize;
using ZKEACMS.EventAction.Models;
using Easy.Constant;

namespace ZKEACMS.EventAction.Controllers
{
[DefaultAuthorize(Policy = PermissionKeys.ViewEventAction)]
public class PendingTaskController : BasicController<Models.PendingTaskEntity, int, IPendingTaskManagerService>
{
public PendingTaskController(IPendingTaskManagerService service) : base(service)
{
}

[HttpPost, DefaultAuthorize(Policy = PermissionKeys.ManageEventAction)]
public override IActionResult Edit(Models.PendingTaskEntity entity)
{
entity.RetryCount = 0;
entity.Status = (int)RecordStatus.Active;
entity.LogMessage = null;
return base.Edit(entity);
}

[HttpPost, DefaultAuthorize(Policy = PermissionKeys.ManageEventAction)]
public override IActionResult Create(Models.PendingTaskEntity entity)
{
return base.Create(entity);
}

[HttpPost, DefaultAuthorize(Policy = PermissionKeys.ManageEventAction)]
public override IActionResult Delete(int id)
{
return base.Delete(id);
}
}
}
1 change: 1 addition & 0 deletions src/ZKEACMS.EventAction/EntityFrameWorkModelCreating.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Models.EventAction>();
modelBuilder.Entity<Models.ActionBody>();
modelBuilder.Entity<Models.PendingTaskEntity>();
}
}
}
19 changes: 16 additions & 3 deletions src/ZKEACMS.EventAction/EventActionPlug.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,23 @@ public override IEnumerable<AdminMenu> AdminMenu()
Icon = "glyphicon-console",
Url = "~/admin/eventaction",
Order = 0,
PermissionKey=PermissionKeys.ViewEventAction
PermissionKey = PermissionKeys.ViewEventAction
},
new AdminMenu
{
Title = "Action Body",
Icon = "glyphicon-log-in",
Url = "~/admin/actionbody",
Order = 1,
PermissionKey=PermissionKeys.ViewActionBody
PermissionKey = PermissionKeys.ViewActionBody
},
new AdminMenu
{
Title = "Pending Task",
Icon = "glyphicon-tasks",
Url = "~/admin/pendingtask",
Order = 2,
PermissionKey = PermissionKeys.ViewPendingTask
}
}
};
Expand All @@ -71,6 +79,8 @@ public override IEnumerable<PermissionDescriptor> RegistPermission()
yield return new PermissionDescriptor(PermissionKeys.ManageEventAction, "EventAction", "Manage EventAction", "");
yield return new PermissionDescriptor(PermissionKeys.ViewActionBody, "EventAction", "View Action Body", "");
yield return new PermissionDescriptor(PermissionKeys.ManageActionBody, "EventAction", "Manage Action Body", "");
yield return new PermissionDescriptor(PermissionKeys.ViewPendingTask, "EventAction", "View Pending Task", "");
yield return new PermissionDescriptor(PermissionKeys.ManagePendingTask, "EventAction", "Manage Pending Task", "");
}

public override IEnumerable<WidgetTemplateEntity> WidgetServiceTypes()
Expand All @@ -83,9 +93,12 @@ public override void ConfigureServices(IServiceCollection serviceCollection)
serviceCollection.AddTransient<IOnModelCreating, EntityFrameWorkModelCreating>();

serviceCollection.AddTransient<IEventActionService, EventActionService>();
serviceCollection.AddSingleton<IPendingTaskService, PendingTaskService>();
serviceCollection.ConfigureMetaData<Models.EventAction, Models.EventActionMetaData>();

serviceCollection.AddTransient<IPendingTaskService, PendingTaskService>();
serviceCollection.AddTransient<IPendingTaskManagerService, PendingTaskManagerService>();
serviceCollection.ConfigureMetaData<Models.PendingTaskEntity, Models.PendingTaskEntityMetaData>();

serviceCollection.AddTransient<IActionBodyService, ActionBodyService>();
serviceCollection.ConfigureMetaData<Models.ActionBody, Models.ActionBodyMetaData>();

Expand Down
46 changes: 46 additions & 0 deletions src/ZKEACMS.EventAction/Models/PendingTaskEntity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* http://www.zkea.net/
* Copyright (c) ZKEASOFT. All rights reserved.
* http://www.zkea.net/licenses */

using Easy.MetaData;
using Easy.Models;
using Easy.RepositoryPattern;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZKEACMS.PendingTask;

namespace ZKEACMS.EventAction.Models
{
[DataTable("EA_PendingTask")]
public class PendingTaskEntity : EditorEntity, TaskEntity
{
[Key]
public int ID { get; set; }
public string Identifier { get; set; }
public string HandlerName { get; set; }
public string Data { get; set; }
public string LogMessage { get; set; }
public int RetryCount { get; set; }
}
class PendingTaskEntityMetaData : ViewMetaData<PendingTaskEntity>
{
protected override void ViewConfigure()
{
ViewConfig(m => m.ID).AsHidden();
ViewConfig(m => m.Identifier).AsTextBox().Required().ShowInGrid();
ViewConfig(m => m.HandlerName).AsTextBox().ShowInGrid().Required();
ViewConfig(m => m.Data).AsTextArea().AddProperty("rows", "10");
ViewConfig(m => m.LogMessage).AsTextArea().AddProperty("rows", "10").ReadOnly();
ViewConfig(m => m.RetryCount).AsTextBox().ReadOnly().ShowInGrid();
ViewConfig(m => m.Title).AsHidden();
ViewConfig(m => m.Description).AsHidden();

ViewConfig(m => m.CreatebyName).AsHidden();
ViewConfig(m => m.LastUpdateByName).AsHidden();
}
}
}
2 changes: 1 addition & 1 deletion src/ZKEACMS.EventAction/PendingTaskBackgroundService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
await scope.ServiceProvider.GetService<IPendingTaskManager>().ProcessAllPendingTaskAsync();
await scope.ServiceProvider.GetService<IPendingTaskExecutor>().ProcessAllPendingTaskAsync();
}
catch (Exception ex)
{
Expand Down
3 changes: 3 additions & 0 deletions src/ZKEACMS.EventAction/PermissionKeys.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,8 @@ public class PermissionKeys
public const string ManageEventAction = "EventAction_Manage";
public const string ViewActionBody = "ActionBody_View";
public const string ManageActionBody = "ActionBody_Manage";

public const string ViewPendingTask = "PendingTask_View";
public const string ManagePendingTask = "PendingTask_Manage";
}
}
18 changes: 18 additions & 0 deletions src/ZKEACMS.EventAction/Service/IPendingTaskManagerService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* http://www.zkea.net/
* Copyright (c) ZKEASOFT. All rights reserved.
* http://www.zkea.net/licenses */

using Easy.RepositoryPattern;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZKEACMS.EventAction.Models;

namespace ZKEACMS.EventAction.Service
{
public interface IPendingTaskManagerService : IService<PendingTaskEntity>
{
}
}
23 changes: 23 additions & 0 deletions src/ZKEACMS.EventAction/Service/PendingTaskManagerService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* http://www.zkea.net/
* Copyright (c) ZKEASOFT. All rights reserved.
* http://www.zkea.net/licenses */

using Easy;
using Easy.RepositoryPattern;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZKEACMS.EventAction.Models;

namespace ZKEACMS.EventAction.Service
{
public class PendingTaskManagerService : ServiceBase<PendingTaskEntity>, IPendingTaskManagerService
{
public PendingTaskManagerService(IApplicationContext applicationContext, DbContext dbContext) : base(applicationContext, dbContext)
{
}
}
}
73 changes: 61 additions & 12 deletions src/ZKEACMS.EventAction/Service/PendingTaskService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,97 @@
* Copyright (c) ZKEASOFT. All rights reserved.
* http://www.zkea.net/licenses */

using Easy.Constant;
using Easy.Serializer;
using LiteDB;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZKEACMS.EventAction.Models;
using ZKEACMS.PendingTask;
using ZKEACMS.Storage;

namespace ZKEACMS.EventAction.Service
{
public class PendingTaskService : PluginData<EventActionPlug>, IPendingTaskService
public class PendingTaskService : IPendingTaskService
{
public PendingTaskService(ILogger<EventActionPlug> logger) : base(logger)
private readonly IDBContextProvider _dbContextProvider;
private readonly Dictionary<TaskEntity, DbContext> _dbContextMapping;
private const int MaxTryTimes = 5;
public PendingTaskService(IDBContextProvider dbContextProvider)
{
_dbContextProvider = dbContextProvider;
_dbContextMapping = new Dictionary<TaskEntity, DbContext>();
}

private ILiteCollection<TaskEntity> GetTaskCollection()
public void Add(string identifier, string handlerName, object context)
{
return GetCollection<TaskEntity>("pendingtasks");
var newTask = new PendingTaskEntity
{
Identifier = identifier,
HandlerName = handlerName,
Data = JsonConverter.Serialize(context),
Status = (int)RecordStatus.Active,
CreateDate = DateTime.Now
};
_dbContextProvider.Current.Set<PendingTaskEntity>().Add(newTask);
_dbContextProvider.Current.SaveChanges();
}

public void Add(string handlerName, object context)
public IEnumerable<TaskEntity> GetPendingTasks()
{
GetTaskCollection().Insert(new TaskEntity { HandlerName = handlerName, Data = JsonConverter.Serialize(context) });
foreach (var dbContext in _dbContextProvider.GetAvailableDbContexts())
{
foreach (var item in GetTopTasks(dbContext))
{
_dbContextMapping[item] = dbContext;
yield return item;
}
}
}

public IEnumerable<TaskEntity> GetPendingTasks()
private IEnumerable<PendingTaskEntity> GetTopTasks(DbContext dbContext)
{
return dbContext.Set<PendingTaskEntity>()
.Where(m => m.Status == (int)RecordStatus.Active && m.RetryCount < MaxTryTimes)
.OrderBy(m => m.LastUpdateDate)
.Take(100)
.ToArray();
}

public void Fail(TaskEntity entity)
{
return GetTaskCollection().Find(m => m.RetryCount < 5, 0, 100).ToList();
(entity as PendingTaskEntity).LastUpdateDate = DateTime.Now;
entity.Status = (int)RecordStatus.InActive;
var dbContext = _dbContextMapping[entity];
dbContext.Set<PendingTaskEntity>().Update(entity as PendingTaskEntity);
dbContext.SaveChanges();
}

public void Remove(TaskEntity entity)
public void Complete(TaskEntity entity)
{
GetTaskCollection().Delete(entity.Id);
(entity as PendingTaskEntity).LastUpdateDate = DateTime.Now;
entity.Status = (int)RecordStatus.InActive;
entity.LogMessage = "Complete";
var dbContext = _dbContextMapping[entity];
dbContext.Set<PendingTaskEntity>().Update(entity as PendingTaskEntity);
dbContext.SaveChanges();
}

public void Update(TaskEntity entity)
public void RetryLater(TaskEntity entity)
{
GetTaskCollection().Update(entity);
(entity as PendingTaskEntity).LastUpdateDate = DateTime.Now;
if (entity.RetryCount >= MaxTryTimes)
{
entity.RetryCount = 0;
}
var dbContext = _dbContextMapping[entity];
dbContext.Set<PendingTaskEntity>().Update(entity as PendingTaskEntity);
dbContext.SaveChanges();
}
}
}
24 changes: 24 additions & 0 deletions src/ZKEACMS.EventAction/Views/PendingTask/Create.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@model ZKEACMS.EventAction.Models.PendingTaskEntity
@{
Script.Reqiured("validate").AtFoot();
Script.Reqiured("tinymce").AtFoot();
}

<div class="panel panel-default">
<div class="panel-heading">
@L("New")
</div>
<div class="panel-body">
@using (Html.BeginForm())
{
@Html.EditorForModel()
<div class="toolBar">
@if (Authorizer.Authorize(ZKEACMS.EventAction.PermissionKeys.ManageEventAction))
{
<input type="submit" class="btn btn-primary" value="@L("Save")" data-value="@ActionType.Update" />
}
<input type="button" class="btn btn-default cancel" value="@L("Cancel")" />
</div>
}
</div>
</div>
24 changes: 24 additions & 0 deletions src/ZKEACMS.EventAction/Views/PendingTask/Edit.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@model ZKEACMS.EventAction.Models.PendingTaskEntity
@{
Script.Reqiured("validate").AtFoot();
Script.Reqiured("tinymce").AtFoot();
}

<div class="panel panel-default">
<div class="panel-heading">
@L("Edit")
</div>
<div class="panel-body">
@using (Html.BeginForm())
{
@Html.EditorForModel()
<div class="toolBar">
@if (Authorizer.Authorize(ZKEACMS.EventAction.PermissionKeys.ManageEventAction))
{
<input type="submit" class="btn btn-primary" value="@L("Retry")" data-value="@ActionType.Update" />
}
<input type="button" class="btn btn-default cancel" value="@L("Cancel")" />
</div>
}
</div>
</div>
Loading

0 comments on commit 4d2a66a

Please sign in to comment.