要するに、tee(1) みたいなもの。
Point-to-Point ChannelをDocument Message用に使うことが多い。 たった一つのコンシューマーが個々のメッセージを処理することを保証できるからだ。 しかし、テストや監視、トラブルシューティングなどのためには、チャネル上を通るすべてのメッセージを調べられると便利だ。
Point-to-Point Channel上を流れるメッセージを調査するには?
デバッグするときなど、チャネル上を流れるメッセージの内容を確認できると便利。でも、Point-to-Point Channelにリスナーを追加するだけではうまくいかない。リスナーはメッセージをチャネルから取り出してしまうので、本来受信すべきチャネルにメッセージが届かなくなってしまう。
送信側もしくは受信側のチャネルに手を加えて、調査用の別チャネルにもメッセージを配送させるという手もある。でも、大量のコンポーネントに手を入れないといけないし、そもそもパッケージアプリなどの場合は、手を入れることすらできないかもしれない。
Point-to-Point ChannelじゃなくてPublish-Subscribe Channelにしてしまうという手もある。そうすれば、新しいリスナーを追加しても既存のメッセージの流れを邪魔することがない。でもそれって、チャネルのセマンティクスを変えてしまうことになる。もともと「たったひとつの受信者がメッセージを受信する」前提で作っていたものを「すべての受信者がメッセージを受信する」ことにしてしまうわけだから、望まざる結果を招く可能性もある。それに、(Pub-SubはP2Pに比べて)非効率的だし信頼性にも劣る。
たいていのメッセージングシステムにはpeekメソッド(メッセージを受信せず、ただその内容を読むだけのメソッド)が用意されている。が、当然、既に他のチャネルが受信済みのメッセージは読めない。
途中のどこかにチャネルを追加する、いわゆる「インターセプター」形式も使える。が、たとえばメッセージの配送時間を調べるなどの複数のチャネルにまたがる調査をする場合は、あちこちにインターセプターを差し込まなければいけなくなる。
チャネルにWire Tapを追加する。これはシンプルなRecipient Listで、 やってきたメッセージをメインチャネルだけではなくもうひとつ別のチャネルにも配送する。
Wire Tapは二つの出力チャネルを持つRecipient List。受信したメッセージを、二つのチャネル(本来の配送先と調査・解析用のチャネル)にそっくりそのまま配送する。元のチャネルの動きが意図せず変わることもなく、既存のシステムに対する副作用のリスクが減らせる。
Control Bus上に、プログラマブルなRecipient Listを作ると便利。第二のチャネルのオン・オフを切り替えられるようになるので、テストやデバッグのときにだけタップを有効にできる。
Wire Tapの最大の弱点は、メッセージを受けてそのまま流すという作業のぶんだけレイテンシーが増加すること。大抵のメッセージングシステムは、右から左にただメッセージを流すだけでも、いったんメッセージをデコードする。そして新たなメッセージIDを振りなおす。メッセージIDが変わってしまうという点に注意。たとえば、元のシステムでメッセージIDをCorrelation Identifierとして使っていたら、Wire Tapを差し込むことでそのシステムは破綻してしまう。だからあれほどメッセージIDをCorrelation Identifierにするなと(ry
Wire Tapは同じメッセージを二つのチャネルに送る。ただ、その二つのメッセージのメッセージIDは異なる。
既にMessage Brokerがあるなら、それをWire Tapに改造するのは簡単だ。というのも、すべてのメッセージがそこを通過するという中央コンポーネントが既に存在するわけだから。
Wire Tapの重要な制約は、チャネル間のメッセージの流れを変更できないこと。変えたいんならDetourを使うこと。
この後の第12章では、第9章で作ったローンブローカーのサンプルにWire Tapを組み込む。クレジットビューローへのリクエストをすべてログに記録するためだ。
図のように、複数のWire Tapからのメッセージを一箇所(たとえばMessage Storeなど)にまとめて、そこでいろいろ分析することができる。