<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Language on Rindrics Mumbles</title>
    <link>https://rindrics.com/tags/language/</link>
    <description>Language</description>    
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Mon, 27 Jul 2026 00:00:00 +0900</lastBuildDate>
    <atom:link href="https://rindrics.com/tags/language/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>システム設計にAlloyを使ってみる（前篇）</title>
      <link>https://rindrics.com/posts/introduction-to-alloy/</link>
      <pubDate>Mon, 27 Jul 2026 00:00:00 +0900</pubDate>
      
      <guid>https://rindrics.com/posts/introduction-to-alloy/</guid>
      <description>&lt;p&gt;Alloyという形式仕様記述言語の使い勝手も試したくなったので触ってみる。&lt;/p&gt;
&lt;h2 id=&#34;はじめに&#34;&gt;はじめに&lt;/h2&gt;
&lt;p&gt;RDSの監査ログをエクスポートするシステムの設計をしている。
一応アーキテクチャの概要は浮かんではいるのだが、要求を満たすか客観的に評価しないと「ぼくの考えた〜」止まりになってしまう。
少し前に&lt;a href=&#34;https://www.shoeisha.co.jp/book/detail/9784798169163&#34;&gt;『実践TLA+』&lt;/a&gt;を読んで以来、設計の評価には&lt;a href=&#34;https://lamport.azurewebsites.net/tla/tla.html&#34;&gt;TLA+&lt;/a&gt;を使っているが、&lt;a href=&#34;https://alloytools.org/alloy6.html&#34;&gt;Alloy&lt;/a&gt;という言語もちらほら耳にして気になっていた。
この機会に使い勝手を試してみる。&lt;/p&gt;
&lt;h2 id=&#34;動作環境&#34;&gt;動作環境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;macOS 15.6.1（Apple M1 Max）&lt;/li&gt;
&lt;li&gt;Alloy Analyzer 6.1.0.20211119T054551&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;givenなものを整理する&#34;&gt;givenなものを整理する&lt;/h2&gt;
&lt;h3 id=&#34;前提assumptions&#34;&gt;前提（Assumptions）&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;要求ID&lt;/th&gt;
          &lt;th&gt;概要&lt;/th&gt;
          &lt;th&gt;理由&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;A001&lt;/td&gt;
          &lt;td&gt;単一リージョンにある5つのRDSクラスタを処理対象とすること&lt;/td&gt;
          &lt;td&gt;&amp;mdash;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;A002&lt;/td&gt;
          &lt;td&gt;RDS監査ログはCloudWatch Logsへ正常に出力されているものとする&lt;/td&gt;
          &lt;td&gt;&amp;mdash;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;A003&lt;/td&gt;
          &lt;td&gt;エクスポート処理はCloudWatch Logsから実施し、RDSから直接ログを取得しないものとする&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DownloadDBLogFilePortion.html#:~:text=Note-,This,Reference%2E&#34;&gt;エクスポート処理による負荷&lt;/a&gt;）をRDSにかけたくないため&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;要求requirements&#34;&gt;要求（Requirements）&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;要求ID&lt;/th&gt;
          &lt;th&gt;概要&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;R001&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://aws.amazon.com/jp/blogs/database/automate-the-export-of-amazon-rds-for-mysql-or-amazon-aurora-mysql-audit-logs-to-amazon-s3-with-batching-or-near-real-time-processing/#:~:text=Solution%202%3A%20Create%20near%20real%2Dtime%20audit%20log%20processing%20with%20Amazon%20Data%20Firehose&#34;&gt;リアルタイム性&lt;/a&gt;よりもインフラコスト抑制を重視すること&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;R002&lt;/td&gt;
          &lt;td&gt;エクスポート単位は日次とすること&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;R003&lt;/td&gt;
          &lt;td&gt;エクスポート済ログに欠損がないこと&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;R004&lt;/td&gt;
          &lt;td&gt;エクスポート済ログに重複がないこと&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;R005&lt;/td&gt;
          &lt;td&gt;一つの処理対象に対する自動試行回数が有限であること&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;R006&lt;/td&gt;
          &lt;td&gt;自動回復できないエクスポート失敗を運用者が認識できること&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;制約constraints&#34;&gt;制約（Constraints）&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;ID&lt;/th&gt;
          &lt;th&gt;概要&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;C001&lt;/td&gt;
          &lt;td&gt;1つのAWSアカウントで同時にアクティブにできるCloudWatch Logs export taskは1つである&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;C002&lt;/td&gt;
          &lt;td&gt;export taskは非同期に実行されるが、export taskの完了イベントは発行されないため成否を確認する必要がある&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;初期システム要件&#34;&gt;初期システム要件&lt;/h2&gt;
&lt;p&gt;前述の前提・要求から、下記の方法は選択肢から除外される:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DownloadDBLogFilePortion.html&#34;&gt;RDSのDownloadDBLogFilePortion API&lt;/a&gt;を使う方法（&lt;code&gt;A003&lt;/code&gt;により）&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://aws.amazon.com/blogs/database/automate-the-export-of-amazon-rds-for-mysql-or-amazon-aurora-mysql-audit-logs-to-amazon-s3-with-batching-or-near-real-time-processing/#:~:text=Solution%202%3A%20Create%20near%20real%2Dtime%20audit%20log%20processing%20with%20Amazon%20Data%20Firehose&#34;&gt;Amazon Data Firehoseによる方法&lt;/a&gt;（&lt;code&gt;R001&lt;/code&gt;により）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;なので基本的には&lt;a href=&#34;https://aws.amazon.com/blogs/database/automate-the-export-of-amazon-rds-for-mysql-or-amazon-aurora-mysql-audit-logs-to-amazon-s3-with-batching-or-near-real-time-processing/#:~:text=Solution%20%231%3A%20Peform%20audit%20log%20batch%20processing%20with%20EventBridge%20and%20Lambda&#34;&gt;こちらのアーキテクチャ&lt;/a&gt;を基本としたものになる見通しだが、システム要件を一応まとめてみる:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;ID&lt;/th&gt;
          &lt;th&gt;概要&lt;/th&gt;
          &lt;th&gt;対応元&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;IR001&lt;/td&gt;
          &lt;td&gt;各RDSクラスタについて1日を一つの処理対象単位とする&lt;/td&gt;
          &lt;td&gt;A001, R002&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;IR002&lt;/td&gt;
          &lt;td&gt;処理対象単位はクラスタと対象日の組で一意に識別される&lt;/td&gt;
          &lt;td&gt;R002, R003, R004&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;IR003&lt;/td&gt;
          &lt;td&gt;同時にアクティブにするexport taskは最大1つとする&lt;/td&gt;
          &lt;td&gt;C001&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;IR004&lt;/td&gt;
          &lt;td&gt;失敗した処理は規定の上限回数まで再試行する&lt;/td&gt;
          &lt;td&gt;R003, R005, R006&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;IR005&lt;/td&gt;
          &lt;td&gt;試行上限に達したジョブはそれ以上自動試行されない&lt;/td&gt;
          &lt;td&gt;R005&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;IR006&lt;/td&gt;
          &lt;td&gt;試行上限に達したジョブを通知対象として記録する&lt;/td&gt;
          &lt;td&gt;R006&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;IR007&lt;/td&gt;
          &lt;td&gt;成功済みの処理対象単位を再び実行対象にしない&lt;/td&gt;
          &lt;td&gt;R004&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;IR008&lt;/td&gt;
          &lt;td&gt;ある処理対象単位について、成功したexport taskの成果物は高々1つとする&lt;/td&gt;
          &lt;td&gt;R004&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;IR009&lt;/td&gt;
          &lt;td&gt;各処理対象単位は、成功または通知対象のいずれかに到達するまで管理対象から削除しない&lt;/td&gt;
          &lt;td&gt;R003, R006&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Alloyによるモデル検査によって要件の穴が見つかるかもしれないので、システム&lt;strong&gt;初期&lt;/strong&gt;要件（Initial system requirements）としておく。&lt;/p&gt;
&lt;h2 id=&#34;システム要件をalloyコードへ&#34;&gt;システム要件をAlloyコードへ&lt;/h2&gt;
&lt;h3 id=&#34;ドメイン構造&#34;&gt;ドメイン構造&lt;/h3&gt;
&lt;p&gt;本モデルでは下記のエンティティを扱うことにする:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Cluster&lt;/code&gt;: 処理対象のRDSクラスタ&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Day&lt;/code&gt;: 処理対象日&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Job&lt;/code&gt;: システムによる、ログエクスポートをトリガーするジョブ&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ExportTask&lt;/code&gt;: CloudWatchがバックエンドで実行する監査ログのエクスポートタスク&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Alloyコードとしては下記のようになる:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-alloy&#34; data-lang=&#34;alloy&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;module&lt;/span&gt; RdsAuditLogExport
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;// Domain model&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;sig&lt;/span&gt; Cluster &lt;span style=&#34;color:#719e07&#34;&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;sig&lt;/span&gt; Day &lt;span style=&#34;color:#719e07&#34;&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;sig&lt;/span&gt; Job &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#586e75&#34;&gt;// 処理対象単位（Cluster × Day）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  cluster: &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; Cluster, &lt;span style=&#34;color:#586e75&#34;&gt;// 各Jobはちょうど一つのClusterを持つ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  day: &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; Day
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;sig&lt;/span&gt; ExportTask &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#586e75&#34;&gt;// AWSの仕様上並行実行不能なのでone&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;var&lt;/span&gt; job: &lt;span style=&#34;color:#719e07&#34;&gt;lone&lt;/span&gt; Job &lt;span style=&#34;color:#586e75&#34;&gt;// 未使用状態があり得るのでoneではなくlone&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑トリガーごとの独立性を示したい&lt;code&gt;job&lt;/code&gt;は、Alloy 6の新機能である&lt;a href=&#34;https://alloytools.org/alloy6.html#:~:text=Alloy%206%20extends%20previous%20versions%20of%20Alloy%20with%20a%20var%20keyword%20to%20specify%20that%20a%20signature%20or%20field%20is%20mutable&#34;&gt;mutable field&lt;/a&gt;（&lt;code&gt;var&lt;/code&gt;）を使って表現する。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Cluster&lt;/code&gt;と&lt;code&gt;Job&lt;/code&gt;だけで表現できる要件があるので、さっそく書いてみる:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  one sig ExportTask { // AWSの仕様上並行実行不能なのでone
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    var job: lone Job // 未使用状態があり得るのでoneではなくlone
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ /*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+  * 各ClusterとDayの組について、処理対象となるJobがちょうど1つ存在する
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+  *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+  * IR001: 各RDSクラスタについて1日を一つの処理対象単位とする
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+  *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+  * IR002: 処理対象単位を、ClusterとDayの組で一意に識別する
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+  */
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ fact OneJobPerClusterAndDay {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   all c: Cluster, d: Day |
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+     one j: Job | // 条件を満たすJobがちょうど1つ存在する
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+       j.cluster = c and j.day = d
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑&lt;code&gt;sig&lt;/code&gt;（signature）で記述したドメインオブジェクトを使って、システム要件を&lt;code&gt;fact&lt;/code&gt;として宣言する。
TLA+はほぼ数式だが、Alloyはほぼプログラミング言語って感じ。
ちなみに、ここで使われている&lt;code&gt;=&lt;/code&gt;は代入ではなく条件判定の意味。&lt;/p&gt;
&lt;p&gt;シンタックスエラー等の早期発見のため、いったんここまででコードを&lt;code&gt;execute&lt;/code&gt;しておく:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Executing &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Run Default for 4 but 4 int, 4 seq expect 1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Solver&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;sat4j Bitwidth&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;4&lt;/span&gt; MaxSeq&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;4&lt;/span&gt; SkolemDepth&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Symmetry&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;OFF Mode&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;batch
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#2aa198&#34;&gt;689&lt;/span&gt; vars&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;64&lt;/span&gt; primary vars&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;1444&lt;/span&gt; clauses&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;2&lt;/span&gt;ms&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Instance found&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; Predicate is consistent, as expected&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;6&lt;/span&gt;ms&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑まだなにも検査してないが、少なくともコンパイルが通ることはわかった。&lt;/p&gt;
&lt;h3 id=&#34;状態&#34;&gt;状態&lt;/h3&gt;
&lt;p&gt;続いて、システムがとりうる状態をコード化していく。&lt;/p&gt;
&lt;p&gt;下記の概念を扱うことにする:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;JobStatus&lt;/code&gt;: ジョブの状態
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Pending&lt;/code&gt;（実行待ち）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Running&lt;/code&gt;（実行中）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RetryWaiting&lt;/code&gt;（リトライ待ち）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Succeeded&lt;/code&gt;（成功）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PendingNotification&lt;/code&gt;（規定のリトライ数を実行済み、通知待ち）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ExportTaskStatus&lt;/code&gt;: CloudWatchによる監査ログエクスポートタスクの状態
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Unused&lt;/code&gt;（エクスポート枠が未使用）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Active&lt;/code&gt;（エクスポート中）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TaskSucceeded&lt;/code&gt;（エクスポート成功）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TaskFailed&lt;/code&gt;（エクスポート失敗）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これらをコード化すると下記のようになる:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fact OneJobPerClusterAndDay {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    all c: Cluster, d: Day |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      one j: Job |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        j.cluster = c and j.day = d
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ // Status
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ abstract sig JobStatus {}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ one sig Pending,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+         Running,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+         RetryWaiting,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+         Succeeded,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+         PendingNotification
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   extends JobStatus {}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ abstract sig ExportTaskStatus {}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ one sig Unused,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+         Active,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+         TaskSucceeded,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+         TaskFailed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   extends ExportTaskStatus {}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑ここでの&lt;code&gt;one&lt;/code&gt;も前述のものと同じく「ちょうど1つ」の意味で、シングルトンな&lt;code&gt;sig&lt;/code&gt;を複数種まとめて宣言しているだけ。
&lt;code&gt;abstract&lt;/code&gt;な親と組み合わせることで、実質的にenumとして振る舞う。&lt;/p&gt;
&lt;p&gt;また、&lt;code&gt;JobStatus&lt;/code&gt;と&lt;code&gt;ExportTaskStatus&lt;/code&gt;はそれぞれ&lt;code&gt;Job&lt;/code&gt;と&lt;code&gt;ExportTask&lt;/code&gt;が持つべき状態なので、それを明示する:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  sig Job { // 処理対象単位（Cluster × Day）
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cluster: one Cluster,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#dc322f&#34;&gt;-   day: one Day
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#dc322f&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   day: one Day,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   var status: one JobStatus
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  one sig ExportTask { // AWSの仕様上並行実行不能なのでone
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#dc322f&#34;&gt;-   var job: lone Job // 未使用状態があり得るのでoneではなくlone
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#dc322f&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   var job: lone Job, // 未使用状態があり得るのでoneではなくlone
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   var status: one ExportTaskStatus
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここまでをまたexecuteしてみる:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Executing &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Run Default for 4 but 4 int, 4 seq expect 1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Solver&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;sat4j Steps&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;1.&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;10&lt;/span&gt; Bitwidth&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;4&lt;/span&gt; MaxSeq&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;4&lt;/span&gt; SkolemDepth&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Symmetry&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;OFF Mode&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;batch
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#2aa198&#34;&gt;1.&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; steps&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;849&lt;/span&gt; vars&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;101&lt;/span&gt; primary vars&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;1704&lt;/span&gt; clauses&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;3&lt;/span&gt;ms&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Instance found&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; Predicate is consistent, as expected&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;2&lt;/span&gt;ms&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑問題なし。&lt;/p&gt;
&lt;p&gt;状態の定義までできたので、次は初期状態の定義に進む。&lt;/p&gt;
&lt;h3 id=&#34;初期状態&#34;&gt;初期状態&lt;/h3&gt;
&lt;p&gt;シミュレーション開始時点のシステムの状態を定義する。&lt;/p&gt;
&lt;p&gt;すべての（今回はたまたま並行実行が最大一つの想定だが）、&lt;code&gt;Job&lt;/code&gt;と&lt;code&gt;ExportTask&lt;/code&gt;の初期状態はそれぞれ&lt;code&gt;Pending&lt;/code&gt;と&lt;code&gt;Unused&lt;/code&gt;であってほしい:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  one sig Unused,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          Active,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          TaskSucceeded,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          TaskFailed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    extends ExportTaskStatus {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+  
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ pred init {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   all j: Job | j.status = Pending and j.attempts = 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   ExportTask.status = Unused
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   no ExportTask.job
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑&lt;code&gt;one sig&lt;/code&gt;である&lt;code&gt;ExportTask&lt;/code&gt;と、ふつうの&lt;code&gt;sig&lt;/code&gt;である&lt;code&gt;Job&lt;/code&gt;の違いがシンタックスによく表れている。&lt;/p&gt;
&lt;p&gt;ここまでの定義がうまくいっているか、いったん確認しておきたい。
検査を実行するために下記を追加する:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  pred init {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    all j: Job | j.status = Pending and j.attempts = 0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ExportTask.status = Unused
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    no ExportTask.job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ run init for
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   exactly 2 Cluster,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   exactly 1 Day,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   exactly 2 Job
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;executeしてみる:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Executing &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Run init for exactly 2 Cluster, exactly 1 Day, exactly 2 Job&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Actual scopes: exactly &lt;span style=&#34;color:#2aa198&#34;&gt;2&lt;/span&gt; Cluster, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Day, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;2&lt;/span&gt; Job, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; ExportTask, &lt;span style=&#34;color:#2aa198&#34;&gt;5&lt;/span&gt; JobStatus, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Pending, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Running, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; RetryWaiting, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Succeeded, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; PendingNotification, &lt;span style=&#34;color:#2aa198&#34;&gt;4&lt;/span&gt; ExportTaskStatus, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Unused, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Active, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; TaskSucceeded, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; TaskFailed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Solver&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;sat4j Steps&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;1.&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;10&lt;/span&gt; Bitwidth&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;4&lt;/span&gt; MaxSeq&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;4&lt;/span&gt; SkolemDepth&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Symmetry&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;20&lt;/span&gt; Mode&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;batch
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#2aa198&#34;&gt;1.&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; steps&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;127&lt;/span&gt; vars&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;23&lt;/span&gt; primary vars&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;202&lt;/span&gt; clauses&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;9&lt;/span&gt;ms&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Instance found&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; Predicate is consistent&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;4&lt;/span&gt;ms&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;figure&gt;&lt;img src=&#34;https://rindrics.com/images/2026-07-26-alloy/initial.webp&#34;
    alt=&#34;初期状態が想定通りになっている&#34;&gt;&lt;figcaption&gt;
      &lt;p&gt;初期状態が想定通りになっている&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h3 id=&#34;状態遷移&#34;&gt;状態遷移&lt;/h3&gt;
&lt;p&gt;ここまでに出てきた状態に関する各概念について、足りないものを補っていく。&lt;/p&gt;
&lt;p&gt;システムの&lt;code&gt;Job&lt;/code&gt;がとる状態（&lt;code&gt;var status&lt;/code&gt;）は、下のように遷移してほしい:&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;stateDiagram-v2
    [*] --&gt; Pending: 初期状態
    Pending --&gt; Running: 開始
    Running --&gt; Succeeded: 終了
    Running --&gt; RetryWaiting: 失敗（規定の試行回数未満）
    Running --&gt; PendingNotification: 失敗（規定の試行回数に到達）
    RetryWaiting --&gt; Running: 再開

    classDef idle fill:#f5f5f5,stroke:#9e9e9e,stroke-width:1px,color:#212121
    classDef active fill:#bdbdbd,stroke:#616161,stroke-width:2px,color:#212121
    classDef waiting fill:#e0e0e0,stroke:#757575,stroke-width:1px,color:#212121
    classDef done fill:#424242,stroke:#212121,stroke-width:2px,color:#ffffff

    class Pending idle
    class Running active
    class RetryWaiting waiting
    class Succeeded done
    class PendingNotification done
&lt;/pre&gt;

&lt;p&gt;↑リトライ上限（&lt;code&gt;var attempts&lt;/code&gt;）も定義する必要がある。&lt;/p&gt;
&lt;p&gt;またCloudWatchの&lt;code&gt;ExportTask&lt;/code&gt;の状態は、下のように遷移する意図で定義したものである:&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;stateDiagram-v2
    [*] --&gt; Unused: 初期状態
    Unused --&gt; Active: 開始
    Active --&gt; TaskSucceeded: 成功
    Active --&gt; TaskFailed: 失敗
    TaskSucceeded --&gt; Unused: 実行枠を解放
    TaskFailed --&gt; Unused: 実行枠を解放

    classDef idle fill:#f5f5f5,stroke:#9e9e9e,stroke-width:1px,color:#212121
    classDef active fill:#bdbdbd,stroke:#616161,stroke-width:2px,color:#212121
    classDef result fill:#757575,stroke:#424242,stroke-width:1px,color:#ffffff

    class Unused idle
    class Active active
    class TaskSucceeded result
    class TaskFailed result
&lt;/pre&gt;

&lt;p&gt;↑&lt;code&gt;Job&lt;/code&gt;とは違って、こちらはリクエストを受けて淡々と実行するだけの形にモデリングしているので、&lt;strong&gt;再&lt;/strong&gt;実行のような概念はない。&lt;/p&gt;
&lt;p&gt;Alloyで状態遷移を表すには、これらの状態遷移図の矢印で発生するイベントを述語（&lt;code&gt;pred&lt;/code&gt;）として定義する必要がある。
以下で、それぞれの関数を個別のブロックで示していく。
すべて&lt;code&gt;rds-audit-log-export.als&lt;/code&gt;への追記である。&lt;/p&gt;
&lt;p&gt;エクスポート処理をシステムの&lt;code&gt;Job&lt;/code&gt;がトリガーする様子:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-alloy&#34; data-lang=&#34;alloy&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;// Events&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;pred&lt;/span&gt; startExport&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;j: Job&lt;span style=&#34;color:#719e07&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// guard&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;in&lt;/span&gt; Pending &lt;span style=&#34;color:#719e07&#34;&gt;+&lt;/span&gt; RetryWaiting
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Unused
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// effect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Running
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Active
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; j
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑枠が空いていて、かつ実行待ちまたはリトライ待ちの&lt;code&gt;Job&lt;/code&gt;があるときに実行される。&lt;/p&gt;
&lt;p&gt;CloudWatchのエクスポートタスク作成に失敗したり、エクスポートタスクが失敗したときには有限回リトライしてほしいので、&lt;code&gt;Job&lt;/code&gt;で試行回数を管理することにする:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff:rds-audit-log-export.als&#34; data-lang=&#34;diff:rds-audit-log-export.als&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;sig&lt;/span&gt; Job &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#586e75&#34;&gt;// 処理対象単位（Cluster × Day）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cluster: &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; Cluster, &lt;span style=&#34;color:#586e75&#34;&gt;// 各Jobはちょうど一つのClusterを持つ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    day: &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; Day,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;-&lt;/span&gt;   &lt;span style=&#34;color:#719e07&#34;&gt;var&lt;/span&gt; status: &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; JobStatus
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+&lt;/span&gt;   &lt;span style=&#34;color:#719e07&#34;&gt;var&lt;/span&gt; status: &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; JobStatus,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+&lt;/span&gt;   &lt;span style=&#34;color:#719e07&#34;&gt;var&lt;/span&gt; attempts: &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; &lt;span style=&#34;color:#dc322f&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;初期状態ではもちろん試行回数は0回:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  pred init {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#dc322f&#34;&gt;-   all j: Job | j.status = Pending
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#dc322f&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   all j: Job | j.status = Pending and j.attempts = 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;&lt;/span&gt;    ExportTask.status = Unused
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    no ExportTask.job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;試行回数は有限にしたいので、ひとまず3回を上限としておく:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff:rds-audit-log-export.als&#34; data-lang=&#34;diff:rds-audit-log-export.als&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#586e75&#34;&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;+  * 1つの処理対象単位（Job）に許される試行回数の上限
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;+  * 初回実行とリトライを合算した回数とする（3ならリトライは最大2回）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;+  */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;fun&lt;/span&gt; MaxAttempts: &lt;span style=&#34;color:#dc322f&#34;&gt;Int&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;3&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;pred&lt;/span&gt; startExport&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;j: Job&lt;span style=&#34;color:#719e07&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#586e75&#34;&gt;// guard&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;in&lt;/span&gt; Pending &lt;span style=&#34;color:#719e07&#34;&gt;+&lt;/span&gt; RetryWaiting
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+&lt;/span&gt;   j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts &lt;span style=&#34;color:#719e07&#34;&gt;&amp;lt;&lt;/span&gt; MaxAttempts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Unused
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#586e75&#34;&gt;// effect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Running
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+&lt;/span&gt;   j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; add&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts, &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Active
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; j
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;重要なポイントとして、このシステムでは一つの&lt;code&gt;ExportTask&lt;/code&gt;枠を&lt;code&gt;クラスタ数 × 日付&lt;/code&gt;個の&lt;code&gt;Job&lt;/code&gt;が譲り合って（？）利用する必要がある。
現時点の書き方だと、すべての&lt;code&gt;Job&lt;/code&gt;の状態がそれぞれ同時に変化するようになってしまっている。
Alloyのドキュメントで&lt;a href=&#34;https://haslab.github.io/formal-software-design/overview/index.html#:~:text=If%20nothing%20is,frame%20conditions.&#34;&gt;説明されている&lt;/a&gt;通り、変化してはならないものについてはそれを明示する必要がある。
この制約を明示するには、ジョブが変化しない場合を表現した関数を追加したうえで、&lt;code&gt;startExport&lt;/code&gt;を下記のようにする:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  pred init {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    all j: Job | j.status = Pending and j.attempts = 0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ExportTask.status = Unused
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    no ExportTask.job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ // Frame conditions
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ pred noJobChange[js: set Job] {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   all j: js | j.status&amp;#39; = j.status and j.attempts&amp;#39; = j.attempts
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;&lt;/span&gt;  // Events
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  pred startExport[j: Job] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    // guard
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j.status in Pending + RetryWaiting
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j.attempts &amp;lt; MaxAttempts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ExportTask.status = Unused
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    // effect
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j.status&amp;#39; = Running
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j.attempts&amp;#39; = add[j.attempts, 1]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ExportTask.status&amp;#39; = Active
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ExportTask.job&amp;#39; = j
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   // frame
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   noJobChange[Job - j]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また、エクスポートタスクは時間がかかるため、システムのタイムステップが進んでも、タスク状態が変わっていない状況がありえる。
そのためエクスポートタスクについても、状態を変化させないフレーム関数をつくる:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  pred noJobChange[js: set Job] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    all j: js | j.status&amp;#39; = j.status and j.attempts&amp;#39; = j.attempts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ pred noTaskChange {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   ExportTask.status&amp;#39; = ExportTask.status
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   ExportTask.job&amp;#39; = ExportTask.job
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ } 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この調子で、状態遷移に必要な他の&lt;code&gt;pred&lt;/code&gt;を追加していく&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;エクスポートタスクの成功・失敗:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-alloy&#34; data-lang=&#34;alloy&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;pred&lt;/span&gt; taskSucceed &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// guard&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Active
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// effect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; TaskSucceeded
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// frame&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  noJobChange&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;Job&lt;span style=&#34;color:#719e07&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;pred&lt;/span&gt; taskFail &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// guard&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Active
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// effect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; TaskFailed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// frame&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  noJobChange&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;Job&lt;span style=&#34;color:#719e07&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑ただ一つの&lt;code&gt;Job&lt;/code&gt;と紐づくようにガードを入れている。&lt;/p&gt;
&lt;p&gt;ジョブの終了:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-alloy&#34; data-lang=&#34;alloy&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;pred&lt;/span&gt; completeJob &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// guard&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; TaskSucceeded
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;let&lt;/span&gt; j &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Running
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#586e75&#34;&gt;// effect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Succeeded
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#586e75&#34;&gt;// frame&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    noJobChange&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;Job &lt;span style=&#34;color:#719e07&#34;&gt;-&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// ExportTask実行枠を解放&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Unused
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;no&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑エクスポートが成功したらエクスポートタスク実行枠を解放する。&lt;/p&gt;
&lt;p&gt;失敗のハンドリング:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-alloy&#34; data-lang=&#34;alloy&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;pred&lt;/span&gt; handleFailure &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; TaskFailed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;let&lt;/span&gt; j &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Running
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts &lt;span style=&#34;color:#719e07&#34;&gt;&amp;lt;&lt;/span&gt; MaxAttempts &lt;span style=&#34;color:#719e07&#34;&gt;implies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; RetryWaiting
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts &lt;span style=&#34;color:#719e07&#34;&gt;&amp;gt;=&lt;/span&gt; MaxAttempts &lt;span style=&#34;color:#719e07&#34;&gt;implies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; PendingNotification
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    noJobChange&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;Job &lt;span style=&#34;color:#719e07&#34;&gt;-&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Unused
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;no&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここまでのAlloyコードの全体は下記のようになる:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-alloy&#34; data-lang=&#34;alloy&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;module&lt;/span&gt; RdsAuditLogExport
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;// Domain model&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;sig&lt;/span&gt; Cluster &lt;span style=&#34;color:#719e07&#34;&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;sig&lt;/span&gt; Day &lt;span style=&#34;color:#719e07&#34;&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;sig&lt;/span&gt; Job &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#586e75&#34;&gt;// 処理対象単位（Cluster × Day）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  cluster: &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; Cluster, &lt;span style=&#34;color:#586e75&#34;&gt;// 各Jobはちょうど一つのClusterを持つ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  day: &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; Day,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;var&lt;/span&gt; status: &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; JobStatus,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;var&lt;/span&gt; attempts: &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; &lt;span style=&#34;color:#dc322f&#34;&gt;Int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;sig&lt;/span&gt; ExportTask &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#586e75&#34;&gt;// AWSの仕様上並行実行不能なのでone&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;var&lt;/span&gt; job: &lt;span style=&#34;color:#719e07&#34;&gt;lone&lt;/span&gt; Job, &lt;span style=&#34;color:#586e75&#34;&gt;// 未使用状態があり得るのでoneではなくlone&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;var&lt;/span&gt; status: &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; ExportTaskStatus
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; * 各ClusterとDayの組について、処理対象となるJobがちょうど1つ存在する
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; * IR001: 各RDSクラスタについて1日を一つの処理対象単位とする
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; * IR002: 処理対象単位を、ClusterとDayの組で一意に識別する
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;fact&lt;/span&gt; OneJobPerClusterAndDay &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;all&lt;/span&gt; c: Cluster, d: Day &lt;span style=&#34;color:#719e07&#34;&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; j: Job &lt;span style=&#34;color:#719e07&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#586e75&#34;&gt;// 条件を満たすJobがちょうど1つ存在する&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;cluster &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; c &lt;span style=&#34;color:#719e07&#34;&gt;and&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;day &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; d
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;// Status&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;abstract&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;sig&lt;/span&gt; JobStatus &lt;span style=&#34;color:#719e07&#34;&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;sig&lt;/span&gt; Pending,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Running,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        RetryWaiting,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Succeeded,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        PendingNotification
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;extends&lt;/span&gt; JobStatus &lt;span style=&#34;color:#719e07&#34;&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;abstract&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;sig&lt;/span&gt; ExportTaskStatus &lt;span style=&#34;color:#719e07&#34;&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;sig&lt;/span&gt; Unused,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Active,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        TaskSucceeded,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        TaskFailed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;extends&lt;/span&gt; ExportTaskStatus &lt;span style=&#34;color:#719e07&#34;&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;pred&lt;/span&gt; init &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;all&lt;/span&gt; j: Job &lt;span style=&#34;color:#719e07&#34;&gt;|&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Pending &lt;span style=&#34;color:#719e07&#34;&gt;and&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Unused
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;no&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;// Frame conditions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;pred&lt;/span&gt; noJobChange&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;js: &lt;span style=&#34;color:#719e07&#34;&gt;set&lt;/span&gt; Job&lt;span style=&#34;color:#719e07&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;all&lt;/span&gt; j: js &lt;span style=&#34;color:#719e07&#34;&gt;|&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;and&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;pred&lt;/span&gt; noTaskChange &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;// Events&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; * 1つの処理対象単位（Job）に許される試行回数の上限
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; * 初回実行とリトライを合算した回数とする（3ならリトライは最大2回）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;fun&lt;/span&gt; MaxAttempts: &lt;span style=&#34;color:#dc322f&#34;&gt;Int&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;3&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;pred&lt;/span&gt; startExport&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;j: Job&lt;span style=&#34;color:#719e07&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// guard&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;in&lt;/span&gt; Pending &lt;span style=&#34;color:#719e07&#34;&gt;+&lt;/span&gt; RetryWaiting
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts &lt;span style=&#34;color:#719e07&#34;&gt;&amp;lt;&lt;/span&gt; MaxAttempts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Unused
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// effect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Running
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; add&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts, &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Active
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; j
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// frame&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  noJobChange&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;Job &lt;span style=&#34;color:#719e07&#34;&gt;-&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; * CloudWatch Logsのエクスポート処理が成功する。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; * JobはまだRunningのままであり、completeJobによって
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; * 成功確認後にSucceededへ遷移する。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;pred&lt;/span&gt; taskSucceed &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// guard&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Active
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// effect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; TaskSucceeded
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// frame&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  noJobChange&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;Job&lt;span style=&#34;color:#719e07&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; * CloudWatch Logsのエクスポート処理が失敗する。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; * JobはまだRunningのままであり、handleFailureによって
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; * RetryWaitingまたはPendingNotificationへ遷移する。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;pred&lt;/span&gt; taskFail &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// guard&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Active
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// effect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; TaskFailed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// frame&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  noJobChange&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;Job&lt;span style=&#34;color:#719e07&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; * ExportTaskの成功を確認し、対応するJobを完了させる。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;pred&lt;/span&gt; completeJob &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// guard&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; TaskSucceeded
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;let&lt;/span&gt; j &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Running
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#586e75&#34;&gt;// effect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Succeeded
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#586e75&#34;&gt;// frame&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    noJobChange&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;Job &lt;span style=&#34;color:#719e07&#34;&gt;-&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#586e75&#34;&gt;// ExportTask実行枠を解放&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Unused
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;no&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;pred&lt;/span&gt; handleFailure &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; TaskFailed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;one&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;let&lt;/span&gt; j &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Running
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts &lt;span style=&#34;color:#719e07&#34;&gt;&amp;lt;&lt;/span&gt; MaxAttempts &lt;span style=&#34;color:#719e07&#34;&gt;implies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; RetryWaiting
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts &lt;span style=&#34;color:#719e07&#34;&gt;&amp;gt;=&lt;/span&gt; MaxAttempts &lt;span style=&#34;color:#719e07&#34;&gt;implies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; PendingNotification
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    noJobChange&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;Job &lt;span style=&#34;color:#719e07&#34;&gt;-&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Unused
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;no&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job&lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;run&lt;/span&gt; init &lt;span style=&#34;color:#719e07&#34;&gt;for&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;exactly&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;2&lt;/span&gt; Cluster,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;exactly&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Day,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;exactly&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;2&lt;/span&gt; Job
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;さてこの状態でexecuteしても、前回の実行時からの違いは&lt;code&gt;attempts&lt;/code&gt;を示す&lt;code&gt;0&lt;/code&gt;が追加されただけで、その他のシステムの状態には全く変化がない:
&lt;figure&gt;&lt;img src=&#34;https://rindrics.com/images/2026-07-26-alloy/state-fixed.webp&#34;&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;これは、現在の&lt;code&gt;run&lt;/code&gt;コマンドが、初期状態を表す&lt;code&gt;init&lt;/code&gt; predicateだけを満たすトレースを探索しているためだ:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-alloy&#34; data-lang=&#34;alloy&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;pred&lt;/span&gt; init &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;all&lt;/span&gt; j: Job &lt;span style=&#34;color:#719e07&#34;&gt;|&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Pending &lt;span style=&#34;color:#719e07&#34;&gt;and&lt;/span&gt; j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; Unused
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;no&lt;/span&gt; ExportTask&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;job
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;run&lt;/span&gt; init &lt;span style=&#34;color:#719e07&#34;&gt;for&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;exactly&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;2&lt;/span&gt; Cluster,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;exactly&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Day,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;exactly&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;2&lt;/span&gt; Job
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そこで、探索対象に&lt;code&gt;startExport&lt;/code&gt; predicateを含めてみる:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#dc322f&#34;&gt;- run init for
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#dc322f&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ run {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   init
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+   some j: Job | startExport[j]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ } for
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;&lt;/span&gt;  exactly 2 Cluster,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  exactly 1 Day,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#dc322f&#34;&gt;- exactly 2 Job
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#dc322f&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+ exactly 2 Job,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;+  3 Int
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑&lt;code&gt;some j: Job | startExport[j]&lt;/code&gt;は、「少なくとも1つの&lt;code&gt;Job&lt;/code&gt;について、&lt;code&gt;startExport[j]&lt;/code&gt;という状態遷移が成立する」という意味&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;また、ややわかりにくいが、&lt;code&gt;run&lt;/code&gt;コマンド最後の&lt;code&gt;3 Int&lt;/code&gt;は、この検証で使いたい整数の範囲を符号付きビット数で指定したもの。
いまは最大でも試行回数用に3まで表現できれば足りるので、3ビットの符号つき整数（-4〜3）でOK。&lt;/p&gt;
&lt;p&gt;探索範囲に&lt;code&gt;startExport&lt;/code&gt;を含めた実行結果を示したのが下図:
&lt;figure&gt;&lt;img src=&#34;https://rindrics.com/images/2026-07-26-alloy/start-export.webp&#34;&gt;
&lt;/figure&gt;

↑&lt;code&gt;status&lt;/code&gt;が&lt;code&gt;Running&lt;/code&gt;となった&lt;code&gt;Job0&lt;/code&gt;の&lt;code&gt;attempt&lt;/code&gt;が&lt;code&gt;1&lt;/code&gt;になり、それが&lt;code&gt;Active&lt;/code&gt;になった&lt;code&gt;ExportTask&lt;/code&gt;と紐づいている。&lt;/p&gt;
&lt;p&gt;ここまでで、ひとまず検証ループを一周回せた。&lt;/p&gt;
&lt;h2 id=&#34;alloyコードとシステム初期要件との照合&#34;&gt;Alloyコードとシステム初期要件との照合&lt;/h2&gt;
&lt;p&gt;&lt;!-- raw HTML omitted --&gt;&lt;!-- raw HTML omitted --&gt;&lt;/p&gt;
&lt;p&gt;システムに対する理解のモデル化を一通り終えたつもりなので、ここでシステム初期要件を見直し、モデル定義で保証できている要件と、追加で検証が必要な要件とを分類する。&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;ID&lt;/th&gt;
          &lt;th&gt;概要&lt;/th&gt;
          &lt;th&gt;対応元&lt;/th&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;現在の対応状況&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;IR001&lt;/td&gt;
          &lt;td&gt;各RDSクラスタについて1日を一つの処理対象単位とする&lt;/td&gt;
          &lt;td&gt;A001, R002&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;&lt;code&gt;Day&lt;/code&gt;としてモデル化済&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;IR002&lt;/td&gt;
          &lt;td&gt;処理対象単位はクラスタと対象日の組で一意に識別される&lt;/td&gt;
          &lt;td&gt;R002, R003, R004&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;&lt;code&gt;OneJobPerClusterAndDay&lt;/code&gt; factで構造的に保証済 &amp;#x2705;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;IR003&lt;/td&gt;
          &lt;td&gt;同時にアクティブにするexport taskは最大1つとする&lt;/td&gt;
          &lt;td&gt;C001&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;単一のエクスポートタスク実行枠として構造的に保証済 &amp;#x2705;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;IR004&lt;/td&gt;
          &lt;td&gt;失敗した処理は規定の上限回数まで再試行される&lt;/td&gt;
          &lt;td&gt;R003, R005, R006&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;モデル化済み・追加で検証が必要 &amp;#x26a0;&amp;#xfe0f;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;IR005&lt;/td&gt;
          &lt;td&gt;試行上限に達したジョブはそれ以上自動試行されない&lt;/td&gt;
          &lt;td&gt;R005&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;モデル化済み・追加で検証が必要 &amp;#x26a0;&amp;#xfe0f;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;IR006&lt;/td&gt;
          &lt;td&gt;試行上限に達したジョブを通知対象として記録する&lt;/td&gt;
          &lt;td&gt;R006&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;PendingNotificationとしてモデル化済み・追加で検証が必要&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt; &amp;#x26a0;&amp;#xfe0f;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;IR007&lt;/td&gt;
          &lt;td&gt;成功済みの処理対象単位を再び実行対象にしない&lt;/td&gt;
          &lt;td&gt;R004&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;&lt;code&gt;startExport&lt;/code&gt;のガードでモデル化済み・追加で検証が必要 &amp;#x26a0;&amp;#xfe0f;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;IR008&lt;/td&gt;
          &lt;td&gt;ある処理対象単位について、成功したexport taskの成果物は高々1つとする&lt;/td&gt;
          &lt;td&gt;R004&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;成果物または実行履歴の追加モデル化と検証が必要 &amp;#x26a0;&amp;#xfe0f;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;IR009&lt;/td&gt;
          &lt;td&gt;各処理対象単位は、成功または通知対象のいずれかに到達するまで管理対象から削除しない&lt;/td&gt;
          &lt;td&gt;R003, R006&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;signatureである&lt;code&gt;Job&lt;/code&gt;は消えない点は構造的に保証済。ただし終端状態への到達は追加で検証が必要 &amp;#x26a0;&amp;#xfe0f;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;hellip;うーん。各要件を意識しながらモデル化したつもりだったが、あらためてなぞってみると、複数の制約の組み合わせによって表現されていて、&amp;ldquo;構造的に保証済&amp;quot;と言い切れるものはほとんどなかった&lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;。
ちなみにAlloyの動作原理は有限範囲を探索するだけなので、構造的に保証したもの以外は「探索した範囲内では反例は見つかりませんでした」という意味でしかないらしい。
ただそれでも、人間の根気ではとても列挙できない多数の状態や組み合わせを機械的に探索してくれるし、境界条件や複数の状態遷移が組み合わさったときの欠陥を発見してくれる点に、やはり大きな価値があると思う。&lt;/p&gt;
&lt;h2 id=&#34;追加検証&#34;&gt;追加検証&lt;/h2&gt;
&lt;h3 id=&#34;事前準備&#34;&gt;事前準備&lt;/h3&gt;
&lt;p&gt;追加の検証でassertとcheckを利用するため、システムが取り得る状態遷移をTraces factとして定義する:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-alloy:rds-audit-log-export.als&#34; data-lang=&#34;alloy:rds-audit-log-export.als&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;pred&lt;/span&gt; stutter &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  noJobChange&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;Job&lt;span style=&#34;color:#719e07&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  noTaskChange
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;fact&lt;/span&gt; Traces &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  init
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;always&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#719e07&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;some&lt;/span&gt; j: Job &lt;span style=&#34;color:#719e07&#34;&gt;|&lt;/span&gt; startExport&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;j&lt;span style=&#34;color:#719e07&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#719e07&#34;&gt;or&lt;/span&gt; taskSucceed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#719e07&#34;&gt;or&lt;/span&gt; taskFail
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#719e07&#34;&gt;or&lt;/span&gt; completeJob
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#719e07&#34;&gt;or&lt;/span&gt; handleFailure
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#719e07&#34;&gt;or&lt;/span&gt; stutter
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑&lt;code&gt;always&lt;/code&gt;の内部では、各時点から次の時点への遷移が、列挙したpredicateのいずれかに一致することを要求している。
しかし、すべてのジョブが状態遷移の終端に到達した場合や、外部処理の完了を待っている場合など、実質的に状態が変化しない時点もあり得る。
そこで、すべての可変フィールドを現在の値のまま維持するstutter遷移を追加する。これにより、実行可能なイベントがない状態でも、同じ状態にとどまるトレースを表現できる。&lt;/p&gt;
&lt;p&gt;準備ができたので、&lt;code&gt;IR0004&lt;/code&gt;に対応するassertを追加してみる。&lt;/p&gt;
&lt;h3 id=&#34;ir004-失敗した処理は規定の上限回数まで再試行される&#34;&gt;IR004: 失敗した処理は規定の上限回数まで再試行される&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-alloy:rds-audit-log-export.als&#34; data-lang=&#34;alloy:rds-audit-log-export.als&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;assert&lt;/span&gt; FailedJobIsEventuallyRetried &lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;always&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;all&lt;/span&gt; j: Job &lt;span style=&#34;color:#719e07&#34;&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt; RetryWaiting &lt;span style=&#34;color:#719e07&#34;&gt;and&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    j&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;attempts &lt;span style=&#34;color:#719e07&#34;&gt;&amp;lt;&lt;/span&gt; MaxAttempts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#719e07&#34;&gt;implies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#719e07&#34;&gt;eventually&lt;/span&gt; startExport&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;j&lt;span style=&#34;color:#719e07&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上記のassertを8ステップ内でcheckしてみる:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-alloy:rds-audit-log-export.als&#34; data-lang=&#34;alloy:rds-audit-log-export.als&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;check&lt;/span&gt; FailedJobIsEventuallyRetried &lt;span style=&#34;color:#719e07&#34;&gt;for&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;exactly&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;2&lt;/span&gt; Cluster,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;exactly&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Day,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;exactly&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;2&lt;/span&gt; Job,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#2aa198&#34;&gt;3&lt;/span&gt; &lt;span style=&#34;color:#dc322f&#34;&gt;Int&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#2aa198&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;steps&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;反例が見つかった:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Executing &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Check FailedJobIsEventuallyRetried for 3 int 8 steps, exactly 2 Cluster, exactly 1 Day, exactly 2 Job&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Actual scopes: exactly &lt;span style=&#34;color:#2aa198&#34;&gt;2&lt;/span&gt; Cluster, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Day, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;2&lt;/span&gt; Job, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; ExportTask, &lt;span style=&#34;color:#2aa198&#34;&gt;5&lt;/span&gt; JobStatus, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Pending, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Running, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; RetryWaiting, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Succeeded, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Exhausted, &lt;span style=&#34;color:#2aa198&#34;&gt;4&lt;/span&gt; ExportTaskStatus, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Unused, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Active, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; TaskSucceeded, exactly &lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; TaskFailed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Solver&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;sat4j Steps&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;1.&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;8&lt;/span&gt; Bitwidth&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;3&lt;/span&gt; MaxSeq&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;3&lt;/span&gt; SkolemDepth&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;1&lt;/span&gt; Symmetry&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;20&lt;/span&gt; Mode&lt;span style=&#34;color:#719e07&#34;&gt;=&lt;/span&gt;batch
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#2aa198&#34;&gt;1.&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;4&lt;/span&gt; steps&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;9201&lt;/span&gt; vars&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;372&lt;/span&gt; primary vars&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;24717&lt;/span&gt; clauses&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;33&lt;/span&gt;ms&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Counterexample found&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; Assertion is invalid&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;7&lt;/span&gt;ms&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;状態を見てみる:
&lt;figure&gt;&lt;img src=&#34;https://rindrics.com/images/2026-07-26-alloy/retry-waiting.webp&#34;
    alt=&#34;Job1が失敗したままになっている&#34;&gt;&lt;figcaption&gt;
      &lt;p&gt;&lt;code&gt;Job1&lt;/code&gt;が失敗したままになっている&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

↑ジョブが&lt;code&gt;RetryWaiting&lt;/code&gt;のまま動かないケースが見つかった。
これは、連続で&lt;code&gt;stutter&lt;/code&gt; predicateが選ばれている状態らしい。
確かに、&lt;code&gt;startExport&lt;/code&gt;が選ばれる条件として&lt;code&gt;RetryWaiting&lt;/code&gt;を書いたが、&lt;code&gt;startExport&lt;/code&gt;を選ば&lt;strong&gt;なければならない&lt;/strong&gt;とは書かなかった&lt;sup id=&#34;fnref:7&#34;&gt;&lt;a href=&#34;#fn:7&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;7&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;このことから、&lt;code&gt;IR004&lt;/code&gt; は状態遷移の正しさだけでは満たすことができず、スケジューリングに関する要件が足りていないことがわかった。
追加要件（Additional Requirement）が見つかったので、IDをふって記録することにする。&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;ID&lt;/th&gt;
          &lt;th&gt;概要&lt;/th&gt;
          &lt;th&gt;関連要件&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;AR001&lt;/td&gt;
          &lt;td&gt;システムは実行を待っているJobを無期限に保留しない&lt;/td&gt;
          &lt;td&gt;IR004&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;追加要件がもっと出てきそうなので、ここでいったん一区切りとする。&lt;/p&gt;
&lt;h2 id=&#34;所感&#34;&gt;所感&lt;/h2&gt;
&lt;p&gt;本記事は、RDS監査ログのエクスポートシステムの設計について検討した（しきれなかった）。
監査ログアーキテクチャが頭に浮かんではいるが&lt;sup id=&#34;fnref:8&#34;&gt;&lt;a href=&#34;#fn:8&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;8&lt;/a&gt;&lt;/sup&gt;、モデルには具体的なアーキテクチャの構成要素は登場させず、あくまでも要求から導かれる仕様を検証してみた。&lt;/p&gt;
&lt;p&gt;まだちょっと触ってみただけだが、Alloyの使い勝手を（TLA+の使い勝手を思い出しながら）メモしておく。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;良さが感じられた点 &amp;#x2600;&amp;#xfe0f;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ドメイン構造を第一級市民として書けるところ
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;処理対象単位が Cluster × Day で一意&amp;rdquo; という制約を一行で&lt;code&gt;one j: Job | j.cluster = c and j.day = d&lt;/code&gt;と書けた&lt;/li&gt;
&lt;li&gt;多重度（&lt;code&gt;one&lt;/code&gt; / &lt;code&gt;lone&lt;/code&gt;）が言語に組み込まれているので、&lt;code&gt;ExportTask&lt;/code&gt;に関する「未使用状態があり得る」を&lt;code&gt;var job: lone Job&lt;/code&gt;と簡潔に書けた&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;モデルを探索的に育てられるところ
&lt;ul&gt;
&lt;li&gt;「そういう状態がありうるか」を&lt;code&gt;run&lt;/code&gt;ですぐ確認できるので、今回はvacuityの検出に多用した&lt;/li&gt;
&lt;li&gt;結果の可視化機能が素晴らしい。初学者にとっては「自分のモデルが何を意味しているのか」を視覚的に確認しながら進める助けになる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;戸惑った点 &amp;#x26c5;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;フレーム条件を自分で書かないといけないところ
&lt;ul&gt;
&lt;li&gt;本記事で扱った題材では、&lt;code&gt;noJobChange[Job - j]&lt;/code&gt; のような述語を自前で用意し、全イベントで
呼ばないといけなかった。呼び忘れると、その変数が次状態で任意の値を取れるようになるので、他のsignatureの状態が意図せず勝手に変わるようになる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stutter&lt;/code&gt;を遷移の選択肢に明示的に足す必要があるところ
&lt;ul&gt;
&lt;li&gt;今回のモデルでは、全&lt;code&gt;Job&lt;/code&gt;が&lt;code&gt;Succeeded&lt;/code&gt;/&lt;code&gt;PendingNotification&lt;/code&gt;に到達し、&lt;code&gt;ExportTask&lt;/code&gt;が&lt;code&gt;Unused&lt;/code&gt;の状態でどのアクションも&lt;code&gt;Enabled&lt;/code&gt;にならない。この状態は意図された終了状態なので必ず到達するべきだが、&lt;code&gt;stutter&lt;/code&gt;を書き忘れるとシミュレーションが先に進めず、有効な無限トレースが1本も存在しなくなってしまう。厄介なのは、同じ原因が問いの向きによって逆の表示になること: 「存在するか」を問う&lt;code&gt;run&lt;/code&gt;では「インスタンスなし」と出るため問題に気付けるが、一方で「反例が存在するか」を問う&lt;code&gt;check&lt;/code&gt;はでは「反例なし」（= 検証成功）になってしまうため気付けない&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;追加要件も見つかったので、別記事で続きをやりたい。&lt;/p&gt;
&lt;h2 id=&#34;参考文献&#34;&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://haslab.github.io/formal-software-design/index.html&#34;&gt;Formal Software Design with Alloy 6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ndlsearch.ndl.go.jp/books/R100000002-I000011231617&#34;&gt;Daniel Jackson (2011) 『抽象によるソフトウェア設計: Alloyではじめる形式手法』オーム社&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/cloudwatch_limits_cwl.html#:~:text=Active%20export%20task,tasks%20per%20account&#34;&gt;CloudWatch Logs quotas | docs.aws.amazon.com&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;ここまででいったんexecuteしてみたが、必要な&lt;code&gt;pred&lt;/code&gt;を全てを定義し切らないと解決しない状態遷移系の違反が起きてしまうため&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;ちなみに&lt;code&gt;all j: Job | startExport[j]&lt;/code&gt;を探索しても、&lt;code&gt;No instance found. Predicate may be inconsistent&lt;/code&gt;となる。これは&lt;code&gt;one sig ExportTask&lt;/code&gt;であり、また&lt;code&gt;ExportTask&lt;/code&gt;では&lt;code&gt;var job: lone Job&lt;/code&gt;なことによる&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;&lt;code&gt;Day&lt;/code&gt; sigによって対象日をモデル化したが、それが暦上の1日単位で生成されることは実装側で保証する必要がある&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34;&gt;
&lt;p&gt;&lt;code&gt;PendingNotification&lt;/code&gt;ステータスと、その状態へ移行する遷移をモデル化する。ただし、試行上限到達時に必ず移行することはassertで検証する必要がある&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:6&#34;&gt;
&lt;p&gt;まぁでもそれは普通のことだと思うし、だからこそ&lt;code&gt;assert&lt;/code&gt;や&lt;code&gt;check&lt;/code&gt;の存在意義があるのだけど&amp;#160;&lt;a href=&#34;#fnref:6&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:7&#34;&gt;
&lt;p&gt;ちなみに、ここで注意が必要なのは、「反例になっているのは連続stutterなのだからstutterを禁止すればよい」はNGであること。
これをやってしまうと、意図された終了状態（全&lt;code&gt;Job&lt;/code&gt;が終端状態に達し、&lt;code&gt;ExportTask&lt;/code&gt;が&lt;code&gt;Unused&lt;/code&gt;の状態など）で無限トレースが構成できず、有効なトレースが1本も存在しなくなってしまう。というか、これが起こると困るからstutterが必要なのだ&amp;#160;&lt;a href=&#34;#fnref:7&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:8&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://aws.amazon.com/jp/blogs/database/automate-the-export-of-amazon-rds-for-mysql-or-amazon-aurora-mysql-audit-logs-to-amazon-s3-with-batching-or-near-real-time-processing/&#34;&gt;アーキテクチャ例&lt;/a&gt;出てるし。&amp;#160;&lt;a href=&#34;#fnref:8&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
    </item>
    
  </channel>
</rss>
