現在のプロセスは次のように実行されています。
1.) ユーザーが分析のためにフロントエンド アプリに URL を入力します。
2.) フロントエンドは URL を検証し、URL の属性を含むテーブルに URL のレコードを作成します。
3.) フロント エンドは、URL が処理のどの段階にあるかを追跡するテーブルの行を作成/更新します (各 URL には独自の内部 ID があります)。
3.A) ステータス コードが「queued」ステータスに更新される
---- テーブル定義:
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 Web ジョブ (バックグラウンド タスク) がこれらのメッセージを継続的に取得し、処理を開始します。
6.) Web ジョブは、この URL を処理する準備ができているかどうかを判断します
..... 次の場合、処理を開始する準備ができています
- 新規です (LastUpdated フィールドが null です)
- アイテムに付けられたステータス コードはエラーを表します
- LastUpdated から 15 分が経過しました
..... 次の場合に終了します
- メッセージ内の ID が無効です
- 添付されたステータス コードは、現在処理中であることを示しています。
- LastUpdated から 15 分未満が経過しています
続行しても問題ないと判断されたら...
- 新しい場合、Web ジョブは LastUpdated を Datetime.Now に更新します。
- プロセスの各ステップの開始時に、これを反映するためにステータス コードが更新されます。
プロセスの最後に、LastUpdated が現在の時刻に更新されます。
トライキャッチがプロセスを囲んでいます
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() が実際に現在の処理状態を反映していることを確認するにはどうすればよいですか?
データベースがステータス コードを「処理中」に更新しようとしているときに、別のスレッドがステータス コードを読み取って、プロセスを続行することを許可した場合はどうなるでしょうか。