Last active
April 16, 2019 09:27
-
-
Save noriyukitakei/07a9c7ae274e8c319947056296d7bbd5 to your computer and use it in GitHub Desktop.
多分わかりやすいDurable Functios【Durable Functionsを使わない場合(C#で書いたアプリ)】
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Linq; | |
using System.Net.Http; | |
using System.Runtime.Serialization; | |
using System.Runtime.Serialization.Json; | |
using System.Text; | |
using System.Threading; | |
using Microsoft.WindowsAzure.Storage; | |
using Microsoft.WindowsAzure.Storage.Queue; | |
using Microsoft.WindowsAzure.Storage.Table; | |
namespace GetFileList | |
{ | |
class Program | |
{ | |
private const string AZURE_STORAGE_CONNECTION_STRING = "UseDevelopmentStorage=true"; | |
private static HttpClient httpClient = new HttpClient(); | |
static void Main(string[] args) | |
{ | |
// Azure Queue Storageへの接続設定 | |
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(AZURE_STORAGE_CONNECTION_STRING); | |
// 対象のWebサイトのRSSからAzureというタグが付いた記事を検索する処理のメッセージを | |
// 格納するキューを作成する | |
CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient(); | |
CloudQueue queue = queueClient.GetQueueReference("task-queue"); | |
queue.CreateIfNotExists(); | |
// 対象のWebサイトのRSSからAzureというタグが付いた記事の件数を格納するテーブルを作成する。 | |
CloudTableClient tableClient = storageAccount.CreateCloudTableClient(); | |
CloudTable table = tableClient.GetTableReference("TaskHistory"); | |
table.CreateIfNotExists(); | |
// 対象のWebサイトのRSSのURLを定義する。 | |
string[] urls = new string[] { | |
"https://tech-lab.sios.jp/feed/", | |
"https://satonaoki.wordpress.com/feed/" | |
}; | |
// Azureというタグが付いた記事の件数を取得する対象のWebサイトに共通なIDを生成する。 | |
// これがAzure Table Storageに入れるPartitionKeyになる。 | |
string jobId = Guid.NewGuid().ToString(); | |
// 集計対象のURLごとに処理をする | |
foreach (string url in urls) | |
{ | |
// Auzre Queue Storageに入れるメッセージを作成する。形式は以下の通りとなる。 | |
// { | |
// "jobId":"[集計対象のURLをグルーピングした一意のIDd]", | |
// "url":"[集計対象のWebサイトのURL]" | |
// } | |
RssMessage rss = new RssMessage(); | |
rss.url = url; | |
rss.jobId = jobId; | |
DataContractJsonSerializer taskSerializer = new DataContractJsonSerializer(typeof(RssMessage)); | |
using (MemoryStream taskMs = new MemoryStream()) | |
{ | |
// 先程作成したメッセージをAuzre Queue Storageに登録する。 | |
taskSerializer.WriteObject(taskMs, rss); | |
string jsonString = Encoding.UTF8.GetString(taskMs.ToArray()); | |
CloudQueueMessage message = new CloudQueueMessage(jsonString); | |
queue.AddMessage(message); | |
// Azure Table Storageにタスクの状態を登録する。形式は以下の通りとする。 | |
// Partition Key:集計対象のWebサイトをグルーピングする任意のID | |
// RowKey: 集計対象のWebサイトのURL(実際はbase64エンコードしている) | |
// Status: processing(処理中を表すステータス) | |
string urlConvertedToBase64 = Convert.ToBase64String(Encoding.GetEncoding("UTF-8").GetBytes(rss.url)); | |
RssCountTaskEntity taskEntity = new RssCountTaskEntity(jobId, urlConvertedToBase64); | |
taskEntity.Status = "processing"; | |
TableOperation insertOperation = TableOperation.Insert(taskEntity); | |
table.Execute(insertOperation); | |
} | |
} | |
// 定期的にAzure Table Storageをチェックし、同じPartitionKeyのStatusが全てsuccessになったら、 | |
// Countの値を合計して、Azure Table Storageの値を更新する。 | |
while (true) | |
{ | |
// 同じPartitionKeyの値のStatusでprocessingになっているものが0件、つまり全て | |
// Successになっているかどうかを確認する。つまり、集計対象のURLのRSSから | |
// Azureというカテゴリの件数をカウントするというAzure Functionsが全て | |
// 終わっているかどうかを確認する。 | |
TableQuery<RssCountTaskEntity> searchProcessingQuery = new TableQuery<RssCountTaskEntity>() | |
.Where( | |
TableQuery.CombineFilters( | |
TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, jobId), | |
TableOperators.And, | |
TableQuery.GenerateFilterCondition("Status", QueryComparisons.Equal, "processing"))); | |
int rowNum = table.ExecuteQuery(searchProcessingQuery).Count(); | |
// もしprocessingが0件だったら、つまり全てsuccessだったら、 | |
// 集計対象のURLにAzureというカテゴリが含まれる記事の件数を | |
// すべて合計して、コンソールに表示する。 | |
if (rowNum == 0) { | |
TableQuery<RssCountTaskEntity> searchSuccessQuery = new TableQuery<RssCountTaskEntity>() | |
.Where( | |
TableQuery.CombineFilters( | |
TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, jobId), | |
TableOperators.And, | |
TableQuery.GenerateFilterCondition("Status", QueryComparisons.Equal, "success"))); | |
int count = 0; | |
foreach (RssCountTaskEntity entity in table.ExecuteQuery(searchSuccessQuery)) | |
{ | |
count += int.Parse(entity.Count); | |
} | |
Console.WriteLine(count); | |
Thread.Sleep(5000); | |
break; | |
} | |
Thread.Sleep(1000); | |
} | |
} | |
} | |
// Azure Storage Queueに登録するメッセージを表したオブジェクト | |
[DataContract] | |
class RssMessage | |
{ | |
[DataMember] | |
public string jobId { get; set; } | |
[DataMember] | |
public string url { get; set; } | |
} | |
// Azure Storage Tableに登録するレコードを表したオブジェクト | |
public class RssCountTaskEntity : TableEntity | |
{ | |
public RssCountTaskEntity(string jobId, string path) | |
{ | |
this.PartitionKey = jobId; | |
this.RowKey = path; | |
} | |
public RssCountTaskEntity() { } | |
public string Count { get; set; } | |
public string Status { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment