アーキテクチャ
Wippy は Go 上に構築されたレイヤー型システムです。コンポーネントは依存関係の順序で初期化され、イベントバスを通じて通信し、work-stealing スケジューラを介して Lua プロセスを実行します。
これは実装リファレンスです。図と Go の型は、アプリケーションのレジストリエントリや拡張 API ではなく、ランタイム内部を説明します。
レイヤー
| レイヤー | コンポーネント |
|---|---|
| アプリケーション | Luaプロセス、関数、ワークフロー |
| ランタイム | Luaエンジン(wippyai/go-lua)、40以上のモジュール |
| サービス | HTTP、キュー、ストレージ、Temporal |
| システム | トポロジー、ファクトリー、関数、コントラクト |
| コア | スケジューラ、レジストリ、ディスパッチャ、イベントバス、リレー |
| インフラストラクチャ | AppContext、ロガー、トランスコーダ |
各レイヤーは下位レイヤーだけに依存します。Core レイヤーは基本的なプリミティブを提供し、Services はその上に高レベルの抽象化を構築します。
ブートシーケンス
アプリケーションの起動は 4 つのフェーズで進みます。
フェーズ 1: インフラストラクチャ
コンポーネントを読み込む前にコアインフラストラクチャを作成します。
| コンポーネント | 目的 |
|---|---|
| AppContext | コンポーネント参照用の sealed dictionary |
| EventBus | コンポーネント間通信用の pub/sub |
| Transcoder | ペイロードのシリアライズ(JSON、YAML、Lua) |
| Logger | イベントストリーミング付き構造化ログ |
| Relay | メッセージルーティング(Node、Router、Mailbox) |
フェーズ 2: コンポーネントのロード
Loaderはトポロジカルソートで依存関係を解決し、レベルごとに、1つずつコンポーネントをロードします。
レベルは依存関係のエッジによって決まります。Core や System などのパッケージグループが、別のグローバル順序を強制することはありません。そのため、依存関係のエッジがないコンポーネントは、パッケージグループにかかわらず同じレベルで読み込まれる場合があります。
各コンポーネントは Load 中に自身を context へ attach し、依存するコンポーネントからサービスを利用可能にします。
フェーズ 3: 有効化
すべてのコンポーネントを読み込んだ後、次の処理を行います。
- ランタイムサービスを開始 -
StartRuntimeServices(ctx)を呼び出す - Dispatcher を freeze - コマンドハンドラレジストリをロックし、ロックフリー検索を可能にする
- AppContext を seal - 以降の書き込みを禁止し、ロックフリー読み取りを可能にする
- コンポーネントを開始 -
Starterインターフェースを持つ各コンポーネントのStart()を呼び出す
フェーズ 4: エントリのロード
_index.json、_index.yaml、_index.yml のプロジェクトマニフェストにあるレジストリエントリを読み込み、検証します。
- プロジェクトファイルからエントリを解析
- パイプラインステージがエントリを変換(override、link、bytecode)
auto_start: trueのサービスが実行を開始- Supervisor が登録済みサービスを監視
コンポーネント
コンポーネントはアプリケーションライフサイクルに参加する Go サービスです。
ライフサイクルフェーズ
| フェーズ | メソッド | 目的 |
|---|---|---|
| Load | Load(ctx) (ctx, error) |
初期化して context へ attach |
| Start | Start(ctx) error |
アクティブな処理を開始 |
| Stop | Stop(ctx) error |
graceful shutdown |
コンポーネントは依存関係を宣言します。Loader は有向非巡回グラフを構築し、トポロジカル順序で実行します。シャットダウンは逆順で行われます。
標準コンポーネント
| コンポーネント | 依存関係 | 目的 |
|---|---|---|
| PIDGen | なし | プロセスID生成 |
| Dispatcher | PIDGen | コマンドハンドラディスパッチ |
| Registry | Artifact | エントリストレージとバージョニング |
| Finder | Registry | エントリルックアップと検索 |
| Supervisor | Registry | サービス再起動ポリシー |
| Topology | Supervisor | プロセスの親子ツリー |
| Lifecycle | Topology | サービスライフサイクル管理 |
| Factory | なし | プロセスの生成 |
| Functions | Registry | プールされた関数の実行 |
イベントバス
コンポーネント間通信用の非同期 pub/sub です。
設計
- 1 つの dispatcher goroutine がすべてのイベントを処理
- Publisher は subscriber への配信を待たずにアクションを enqueue
- パターンマッチングは完全一致、
*、**、セグメントの選択肢に対応 - context ベースのライフサイクルが subscription と cancel を関連付ける
イベントフロー
sequenceDiagram
participant P as Publisher
participant B as EventBus
participant S as Subscribers
P->>B: Send(ctx, Event)
B->>B: Match patterns
B->>S: Deliver on subscriber channel
S->>S: Execute callback
一般的なトピック
各イベントは System と Kind を持ちます。組み込みシステムが発行するもの:
| システム | 種別 | 目的 |
|---|---|---|
registry |
entry.create、entry.update、entry.delete、entry.accept、entry.reject |
エントリの変更 |
registry |
registry.begin、registry.commit、registry.discard |
トランザクション境界 |
process |
factory.register、factory.delete、factory.accept、factory.reject |
プロセス種別のファクトリ登録 |
supervisor |
service.register、service.remove、service.update、service.start、service.stop |
サービスライフサイクル |
レジストリ
エントリ定義のバージョン管理ストレージです。
機能
- バージョン付き状態 - 各変更で新バージョンを作成
- 履歴 - 監査証跡用のSQLiteバック履歴
- イベント駆動 - 変更時にイベントをパブリッシュ
エントリライフサイクル
flowchart LR
YAML[YAML Files] --> Parser
Parser --> Stages[Pipeline Stages]
Stages --> Registry
Registry --> Validation
Validation --> Active
パイプラインステージはエントリを変換します。
| ステージ | 目的 |
|---|---|
| Override | 設定の override を適用 |
| 無効化 | パターンでエントリを除外 |
| Link | requirement と dependency を解決 |
| Bytecode | Lua を bytecode へコンパイル |
| EmbedFS | ファイルシステムエントリを収集 |
Relay
ノードをまたいだプロセス間のメッセージルーティングです。
3 段階のルーティング
flowchart LR
subgraph Router
Local[Local Node] --> Peer[Registered Peers]
Peer --> Inter[Internode]
end
Local -.- L[このノード]
Peer -.- P[登録済みピアレシーバー]
Inter -.- I[クラスター内の他ノード]
- ローカル - 同一ノード内での直接配信
- ピア - そのノードIDに対して登録されたレシーバー(Temporalワーカーなどの外部ピア)へ配信
- インターノード - ブート後にクラスターコンポーネントがインストールするクラスターのインターノードトランスポートへフォールバック
Mailbox
各ノードはワーカープールを持つ mailbox を備えます。
- FNV-1a hashing により送信元をワーカーへ割り当て
- 送信元ごとのメッセージ順序を維持
- ワーカーがメッセージを並行処理
- キューが満杯になると back-pressure
AppContext
コンポーネント参照用の sealed dictionary です。
| プロパティ | 動作 |
|---|---|
| seal 前 | ブート中のシングルスレッド書き込み |
| seal 後 | ロックフリー読み取り、書き込み時に panic |
| キーの重複 | Panic |
| 型安全性 | 型付き getter 関数 |
コンポーネントは Load フェーズ中にサービスを attach します。ブート完了後、AppContext は seal され、ロックフリー読み取りが可能になり、それ以上の書き込みは禁止されます。
シャットダウン
graceful shutdown は依存関係の逆順で進みます。
- SIGINT/SIGTERM がシャットダウンを開始
- Supervisor が管理対象サービスを停止
Stopperインターフェースを持つコンポーネントがStop()を受信- インフラストラクチャをクリーンアップ
2 回目のシグナルで即時終了します。
関連項目
- スケジューラ - プロセスの実行
- イベントバス - pub/sub システム
- レジストリ - 状態管理
- コマンドディスパッチ - yield の処理