1

現在のプロセスは次のように実行されています。

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() が実際に現在の処理状態を反映していることを確認するにはどうすればよいですか?

データベースがステータス コードを「処理中」に更新しようとしているときに、別のスレッドがステータス コードを読み取って、プロセスを続行することを許可した場合はどうなるでしょうか。

4

2 に答える 2

0

これは、限られた開発者テストによる私の初歩的なソリューションです...私が進むにつれて更新されます。

...... IsReadyToParse() の代わりにこのストアド プロシージャを使用します

CREATE PROCEDURE dbo.usp_getIsReadyForProcess
@[ID] INT 
AS
BEGIN
 BEGIN TRY

  SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
  BEGIN TRANSACTION

    DECLARE @lastUpdated DATETIME
    DECLARE @statusCode INT

    -- LOCK ROW UNTIL END OF TRANSACTION
    SET @lastUpdated = (SELECT LastUpdated FROM dbo.ProcessStatus WITH (ROWLOCK, HOLDLOCK) WHERE [ID] = @[ID])
    SET @statusCode = (SELECT StatusCode FROM dbo.ProcessStatus WHERE [ID] = @[ID])

    DECLARE @isReady BIT

    --If there is no row count
    IF @@ROWCOUNT = 0
    BEGIN
        SET @isReady = 0
    END

    -- If video is already in process
    ELSE IF @statusCode > 1
    BEGIN
        SET @isReady = 0
    END

    -- If this is the first time it is getting parsed
    ELSE IF @lastUpdated IS NULL
    BEGIN
        SET @isReady = 1

        --Update datetime field
        UPDATE dbo.ProcessStatus 
        SET LastUpdated = GETDATE()
        WHERE [ID] = @[ID]
    END

    -- If is isnt the initial parse and hasnt been 15 minutes yet
    ELSE IF GETDATE() < DATEADD(MINUTE, 15, @lastUpdated)
    BEGIN
        SET @isReady = 0
    END


    -- Anything else, and its a go 
    ELSE 
    BEGIN
        SET @isReady = 1
    END



    -- If were ready to start, update the status code
    IF @isReady = 1
    BEGIN
        UPDATE dbo.ProcessStatus 
        SET StatusCode = 2 
        WHERE [ID] = @[ID]
    END

 COMMIT TRANSACTION

 SELECT @isReady

 END TRY    
 BEGIN CATCH
    -- If there was any type of error
    ROLLBACK
    SELECT 0
 END CATCH 
END
于 2015-02-22T21:21:59.443 に答える