EPIC: Mesh v2 拡張機能の実装
概要
GitHub Issue #350 の実装のため、Mesh v2 拡張機能を実装します。既存のMeshと同じブロックとイベント処理を提供しつつ、バックエンドに新しいMesh v2システム(AWS AppSync + GraphQL)を使用します。
背景・目的
抽象的なクライアントである「Node」を「Group」に所属させ、リアルタイムでデータ共有とイベント通知を行うIoTバックエンドシステムを構築します。
システム要件と性能要件
基本要件
- クライアント: Node (センサー、ブラウザタブ等)
- データ共有範囲: Group 内に限定
- データ更新: 項目名と値のペア (値は文字列)
- イベント通知: 任意のイベント名で発火
- グループ管理: ホスト (作成者) の退出でグループ解散
性能要件 (ピーク時)
- 最大 40台 / グループ
- 同時稼働 10グループ
- データ更新: 15 回/秒 / グループ
- イベント通知: 2 回/秒 / グループ
- 全体書き込み負荷: 170 TPS
システムアーキテクチャ
データ構造とエンティティ
| エンティティ | 役割 | 主要フィールド |
|---|---|---|
| Group | データ共有とイベント通知のスコープ | id, name, hostId |
| Node | データを報告・受信する抽象クライアント | id, name, groupId |
| NodeStatus | Nodeが報告した最新のデータ集合 | nodeId, groupId, data |
| SensorData | 報告される単一のデータ項目 | key (マルチバイト可), value (String) |
| Event | Nodeが発火する通知ペイロード | name, firedByNodeId, payload |
GraphQL操作概要
| 操作タイプ | フィールド名 | 目的 | 実装最適化 |
|---|---|---|---|
| Mutation (高頻度) | reportDataByNode | センサーデータをグループに報告 | DynamoDB直結 (JS/VTL) で低遅延・低コスト |
| Mutation (イベント) | fireEventByNode | グループ内イベントを発火 | Noneデータソース、DB書き込み省略 |
| Mutation (管理) | createGroup, joinGroup | グループの作成と参加 | DynamoDB直結 |
| Mutation (管理) | leaveGroup | グループ退出、ホスト退出時はグループ削除 | Lambda でホスト判定ロジック |
| Subscription | onDataUpdateInGroup | データ更新をリアルタイム通知 | groupId フィルター必須 |
| Subscription | onEventInGroup | イベント発火をリアルタイム通知 | groupId フィルター必須 |
| Query | listGroupStatuses, getNodeStatus | グループやNodeの現在の状態を取得 | DynamoDB PK/SK設計で高速取得 |
GraphQL スキーマ
スキーマ定義を表示
# --- データの基本構造 --- input SensorDataInput { key: String! value: String! } type SensorData { key: String! value: String! } # --- 主要エンティティ --- type Group { id: ID! name: String! hostId: ID! createdAt: AWSDateTime! } type Node { id: ID! name: String! groupId: ID } type NodeStatus { nodeId: ID! groupId: ID! data: [SensorData!]! timestamp: AWSDateTime! } type Event { name: String! firedByNodeId: ID! groupId: ID! payload: String timestamp: AWSDateTime! } type GroupDissolvePayload { groupId: ID! message: String! } # --- クエリ (Queries) --- type Query { getGroup(groupId: ID!): Group getNodeStatus(nodeId: ID!): NodeStatus listGroupStatuses(groupId: ID!): [NodeStatus!]! listNodesInGroup(groupId: ID!): [Node!]! } # --- ミューテーション (Mutations) --- type Mutation { # グループ管理 createGroup(name: String!, hostId: ID!): Group! joinGroup(groupId: ID!, nodeId: ID!): Node! leaveGroup(groupId: ID!, nodeId: ID!): Node # データ通信 reportDataByNode( groupId: ID! nodeId: ID! data: [SensorDataInput!]! ): NodeStatus! fireEventByNode( groupId: ID! nodeId: ID! eventName: String! payload: String ): Event! } # --- サブスクリプション (Subscriptions) --- type Subscription { onDataUpdateInGroup(groupId: ID!): NodeStatus! @aws_subscribe(mutations: ["reportDataByNode"]) onEventInGroup(groupId: ID!): Event! @aws_subscribe(mutations: ["fireEventByNode"]) onGroupDissolve(groupId: ID!): GroupDissolvePayload! @aws_subscribe(mutations: ["leaveGroup"]) }
実装コンポーネント
1. gui/smalruby3-gui の修正
- Mesh v2 拡張機能ブロックの実装
- 既存のMeshブロックと同じUI/UX
- バックエンドはMesh v2システム (GraphQL) を使用
- WebSocket経由でSubscriptionを受信
2. infra/mesh-v2 (新規サブモジュール)
- AWS CDK (Ruby) でインフラ構築
- AWS AppSync GraphQL API
- DynamoDB (オンデマンド課金)
- Lambda (Ruby 3.2) - 複雑なロジック処理用
- JavaScript/VTLリゾルバー - 高頻度処理用
DynamoDBテーブル設計
| PK (Partition Key) | SK (Sort Key) | 属性 | 用途 |
|---|---|---|---|
GROUP#<groupId> |
METADATA |
hostId, name |
グループメタデータ |
GROUP#<groupId> |
NODE#<nodeId> |
name, statusData |
Node情報と状態 |
NODE#<nodeId> |
METADATA |
groupId |
Node所属グループ |
技術スタック
- フロントエンド: React (smalruby3-gui)
- バックエンドAPI: AWS AppSync (GraphQL)
- データベース: Amazon DynamoDB
- リアルタイム通信: AppSync Subscriptions (WebSocket)
- サーバーレス関数: AWS Lambda (Ruby 3.2)
- IaC: AWS CDK (Ruby)
- リゾルバー: AppSync JavaScript / VTL
実装タスク
Phase 0: 既存Mesh拡張機能の調査と分析
- Phase 0: 既存Mesh拡張機能とSkyWay API利用状況の調査 #445 既存Mesh拡張機能とSkyWay API利用状況の調査
Phase 1: インフラストラクチャ基盤
- Phase 1-1: infra/mesh-v2リポジトリのセットアップとCDK基本構成 #446 infra/mesh-v2リポジトリのセットアップとCDK基本構成
- Phase 1-2: DynamoDBテーブルの設計と実装 #447 DynamoDBテーブルの設計と実装
- Phase 1-3: AppSync GraphQL APIとスキーマの実装 #448 AppSync GraphQL APIとスキーマの実装
Phase 2: バックエンドロジック
- Phase 2-1: グループ管理Mutationの実装 #449 グループ管理Mutationの実装 (createGroup, joinGroup)
- Phase 2-2: 高頻度Mutationリゾルバーの実装 #450 高頻度Mutationリゾルバーの実装 (reportDataByNode, fireEventByNode)
- Phase 2-3: Lambda関数の実装 (leaveGroupロジック) #451 Lambda関数の実装 (leaveGroupロジック - ホスト判定とグループ解散)
- Phase 2-4: Subscriptionの実装とテスト #452 Subscriptionの実装とテスト
Phase 3: フロントエンド
- Phase 3: Mesh v2拡張機能ブロックの実装 #453 Mesh v2拡張機能ブロックの実装
Phase 4: テストとドキュメント
- Phase 4-1: 統合テストと負荷テスト #454 統合テストと負荷テスト (170 TPS要件の検証)
- Phase 4-2: ドキュメントとデプロイ手順書 #455 ドキュメントとデプロイ手順書
参考資料
- 関連Issue: Support the alternative API of the Mesh extension #350
- AWS AppSync ドキュメント: https://docs.aws.amazon.com/appsync/
- AWS CDK Ruby ドキュメント: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html
🤖 Generated with Claude Code
Co-Authored-By: Claude noreply@anthropic.com