Skip to content

Instantly share code, notes, and snippets.

@noriyukitakei
Last active April 16, 2019 09:27
Show Gist options
  • Save noriyukitakei/07a9c7ae274e8c319947056296d7bbd5 to your computer and use it in GitHub Desktop.
Save noriyukitakei/07a9c7ae274e8c319947056296d7bbd5 to your computer and use it in GitHub Desktop.
多分わかりやすいDurable Functios【Durable Functionsを使わない場合(C#で書いたアプリ)】
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