実行モデル(全体構成と実行フロー) - smileygames/dipper GitHub Wiki

本ページは、dipper の全体構成と主要処理の実行フローを ASCII 図+短い説明で俯瞰できるように整理したものである。

  • 設計思想(なぜそうするか)とは役割が異なり、本ページは「どう動くか」を中心に扱う
  • 厳密なフローチャートではなく、全体の理解・仕様書作成・テスト設計の前提共有を目的とする
  • 詳細な実装はソースコードを正とし、本ページは読みやすい中間レイヤーとして扱う

1. 入口(エントリポイント)

  • systemd で dipper.service が起動する
  • サービスが bin/dipper.sh を起動し、常駐動作する
  • 設定は config/user.conf(ユーザー設定)を読み込む

2. 最小の実行サイクル(疑似スケジューラ)

dipper は cron / systemd timer を使用せず、 短周期ループによる 疑似スケジューラ方式で動作する。 各処理は「実行すべきタイミングかどうか」を cache の時刻で判定し、 実行が必要なときだけ動く。

  1. 短周期ループを回す(例:数十秒周期)
  2. cache を読み、各処理が「実行すべきか」を判定する
  3. 必要な処理だけ実行する(IP取得 / DDNS更新 / 通知など)
  4. 実行結果(時刻・状態・回数など)を cache に記録する
  5. 次のループで cache を基準に再判定する

この方式により、DDNS サーバーへの不要なアクセスや不要な再試行を抑え、 長期運用で壊れにくい動作を目指す。


3. 状態管理(cache の役割)

dipper は状態をメモリではなくファイル(cache)で管理する。 これは「いつ・何が・なぜ実行されたか」を見える形で残すための設計である。

  • update_cache:定期更新処理の実行状態(時刻)を記録し、更新間隔のゲートとして使用する
  • ip_cache:前回取得した IP と時刻を記録し、IP 変更検知や取得頻度制御に利用する
  • ddns_cache:DDNS 更新処理の実行状態(時刻)を記録し、連続更新を防止する
  • err_mail:通知(主にエラー通知)の実行状態を記録し、過剰通知を防止する

4. 全体構成(ASCII)

以下は 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 等)

5. 実行フロー(概略)

dipper の主要処理は、概ね次の順で進む。 (詳細はソースコードを正とし、本節は俯瞰用とする。)

  1. 起動:設定を読み込み、必要に応じて cache 初期化
  2. ループ:短周期で回り続ける
  3. 判定:cache と設定により「実行すべき処理」を決める
  4. IP:IP を取得し、必要に応じて ip_cache を更新する
  5. DDNS:更新が必要な場合のみ、dns_select → dns_service を実行する
  6. 記録:実行時刻や状態を cache に記録し、次回の判定材料にする
  7. 通知:必要条件を満たした場合のみ通知(過剰通知は err_mail でゲートする)

6. テストとの関係(重要)

  • 現在のテスト方針はホワイトボックステストを主とする
  • テストは「挙動の善悪」を裁かず、動いている挙動を固定する(歴史のスナップショット)
  • 挙動変更(仕様変更)を行う場合は、テスト整備とは切り離し、別 Issue として扱う

7. 更新ルール(運用)

  • 本ページは「全体を俯瞰できること」を最優先し、細部の実装説明は増やしすぎない
  • 細部が必要になったら、別ページ(例:cache 詳細、疑似スケジューラ詳細)へ分離してよい
  • 変更したら GitHub のコミット/Issue と結びつけ、後から追えるようにする

全体構成(ASCII 構成図)

まずは 俯瞰図 から。

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(脳)の中身を拡大

┌─────────────────────────────┐ │ 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 ディレクトリの意味(超重要)

cache/ ├ update_cache ← 定期更新の状態 ├ ddns_cache ← IP変更検知の状態 ├ err_mail ← エラー通知制御

各キャッシュの中身(概念):

last_time: 1700000000 pid: 12345

👉 cache = 状態オブジェクト

これが

Unix 的:状態はファイルに置け

の実体。


dns_select.sh(手足)

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 が

    • 時間

    • 状態

    • 実行可否

    • エラー判断

一手に引き受けている から。

でも同時に:

  • 実処理は外出し

  • 状態はファイル

  • 並列は最小限

👉 ギリギリ健全


⚠️ **GitHub.com Fallback** ⚠️