6

レガシー アプリケーションのリファクタリングを行っています。問題のアプリケーションは、SQL Server データベース テーブルを使用して、1 つ以上の Windows サービスによって取得および処理されるジョブをキューに入れます。適切なロックを維持しながら、処理のために「待機中」ステータスでキューに入れられた次のジョブをプルするイテレータを作成したいと考えています。サンプル単体テストが以下に含まれています。私の質問は、私のアプローチに潜在的なショーストッパーがあるかどうかです。

// Database DDL

if object_id('Jobs') is not null begin
   drop table Jobs;
end
go
create table Jobs
(
    Id int identity(1,1) not null primary key clustered
,   JobStatus varchar(50) not null
);

insert Jobs
select 'Waiting'
union all
select 'Waiting'
union all
select 'Processing'
union all
select 'Completed'
union all
select 'Failed';

// Unit Test

// Data Model
public sealed class Job
{
    public readonly int JobId;

    public Job(int jobId)
    {
        JobId = jobId;
    }
}

[TestFixture]
public class JobsTest
{
    private const string connectionString = 
        "Data Source=.;Initial Catalog=<databasename>;Integrated Security=True;Connect Timeout=15;Encrypt=False;TrustServerCertificate=False";

    const string SQL =
        @"declare @jobId table(JobId int)
          update  top(1) Jobs
          set     JobStatus = 'Processing'
          output  Inserted.Id into @jobId
          where   JobStatus = 'Waiting'
          select  JobId from @jobId;";

    [Test]
    public void CanIterateJobs()
    {
        foreach (var job in Jobs)
        {
            Assert.NotNull(job, "job was null.");
            Console.WriteLine(job.JobId);
        }
    }

    public static IEnumerable<Job> Jobs
    {
        get
        {
            while (true)
            {
                Job job = null;
                do
                {
                    using (var connection = new SqlConnection(connectionString))
                    {
                        using (var command = new SqlCommand(SQL, connection))
                        {
                            connection.Open();
                            var reader = command.ExecuteReader();
                            if (reader.Read())
                            {
                                job = new Job(Convert.ToInt32(reader["JobId"]));
                                yield return job;
                            }
                        }
                    }

                } while (job == null);

                Task.Delay(1000);
            }
        }
    } 
}
4

0 に答える 0