我当前的进程以以下方式运行:
1.) 用户在前端应用程序中输入 URL 进行分析
2.) 前端验证 URL 并在包含 URL 属性的表中创建 URL 记录
3.) 前端在表中创建/更新一行,跟踪 URL 所处的处理阶段(每个 URL 都有自己的内部 ID)
3.A) 状态码更新为“排队”状态
---- 表格定义:
ID INT PRIMARY KEY,
StatusCode INT,
StatusDescription VARCHAR(MAX),
IsInitial BIT,
LastUpdated DATETIME
4.) 前端向包含提交 URL 的内部 ID 的 Azure 存储队列发送消息
第一条消息发送到队列后------------>
4.A) 在 UI 中创建一个对象供用户单击(以“刷新”数据)
4.B)用户在创建的对象上单击(这很可能会发生)一旦创建(如果验证则立即)
4.C) 另一条消息被发送到包含 URL ID 的队列
<--------------------------------
5.) 一个正在运行的 azure webjob(后台任务)不断拾取这些消息并开始处理
6.) 网络作业确定此 URL 是否已准备好进行处理
.....它准备好开始处理如果
- 它是新的(LastUpdated 字段为空)
- 附加到项目的状态代码表示错误
- 距离上次更新已 15 分钟
.....如果它退出
- 消息中的 ID 无效
- 附加的状态代码表示它目前正在处理中
- 距离 LastUpdated 不到 15 分钟
一旦确定被认为可以继续...
- 如果是新的,webjob 会将 LastUpdated 更新为 Datetime.Now
- 在流程的每个步骤开始时,状态代码都会更新以反映这一点
在该过程的最后,LastUpdated 被更新为当前时间
一个 try catch 围绕着这个过程
a.) 如果过程出错,则更新状态代码以反映
b.) 一条新消息被推入队列进行重试
确定 URL 是否可以解析的函数:
private bool IsReadyToParse(int [ID])
{
using (var db = EntityFactory.GetInstance())
{
var item = db.ProcessStatus.FirstOrDefault(x => x.ID == [ID]);
if (item == null || item.StatusCode > 1)
{
return false;
}
if (item.StatusCode == (int)ProcessStatusEnum.Error || item.LastUpdated == null)
{
item.LastUpdated = DateTime.Now;
db.Entry(item).State = EntityState.Modified;
db.SaveChanges();
return true;
}
return ((DateTime)item.LastUpdated).AddMinutes(15) < DateTime.Now;
}
}
队列消息通过这个函数进入:
// This function will get triggered/executed when a new message is written
// on an Azure Queue
public static void ProcessQueueMessage([QueueTrigger("[queue]")] QueueItem item, TextWriter log)
{
Console.WriteLine("Item found! Starting services [Id: {0}]", item.ID);
Agent agent = new Agent([ID], log);
agent.StartProcessing();
log.WriteLine([Item]);
}
...现在的问题是,这个连续运行的 webjob 一次可以接收多条消息(我想将其扩展到更多的 webjobs 从同一个队列中读取)
如何确定 IsReadyToParse() 函数实际上反映了当前的处理状态?
如果数据库即将将状态代码更新为“正在处理”,但另一个线程刚刚读取了状态代码并给出了 OK 以继续该过程怎么办?