C#

バッファのない PropagatorBlock はつくれないという話

また TPL Dataflow の話です。突然ですが、バッファのない PropagatorBlock って欲しくないですか?

例えば、複数の SourceBlock があって、それをひとつの SourceBlock として返したいとき。

ISourceBlock<T> CreateSource()
{
    IEnumerable<ISourceBlock<T>> sources = /* ... */;

    var resultBlock = new BufferBlock<T>(new DataflowBlockOptions() { BoundedCapacity = 1 });
    foreach (var s in sources) s.LinkTo(resultBlock);

    return resultBlock;
}

どうでしょう? resultBlock は、1件はバッファに持ってしまうので、後段のブロックがどうであれ、ソースからは必ず1件多く取り出されてしまいます。

1件くらいいいじゃない? それは sources 次第でしょう。

というわけで、本題のバッファのない PropagatorBlock が欲しい、ということです。もし resultBlock にバッファがなければ、 CreateSource の戻り値を利用する(リンクする)とき、初めて sources からデータが取り出されます。やりたいですね。

続きを読む

Visual Studio と VSCode どちらでも使える Docker Compose 環境

開発環境を Docker でいい感じにしてくれるやつとして、 Visual Studio では「コンテナー開発ツール」が、 Visual Studio Code には Remote 拡張があります。これらは Dockerfile や docker-compose.yml を用意すると、その中でアプリを動かすことができるやつです。しかし、同じものではないので、挙動はまったく異なります。それぞれメリット、デメリットがあるので、両方使えるとうれしいわけです。そこで、うまいこと両方で使える docker-compose.yml を書いてみようという試みをやっていきます。

続きを読む

ProjectReference にバージョン範囲を指定したい

複数のプロジェクトをひとつのリポジトリで管理するとき、プロジェクト間の参照関係は csproj に <ProjectReference> を書くわけですが、ここで、このプロジェクトを NuGet パッケージ化するときのことを考えます。例えば、 A と B というプロジェクトがあり、 B が A に依存しているとします。このとき B を dotnet pack してできあがるパッケージの A への依存はどのようになるでしょうか? 実際にやってみると、現在の A のバージョン以上という依存関係になります。

ここで、 A の現在のバージョンを 1.0.0 とします。 Semantic Versioning に従っていると考えると、もし 2.0.0 がリリースされたら、破壊的な変更が入っているかもしれません。それでも B から A への依存は 1.0.0 以上で良いのでしょうか? と考えると、「以上」以外の柔軟な依存関係を指定したくなりませんか? というわけで、 <ProjectReference> を使ったプロジェクト間参照で、柔軟なバージョン範囲指定をしたいというのが今回のお話です。

続きを読む

プロトコルから比較する Reactive Streams と TPL Dataflow

以前、いまさら使う TPL Dataflowで紹介した TPL Dataflow は、入力されたデータを並列に処理するプログラムを、ブロックの組み合わせで簡単に記述できるライブラリです。 類似品との比較で述べたように、 TPL Dataflow は、プッシュ型とプル型の両方の性質を持っており、送信者(Producer)が、受信者(Consumer)が処理しきれないほど大量のデータをプッシュしようとするとき、受信者がそのデータの受信を遅延させることで、データフロー内を流れるデータ量を制御します。

一方で、このような、大量のデータや時系列データ(イベント列)を入力し、データフロー内を流れるデータ量を制御しながら、並列にデータを加工する仕組みは、一般的に、特に Java のコミュニティでは Reactive Streams と呼ばれています。 Reactive Streams に用いられるインターフェイスは Java 9 で java.util.concurrent.Flow として標準ライブラリ入りしており、 RxJava や Akka Streams がこのインターフェイスの実装を提供しています(実際には、互換性のため reactive-streams パッケージを通じて実装しています)。

C# においても Reactive Streams は他人事ではなく、 java.util.concurrent.Flow と同様のインターフェイスが Reactive.Streams パッケージとして NuGet で配布されており、標準的なインターフェイスの座を狙っています。また Akka.NET Streams がこのインターフェイスの実装を提供しています。

いずれの方法も、 Reactive Extensions (Rx) 的なプッシュ型に対して、流量制限(back pressure)を導入することで、データ量を制御しています。この記事では、 Reactive Streams と TPL Dataflow をプロトコル(インターフェイスとその実装方法)から比較します。

続きを読む