Digdagのrequireオペレーターの挙動

Digdagには他のワークフローとの依存関係を表すためのオペレーターである、requireオペレーターがあります。
このオペレーターはcallオペレーターと似ているものですが、挙動がやや複雑なのでまとめてみました。

なお、この記事はDigdagのsession_timeの概念がわかっていることを前提としています。
session_timeについては以下のドキュメントに書かれていますので、参考にしてください。
https://docs.digdag.io/concepts.html#scheduled-execution-and-session-time

requireオペレーターは引数に指定したワークフローの実行状況によって、以下の3つのどれかの動作を行います。
未実行の場合は1、実行中の場合は2、実行完了の場合は3の動作を行います。

1. 引数で指定したワークフローをサブワークフローとして実行する(callオペレーターと同じ動作)
2. 引数で指定したワークフローの実行完了を待つ
3. 何もしない

**※この時の注意点はrequireオペレーターによって示される依存関係は基本的には同一のsession_timeのもの同士に限られるということです。**
そのため、session_timeの概念の理解があやふやなままrequireオペレーターを使用するのは事故の元だと思います。


以下の2つのワークフローを用いて具体的に説明していきます。

```yaml:workflow1
+step1:
  echo>: before require

+step2:
  require>: workflow2

+step3:
  echo>: after require
```

```yaml:workflow2
+step1:
  echo>: in workflow2

+step2:
  echo>: before sleep

+step3:
  sh>: sleep 10

+step4:
  echo>: after sleep
```

# 引数で指定したワークフローをサブワークフローとして実行する場合
引数で指定されたワークフローが未実行の場合は、引数で指定したワークフローをサブワークフローとして実行します。

```bash
$ rm -rf .digdag # 念のためにワークフローの実行履歴削除
$ digdag run --session '2019-01-01 00:00:00' workflow1.dig
2019-03-01 11:36:29 +0900: Digdag v0.9.33
2019-03-01 11:36:30 +0900 [INFO] (main): Using session /Users/takehiro.shiozaki/work/digdag_require_test/.digdag/status/20190101T000000+0000.
2019-03-01 11:36:30 +0900 [INFO] (main): Starting a new session project id=1 workflow name=workflow1 session_time=2019-01-01T00:00:00+00:00
2019-03-01 11:36:31 +0900 [INFO] (0017@[0:default]+workflow1+step1): echo>: before require
before require
2019-03-01 11:36:31 +0900 [INFO] (0017@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:36:31 +0900 [INFO] (0017@[0:default]+workflow1+step2): Starting a new session project id=1 workflow name=workflow2 session_time=2019-01-01T00:00:00+00:00
2019-03-01 11:36:32 +0900 [INFO] (0017@[0:default]+workflow2+step1): echo>: in workflow2
in workflow2
2019-03-01 11:36:32 +0900 [INFO] (0017@[0:default]+workflow2+step2): echo>: before sleep
before sleep
2019-03-01 11:36:32 +0900 [INFO] (0017@[0:default]+workflow2+step3): sh>: sleep 10
2019-03-01 11:36:33 +0900 [INFO] (0019@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:36:34 +0900 [INFO] (0019@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:36:36 +0900 [INFO] (0019@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:36:38 +0900 [INFO] (0019@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:36:40 +0900 [INFO] (0019@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:36:41 +0900 [INFO] (0019@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:36:42 +0900 [INFO] (0017@[0:default]+workflow2+step4): echo>: after sleep
after sleep
2019-03-01 11:36:42 +0900 [INFO] (0017@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:36:43 +0900 [INFO] (0017@[0:default]+workflow1+step3): echo>: after require
after require
Success. Task state is saved at /Users/takehiro.shiozaki/work/digdag_require_test/.digdag/status/20190101T000000+0000 directory.
  * Use --session <daily | hourly | "yyyy-MM-dd[ HH:mm:ss]"> to not reuse the last session time.
  * Use --rerun, --start +NAME, or --goal +NAME argument to rerun skipped tasks.
```

# 引数で指定されたワークフローの実行完了を待つ場合
引数で指定されたワークフローが実行中の場合は、そのワークフローの実行完了を待ちます。

下のコマンドを実行して、sleepしている最中にその下のコマンドを実行。

```bash
$ digdag run --session '2019-01-01 00:00:00' workflow2.dig
2019-03-01 11:49:15 +0900: Digdag v0.9.33
2019-03-01 11:49:16 +0900 [INFO] (main): Using session /Users/takehiro.shiozaki/work/digdag_require_test/.digdag/status/20190101T000000+0000.
2019-03-01 11:49:16 +0900 [INFO] (main): Starting a new session project id=1 workflow name=workflow2 session_time=2019-01-01T00:00:00+00:00
2019-03-01 11:49:17 +0900 [INFO] (0017@[0:default]+workflow2+step1): echo>: in workflow2
in workflow2
2019-03-01 11:49:17 +0900 [INFO] (0017@[0:default]+workflow2+step2): echo>: before sleep
before sleep
2019-03-01 11:49:17 +0900 [INFO] (0017@[0:default]+workflow2+step3): sh>: sleep 10
2019-03-01 11:49:27 +0900 [INFO] (0017@[0:default]+workflow2+step4): echo>: after sleep
after sleep
Success. Task state is saved at /Users/takehiro.shiozaki/work/digdag_require_test/.digdag/status/20190101T000000+0000 directory.
  * Use --session <daily | hourly | "yyyy-MM-dd[ HH:mm:ss]"> to not reuse the last session time.
  * Use --rerun, --start +NAME, or --goal +NAME argument to rerun skipped tasks.
```

```bash
digdag run --session '2019-01-01 00:00:00' workflow1.dig
2019-03-01 11:49:19 +0900: Digdag v0.9.33
2019-03-01 11:49:20 +0900 [INFO] (main): Using session /Users/takehiro.shiozaki/work/digdag_require_test/.digdag/status/20190101T000000+0000.
2019-03-01 11:49:20 +0900 [INFO] (main): Starting a new session project id=1 workflow name=workflow1 session_time=2019-01-01T00:00:00+00:00
2019-03-01 11:49:21 +0900 [INFO] (0017@[0:default]+workflow1+step1): echo>: before require
before require
2019-03-01 11:49:21 +0900 [INFO] (0017@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:49:21 +0900 [INFO] (0017@[0:default]+workflow1+step2): Starting a new session project id=1 workflow name=workflow2 session_time=2019-01-01T00:00:00+00:00
2019-03-01 11:49:21 +0900 [WARN] (0017@[0:default]+workflow2+step1): Skipped
2019-03-01 11:49:21 +0900 [WARN] (0017@[0:default]+workflow2+step2): Skipped
2019-03-01 11:49:23 +0900 [INFO] (0017@[0:default]+workflow2+step3): sh>: sleep 10
2019-03-01 11:49:23 +0900 [INFO] (0019@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:49:25 +0900 [INFO] (0019@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:49:27 +0900 [INFO] (0019@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:49:28 +0900 [INFO] (0019@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:49:30 +0900 [INFO] (0019@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:49:32 +0900 [INFO] (0019@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:49:33 +0900 [WARN] (0017@[0:default]+workflow2+step4): Skipped
2019-03-01 11:49:33 +0900 [INFO] (0017@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:49:33 +0900 [INFO] (0017@[0:default]+workflow1+step3): echo>: after require
after require
Success. Task state is saved at /Users/takehiro.shiozaki/work/digdag_require_test/.digdag/status/20190101T000000+0000 directory.
  * Use --session <daily | hourly | "yyyy-MM-dd[ HH:mm:ss]"> to not reuse the last session time.
  * Use --rerun, --start +NAME, or --goal +NAME argument to rerun skipped tasks.
```

# 何もしない場合
引数で指定されたワークフローが実行完了していた場合は、requireオペレーターは何もせずに処理を終えます。
なお、この挙動は広義には引数で指定したワークフローの実行完了を待つ場合と同じとみなすこともできます。

以下のコマンドを実行して、実行が完了した後に、その下のコマンドを実行。

```bash
digdag run --session '2019-01-01 00:00:00' workflow2.dig
2019-03-01 11:49:15 +0900: Digdag v0.9.33
2019-03-01 11:49:16 +0900 [INFO] (main): Using session /Users/takehiro.shiozaki/work/digdag_require_test/.digdag/status/20190101T000000+0000.
2019-03-01 11:49:16 +0900 [INFO] (main): Starting a new session project id=1 workflow name=workflow2 session_time=2019-01-01T00:00:00+00:00
2019-03-01 11:49:17 +0900 [INFO] (0017@[0:default]+workflow2+step1): echo>: in workflow2
in workflow2
2019-03-01 11:49:17 +0900 [INFO] (0017@[0:default]+workflow2+step2): echo>: before sleep
before sleep
2019-03-01 11:49:17 +0900 [INFO] (0017@[0:default]+workflow2+step3): sh>: sleep 10
2019-03-01 11:49:27 +0900 [INFO] (0017@[0:default]+workflow2+step4): echo>: after sleep
after sleep
Success. Task state is saved at /Users/takehiro.shiozaki/work/digdag_require_test/.digdag/status/20190101T000000+0000 directory.
  * Use --session <daily | hourly | "yyyy-MM-dd[ HH:mm:ss]"> to not reuse the last session time.
  * Use --rerun, --start +NAME, or --goal +NAME argument to rerun skipped tasks.
```

```bash
$ digdag run --session '2019-01-01 00:00:00' workflow1.dig
2019-03-01 11:56:57 +0900: Digdag v0.9.33
2019-03-01 11:56:58 +0900 [INFO] (main): Using session /Users/takehiro.shiozaki/work/digdag_require_test/.digdag/status/20190101T000000+0000.
2019-03-01 11:56:58 +0900 [INFO] (main): Starting a new session project id=1 workflow name=workflow1 session_time=2019-01-01T00:00:00+00:00
2019-03-01 11:56:59 +0900 [INFO] (0017@[0:default]+workflow1+step1): echo>: before require
before require
2019-03-01 11:56:59 +0900 [INFO] (0017@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:56:59 +0900 [INFO] (0017@[0:default]+workflow1+step2): Starting a new session project id=1 workflow name=workflow2 session_time=2019-01-01T00:00:00+00:00
2019-03-01 11:57:00 +0900 [WARN] (0017@[0:default]+workflow2+step1): Skipped
2019-03-01 11:57:00 +0900 [WARN] (0017@[0:default]+workflow2+step2): Skipped
2019-03-01 11:57:00 +0900 [WARN] (0018@[0:default]+workflow2+step3): Skipped
2019-03-01 11:57:00 +0900 [WARN] (0018@[0:default]+workflow2+step4): Skipped
2019-03-01 11:57:01 +0900 [INFO] (0017@[0:default]+workflow1+step2): require>: workflow2
2019-03-01 11:57:01 +0900 [INFO] (0017@[0:default]+workflow1+step3): echo>: after require
after require
Success. Task state is saved at /Users/takehiro.shiozaki/work/digdag_require_test/.digdag/status/20190101T000000+0000 directory.
  * Use --session <daily | hourly | "yyyy-MM-dd[ HH:mm:ss]"> to not reuse the last session time.
  * Use --rerun, --start +NAME, or --goal +NAME argument to rerun skipped tasks.
```

# 参考
https://docs.digdag.io/operators/require.html