実行モデル(全体構成と実行フロー) - smileygames/dipper GitHub Wiki
本ページは、dipper の全体構成と主要処理の実行フローを ASCII 図+短い説明で俯瞰できるように整理したものである。
- 設計思想(なぜそうするか)とは役割が異なり、本ページは「どう動くか」を中心に扱う
- 厳密なフローチャートではなく、全体の理解・仕様書作成・テスト設計の前提共有を目的とする
- 詳細な実装はソースコードを正とし、本ページは読みやすい中間レイヤーとして扱う
- systemd で
dipper.serviceが起動する - サービスが
bin/dipper.shを起動し、常駐動作する - 設定は
config/user.conf(ユーザー設定)を読み込む
dipper は cron / systemd timer を使用せず、 短周期ループによる 疑似スケジューラ方式で動作する。 各処理は「実行すべきタイミングかどうか」を cache の時刻で判定し、 実行が必要なときだけ動く。
- 短周期ループを回す(例:数十秒周期)
- cache を読み、各処理が「実行すべきか」を判定する
- 必要な処理だけ実行する(IP取得 / DDNS更新 / 通知など)
- 実行結果(時刻・状態・回数など)を cache に記録する
- 次のループで cache を基準に再判定する
この方式により、DDNS サーバーへの不要なアクセスや不要な再試行を抑え、 長期運用で壊れにくい動作を目指す。
dipper は状態をメモリではなくファイル(cache)で管理する。 これは「いつ・何が・なぜ実行されたか」を見える形で残すための設計である。
- update_cache:定期更新処理の実行状態(時刻)を記録し、更新間隔のゲートとして使用する
- ip_cache:前回取得した IP と時刻を記録し、IP 変更検知や取得頻度制御に利用する
- ddns_cache:DDNS 更新処理の実行状態(時刻)を記録し、連続更新を防止する
- err_mail:通知(主にエラー通知)の実行状態を記録し、過剰通知を防止する
以下は dipper の主要コンポーネントと、実行・データ(状態)の流れを表す。 (必要に応じて更新してよい。)
systemd
└─ dipper.service
└─ bin/dipper.sh (全体制御 / 疑似スケジューラ)
│
├─ config/user.conf (設定)
│
├─ bin/cache/* (キャッシュ操作ロジック)
│ ├─ initial.sh (cache 初期化)
│ ├─ time_check.sh (cache の時間ゲート)
│ ├─ reset.sh (cache リセット)
│ └─ count.sh (回数/通知用記録)
│
├─ bin/ip_check.sh (IP 取得)
│ └─ cache/ip_cache (前回 IP / 時刻)
│
├─ bin/dns_select.sh (DDNS 処理振り分け)
│ └─ bin/dns_service/* (各 DDNS 実装)
│ ├─ mydns.sh
│ └─ cloudflare.sh
│
├─ cache/update_cache (定期更新のゲート)
├─ cache/ddns_cache (DDNS 更新のゲート)
├─ cache/err_mail (通知のゲート)
│
└─ bin/err_message.sh (logger / エラーログ出力)
└─(必要に応じて mail/sending.sh 等)
dipper の主要処理は、概ね次の順で進む。 (詳細はソースコードを正とし、本節は俯瞰用とする。)
- 起動:設定を読み込み、必要に応じて cache 初期化
- ループ:短周期で回り続ける
- 判定:cache と設定により「実行すべき処理」を決める
- IP:IP を取得し、必要に応じて ip_cache を更新する
- DDNS:更新が必要な場合のみ、dns_select → dns_service を実行する
- 記録:実行時刻や状態を cache に記録し、次回の判定材料にする
- 通知:必要条件を満たした場合のみ通知(過剰通知は err_mail でゲートする)
- 現在のテスト方針はホワイトボックステストを主とする
- テストは「挙動の善悪」を裁かず、動いている挙動を固定する(歴史のスナップショット)
- 挙動変更(仕様変更)を行う場合は、テスト整備とは切り離し、別 Issue として扱う
- 本ページは「全体を俯瞰できること」を最優先し、細部の実装説明は増やしすぎない
- 細部が必要になったら、別ページ(例:cache 詳細、疑似スケジューラ詳細)へ分離してよい
- 変更したら GitHub のコミット/Issue と結びつけ、後から追えるようにする
まずは 俯瞰図 から。
systemd │ ▼ ┌─────────────┐ │ dipper.sh │ ← メイン(脳) └─────┬───────┘ │ 30秒周期 ▼ ┌─────────────────────┐ │ timer_select() │ │ (疑似スケジューラ) │ └─────┬───────┬───────┘ │ │ ┌──────────▼─┐ ┌───▼──────────┐ │ update判定 │ │ check判定 │ └─────┬──────┘ └────┬─────────┘ │ │ ▼ ▼ ┌────────────────┐ ┌────────────────┐ │ dns_select.sh │ │ dns_select.sh │ │ update │ │ check │ └──────┬─────────┘ └──────┬─────────┘ │ │ ▼ ▼ ┌──────────────┐ ┌─────────────────┐ │ MyDNS 更新 │ │ IP取得 & 比較 │ └──────────────┘ └──────┬──────────┘ │ ▼ ┌─────────────────┐ │ DDNSサービス群 │ │ MyDNS / CF 等 │ └─────────────────┘
要素 | 役割 -- | -- systemd | dipper を生かし続ける dipper.sh | 判断しかしない脳 timer_select | 疑似スケジューラ cache | 記憶(状態) dns_select.sh | 実行担当 dns_service/* | 実処理
┌─────────────────────────────┐ │ dipper.sh │ ├─────────────────────────────┤ │ config 読み込み │ │ ├ default.conf │ │ └ user.conf │ │ │ │ 時間設定の正規化 │ │ ├ UPDATE_TIME │ │ ├ DDNS_TIME │ │ ├ IP_CACHE_TIME │ │ └ ERR_CHK_TIME │ │ │ │ dns_service_check() │ │ └ サービス定義ある? │ │ │ │ while true (30秒) │ │ └ timer_select() │ │ ├ update 判定 │ │ ├ ddns 判定 │ │ └ err_mail 判定 │ └─────────────────────────────┘
👉 重要
-
dipper.sh は IPを見ない
-
dipper.sh は DNSを叩かない
-
dipper.sh は 判断しかしない
これが「脳」と言った理由。
timer_select() │ ├─ cache/time_check.sh │ │ │ └─ 前回実行時刻との差分を見る │ ├─ cache/event_can_start.sh │ │ │ └─ 多重起動してない? │ └─ dns_select.sh & ← 非同期実行
-
sleep に依存しない
-
前回実行時刻ベース
-
多少ズレても OK
👉 cron/systemd timer を使わない理由がここ。
cache/ ├ update_cache ← 定期更新の状態 ├ ddns_cache ← IP変更検知の状態 ├ err_mail ← エラー通知制御
各キャッシュの中身(概念):
last_time: 1700000000 pid: 12345
👉 cache = 状態オブジェクト
これが
Unix 的:状態はファイルに置け
の実体。
dns_select.sh MODE │ ├ MODE=update │ └ 定期IP更新 │ ├ MODE=check │ └ IP取得 → 差分 → DDNS更新 │ └ MODE=err_mail └ メール送信
dns_select.sh は:
-
判断しない
-
スケジュールしない
-
指示されたことだけやる
👉 ワーカー
dipper =[ systemd ] ↓ [ 脳: dipper.sh ] ↓ [ 判断: 疑似スケジューラ ] ↓ [ 実行: dns_select.sh ] ↓ [ 実体: DDNSサービス ] ↓ [ 状態: cacheファイル ]
-
dipper.sh が
-
時間
-
状態
-
実行可否
-
エラー判断
-
を 一手に引き受けている から。
でも同時に:
-
実処理は外出し
-
状態はファイル
-
並列は最小限
👉 ギリギリ健全