色んな事を書く

シンプルさを極めたエンジニアになりたい

ServiceBusAdministrationClient について

Rule の作成

この記事を読みながら

learn.microsoft.com

CreateRuleAsync というメソッドを使えば、ある topic の subscription に適応するルールを作成できます。

このルールを適応すれば、例えば以下のようなことが出来ます。

  • ApplicationProperty の Shop の値が test となっている時、Message の ReplyTo を hoge にする
  • Message の To が fuga の時に、ApplicationProperty の Shop の値を `` にする

など、Message のプロパティを書き換える事が出来ます。

こんなコードを書きます。

var a = new ServiceBusAdministrationClient(connectionString);
await a.CreateRuleAsync("some-topic", "some-subscriptions", new CreateRuleOptions
{
    Name = "StoreIsTestRule",
    Filter = new SqlRuleFilter("Store = 'test'"),
    Action = new SqlRuleAction("SET sys.ReplyTo = 'hoge'")
});

すると Subscription に対して Rule が出来ます。

Fileter ってのがどの Message に対して Action を実行するかって条件を記述します。サンプルコードのように SQL Like に書くためのクラスが SqlRuleFilter です。

Store='test' と書いてて Store とは何ぞ?となるかもしれませんが、これは ApplicationProperty 内の値を示しています。Shop とか書くと、ApplicationProperty 内の Shop に対して条件をかけます。ネストされたプロパティに対しては、Shop.Name='Tokyo' のように書くことが出来ます (配列は試してない)。

ApplicationProperty だけでなく、システムプロパティにも条件は書けます。システムプロパティとは

  • Subject
  • State
  • ReplyTo

などなどですね。詳しくはこちらの記事を参考にしてください。

これらに対して SQL を書くときは、sys を先頭に付けます。なので sys.To='fuga' のようにする必要があります。

同じく Filter を書くためのクラスには CorrelationRuleFilter というのもあります。こんな感じで書けますね。

var a = new ServiceBusAdministrationClient(connectionString);
var fileter = new CorrelationRuleFilter();
fileter.ApplicationProperties.Add("Store", "Tokyo");
await a.CreateRuleAsync("etl-location-changed", "pub-make-location-content-sources", new CreateRuleOptions
{
    Name = "StoreIsTestRule1",
    Filter = fileter,
    Action = new SqlRuleAction("SET Shop = 'hoge'")
});

こちらの方が書き心地が良いかもしれません。

では実際に message を投げて Rule が適応されているのか見てみます。

await using var client = new ServiceBusClient(connectionString);
await using var sender = client.CreateSender("some-topic");

var message = new ServiceBusMessage();
message.ApplicationProperties.Add("Store", "test");

await sender.SendMessageAsync(message);

await using var receiver = client.CreateReceiver("some-subscriptions");
var messages = await receiver.ReceiveMessagesAsync(100, TimeSpan.FromMilliseconds(5));

foreach (var m in messages)
{
    m.Dump();
    await receiver.CompleteMessageAsync(m);
}

すると受け取った message の ReplyTo にちゃんと hoge と入っていました。面白いのが、ApplicationProperty に適応された Rule が記録されていることです。Rule 名を同じ ApplicationProperty をプログラムで追加してるとどうなるだろう?

後不思議だったのが、同じ MessageId の message が複数受信できたことです。今回の場合だと Rule が適応されていない Message適応されている Message の 2 つが受信出来ました。同じ MessageId って複数存在しないと思ってたけどなんでだろう?

色々使える場面はあるのかもしれんけど、普段 ApplicationProperty に値を積めないから想像がつかんなぁ。そもそも ApplicationProperty を使いたい時とは。

書いてる途中で知ったんだけど、ServiceBusClient に CreateRuleManager ってメソッドがあって、これの戻り値でも同じように Rule の作成が出来そうだった。