コンテンツにスキップ

3. 設定ファイルでまとめて起動する

第 1 章では Process を、第 2 章では Container を、それぞれ別々に起動しました。 実際のロボットでは、カメラやモータ、それを処理する Process など、たくさんの部品を一度に動かします。 この章では、これまでの Process と Container を 1 つの設定ファイルに書いて、まとめて起動します。

第 1 章でクローンしてビルドしたサンプル集をそのまま使います。 まだの場合は、第 1 章の「サンプルを用意する」 の手順を済ませてください。

この章では、サンプル集のルートに tutorial.conf という設定ファイルを新しく作ります。

次の内容で tutorial.conf を作ってください。

tutorial.conf
name: tutorial
option:
http_broker:
start: true
port: 8000
plugins:
process_factories:
increment_process:
path: "./target/debug"
container_factories:
example_container:
path: "./target/debug"
processes:
example_container_increment:
path: "./target/debug"
example_container_get:
path: "./target/debug"
processes:
- type_name: increment_process
name: inc0
- type_name: increment_process
name: inc1
containers:
- type_name: example_container
name: counter0
processes:
- type_name: example_container_increment
name: increment0
- type_name: example_container_get
name: get0

設定ファイルは YAML で書きます。上から順に見ていきましょう。

name: tutorial
option:
http_broker:
start: true
port: 8000

name はこのシステムの名前です。 option の http_broker は、これまで -d で立ち上げていた HTTP ブローカーの設定です。port で待ち受けるポートを変えられます。

plugins には、どのファイルから型を読み込むかを書きます。第 1 章の --process、第 2 章の --container / --container_process に当たる部分です。

  • process_factories には Process の型を書きます。
  • container_factories には Container の型を書き、その下の processes に、その Container に結びつく ContainerProcess の型を書きます。

キーには型名を書きます。juiz は path に書いたディレクトリから、型名に合ったファイルを探します。

型名 increment_process なら、./target/debug の中の libincrement_process.so(macOS では .dylib)が読み込まれます。 language を省略すると rust として扱われます。

plugins に書くだけでは、まだ何も動きません。juiz が型(作り方)を覚えるだけです。

processes と containers には、読み込んだ型からインスタンスを作ることを書きます。第 1 章・第 2 章の -1 に当たる部分です。

  • type_name には plugins に書いた型名を、name には作るインスタンスの名前を書きます。
  • processes では、同じ型 increment_process から inc0 と inc1 の 2 つのインスタンスを作っています。
  • containers では、Container counter0 を作り、その下の processes で、counter0 に結びつく ContainerProcess increment0 と get0 を作っています。

-1 で作ったときは「型名 + 0」という名前に決まっていましたが、設定ファイルでは好きな名前を付けられます。

設定ファイルを -f で渡して起動します。どの言語でも同じコマンドです。

ターミナルウィンドウ
juiz -f tutorial.conf -d

Python の場合は、第 1 章で作った venv を有効にしたターミナルで実行してください。

juiz を起動したまま別のターミナルを開き、Process の一覧を見てみます。

ターミナルウィンドウ
juiz process list
# => ["http://127.0.0.1:8000/process/inc0::increment_process", "http://127.0.0.1:8000/process/inc1::increment_process"]
juiz container-process list
# => ["core://core/container_process/increment0::example_container_increment:counter0", "core://core/container_process/get0::example_container_get:counter0"]

表示される順番は実行ごとに変わることがあります。 同じ型 increment_process のインスタンスが inc0 と inc1 の 2 つ、ID の「インスタンス名」の部分だけが違う形で並んでいます。 それぞれを呼び出してみましょう。

ターミナルウィンドウ
juiz process call "http://127.0.0.1:8000/process/inc0::increment_process" '{"arg1": 3}' -p
# => CapsulePtr((value:Value(4), option: []))
juiz process call "http://127.0.0.1:8000/process/inc1::increment_process" '{"arg1": 10}' -p
# => CapsulePtr((value:Value(11), option: []))
juiz container-process call "http://127.0.0.1:8000/container_process/increment0::example_container_increment:counter0" '{"arg1": 5}' -p
# => CapsulePtr((value:Value(5), option: []))
juiz container-process call "http://127.0.0.1:8000/container_process/get0::example_container_get:counter0" '{}' -p
# => CapsulePtr((value:Value(5), option: []))

第 1 章の Process と第 2 章の Container が、1 つの juiz の中で一緒に動いています。 inc0 と inc1 は同じ型から作られた別々のインスタンスですが、Process は状態を持たないので、どちらを呼んでも同じ引数なら同じ結果になります。

containers の項目には、type_name と name のほかに、Container を作る関数に渡す値も書けます。 カウンタを 3 から始めるように、counter0 の項目に 1 行足してみましょう。

containers:
- type_name: example_container
name: counter0
initial_value: 3
processes:

example_container 関数の引数 initial_value に 3 が渡されます。

juiz を Ctrl+C で止めて起動し直し、get を呼び出すと 3 が返ってきます。

ターミナルウィンドウ
juiz container-process call "http://127.0.0.1:8000/container_process/get0::example_container_get:counter0" '{}' -p
# => CapsulePtr((value:Value(3), option: []))

コードを書き換えずに、設定ファイルだけで振る舞いの出発点を変えられました。

Process の引数に初期値を渡す: p_apply

Section titled “Process の引数に初期値を渡す: p_apply”

Container だけでなく、Process の引数にも設定ファイルで値を与えられます。 processes の項目と、containers の中の processes の項目に p_apply を書き、引数の名前と値を並べます。

inc0 の arg1 を 10 に、increment0 の arg1 を 5 にしてみましょう。

processes:
- type_name: increment_process
name: inc0
p_apply:
arg1: 10
- type_name: increment_process
name: inc1
containers:
- type_name: example_container
name: counter0
initial_value: 3
processes:
- type_name: example_container_increment
name: increment0
p_apply:
arg1: 5
- type_name: example_container_get
name: get0

p_apply の値は、インスタンスを作った直後にその引数へ入り、初期値になります。 この値が使われるのは、引数を渡さずに Process を**実行(execute)**したときです。次の章で使う Execution Context は、この方法で Process を動かします。 これまで使ってきた call は、呼び出すたびに引数を全部渡すので、p_apply の値は使われません。

juiz を起動し直し、HTTP API の execute で引数を渡さずに実行してみましょう。

ターミナルウィンドウ
curl -X PATCH "http://127.0.0.1:8000/api/process/execute?identifier=core://core/process/inc0::increment_process" \
-H "Content-Type: application/json" -d '{}'
# => 11
curl -X PATCH "http://127.0.0.1:8000/api/container_process/execute?identifier=core://core/container_process/increment0::example_container_increment:counter0" \
-H "Content-Type: application/json" -d '{}'
# => 8

inc0 は arg1 の 10 に 1 を足して 11 を返します。p_apply を書いていない inc1 を同じように実行すると、引数の既定値 0 が使われて 1 が返ります。 increment0 は、初期値 3 のカウンタに 5 を足して 8 を返します。

p_apply に Process が持っていない引数の名前を書くと、juiz は起動時にエラーで止まります。 たとえば arg1 を arg10 と書き間違えると、次のようなエラーになります。

Error:setup_objects() failed in setup in system.rs
Caused by:
0: setup_processes(...) in setup_objects() in setup_objects.rs
1: p_apply(arg_name='arg10', value=10)
2: Can not find Process::Inlet(arg10)

書き間違いに、動かしてから気づくのではなく、起動したときに気づけます。

  • processes と containers を消して plugins だけ残した設定ファイルで起動し、juiz process list を見てみましょう。空のリスト [] が返ります。読み込んだだけでは、インスタンスは作られないことがわかります。
  • containers にもう 1 つ Container(たとえば counter1)と、それに結びつく increment / get を書き足してみましょう。counter0 と counter1 は別々の値を持ちます。ContainerProcess の ID には Container の名前が入るので、increment0 のような名前は Container ごとに同じでもかまいません。
  • サンプル集の decrement_process を plugins と processes に書き足して、1 を引く Process も一緒に動かしてみましょう。
  • 設定ファイルには、型を読み込む plugins と、そこからインスタンスを作る processes / containers を分けて書きます。
  • 1 つの型から、名前の違うインスタンスをいくつも作れます。インスタンスの名前は ID の一部になります。
  • Container の初期値のような、インスタンスごとの設定も設定ファイルで渡せます。
  • p_apply で Process の引数に初期値を与えられます。この値は、引数を渡さずに実行したとき(Execution Context から動かしたときなど)に使われます。
  • 設定ファイルの項目は、ガイドの「設定ファイル」 にまとめてあります。

次の章では、設定ファイルに Process どうしのつながりと、Process を動かすタイミングを書き足します。Process をつなぐ: connect と Execution Context に進みましょう。