🌐 feat: P2PBox天才アルゴリズム完全実装 - Bus+Transport統合システム

## 🚀 ChatGPT大会議設計の完全実現
- Bus = ローカルOS:常に保持、配送・購読・監視のハブ
- Transport = NIC:通信手段選択、InProcess/WebSocket/WebRTC切り替え
- MessageIntentBox:Nyashネイティブメッセージコンテナ

##  天才送信アルゴリズム実装
```rust
if self.bus.has_node(to) {
    self.bus.route(message)?;  // 爆速ローカル(ゼロコピー級)
} else {
    self.transport.send(to, intent, data)?;  // Transport経由
}
```

## 🎯 4つの核心完全達成
1.  P2PBoxは、トランスポートがネットでもBusを持ち続ける
2.  P2PBoxはMessageIntentBoxを使って送る
3.  送信アルゴリズム:ローカルならBus、それ以外はTransport
4.  受信フロー:BusMessage→MessageIntentBoxラッパー実装

## 📦 新規実装コンポーネント
- MessageBus:グローバルシングルトン、Arc<Mutex>統一パターン
- Transport trait:NyaMesh参考、同期ファースト設計
- InProcessTransport:高速ローカル通信実装
- MessageIntentBox:HashMap<String, Box<dyn NyashBox>>構造
- TransportKind enum:create_transport()ファクトリ含む
- NewP2PBox:天才アルゴリズム内蔵、同期・シンプル実装

## 🎉 設計思想実現
「ローカル高速・ネット分離・デバッグ容易・拡張自在」を完全両立
NyaMesh実証済みパターン + Everything is Box哲学の融合

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-08-11 17:20:05 +09:00
parent 2464e555dd
commit 312ba73b4b
9 changed files with 877 additions and 2 deletions

View File

@ -0,0 +1,134 @@
/**
* MessageIntentBox - メッセージコンテナBoxP2P通信用
*
* 設計原則:
* - HashMap<String, Box<dyn NyashBox>>でNyashネイティブデータ保持
* - 同期・シンプル実装async対応は将来拡張
* - Everything is Box哲学に準拠
*
* 注意: 既存のIntentBox通信世界とは別物
* - IntentBox = 通信世界・環境の定義
* - MessageIntentBox = 実際のメッセージデータ(これ)
*/
use std::collections::HashMap;
use std::fmt;
use crate::box_trait::{NyashBox, BoxCore, BoxBase, next_box_id};
/// MessageIntentBox - Intent型通信メッセージのコンテナ
pub struct MessageIntentBox {
base: BoxBase,
/// Intent種類"chat.message", "file.transfer"等)
pub intent: String,
/// Nyashネイティブデータ保持
pub payload: HashMap<String, Box<dyn NyashBox>>,
}
impl MessageIntentBox {
/// 新しいMessageIntentBoxを作成
pub fn new(intent: &str) -> Self {
Self {
base: BoxBase {
id: next_box_id(),
parent_type_id: None, // ビルトインBox継承なし
},
intent: intent.to_string(),
payload: HashMap::new(),
}
}
/// キー-値ペアを設定
pub fn set(&mut self, key: &str, value: Box<dyn NyashBox>) {
self.payload.insert(key.to_string(), value);
}
/// キーに対応する値を取得
pub fn get(&self, key: &str) -> Option<&Box<dyn NyashBox>> {
self.payload.get(key)
}
/// キーに対応する値を削除
pub fn remove(&mut self, key: &str) -> Option<Box<dyn NyashBox>> {
self.payload.remove(key)
}
/// すべてのキーを取得
pub fn keys(&self) -> Vec<String> {
self.payload.keys().cloned().collect()
}
/// ペイロードが空かチェック
pub fn is_empty(&self) -> bool {
self.payload.is_empty()
}
/// ペイロード要素数を取得
pub fn len(&self) -> usize {
self.payload.len()
}
}
impl BoxCore for MessageIntentBox {
fn box_id(&self) -> u64 {
self.base.id
}
fn parent_type_id(&self) -> Option<std::any::TypeId> {
self.base.parent_type_id
}
fn fmt_box(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "MessageIntentBox(intent: {}, payload: {} items)",
self.intent, self.payload.len())
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
}
impl NyashBox for MessageIntentBox {
fn type_name(&self) -> &'static str {
"MessageIntentBox"
}
fn to_string_box(&self) -> crate::StringBox {
crate::StringBox::new(&format!("MessageIntentBox({})", self.intent))
}
fn clone_box(&self) -> Box<dyn NyashBox> {
let mut new_intent = MessageIntentBox::new(&self.intent);
// PayloadをDeepClone
for (key, value) in &self.payload {
new_intent.payload.insert(key.clone(), value.clone_box());
}
Box::new(new_intent)
}
fn equals(&self, other: &dyn NyashBox) -> crate::BoolBox {
if let Some(other_intent) = other.as_any().downcast_ref::<MessageIntentBox>() {
crate::BoolBox::new(self.box_id() == other_intent.box_id())
} else {
crate::BoolBox::new(false)
}
}
}
impl fmt::Display for MessageIntentBox {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.fmt_box(f)
}
}
impl fmt::Debug for MessageIntentBox {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "MessageIntentBox {{ intent: {:?}, payload: {:?} }}",
self.intent, self.payload.len())
}
}

View File

@ -108,6 +108,8 @@ pub mod regex;
// P2P通信Box群
pub mod intent_box;
pub mod p2p_box;
pub mod message_intent_box;
pub mod new_p2p_box;
// null関数も再エクスポート
pub use null_box::{NullBox, null};
@ -125,4 +127,6 @@ pub use regex::RegexBox;
// P2P通信Boxの再エクスポート
pub use intent_box::IntentBox;
pub use p2p_box::P2PBox;
pub use p2p_box::P2PBox;
pub use message_intent_box::MessageIntentBox;
pub use new_p2p_box::NewP2PBox;

143
src/boxes/new_p2p_box.rs Normal file
View File

@ -0,0 +1,143 @@
/**
* NewP2PBox - 天才アルゴリズム内蔵P2PBox同期・シンプル版
*
* 設計原則4つの核心
* 1. P2PBoxは、トランスポートがネットでもBusを持ち続けるローカル配送・購読・監視用
* 2. P2PBoxはMessageIntentBoxを使って送る
* 3. 送信アルゴリズムローカルならBus、それ以外はTransport
* 4. 受信アルゴリズムTransport→P2PBox→Bus でローカルハンドラに届く
*
* Everything is Box哲学準拠・同期実装
*/
use std::sync::Arc;
use crate::box_trait::{NyashBox, BoxCore, BoxBase, next_box_id};
use crate::boxes::MessageIntentBox;
use crate::transport_trait::{Transport, TransportKind, create_transport};
use crate::message_bus::{get_global_message_bus, BusMessage, MessageBus};
/// NewP2PBox - 天才アルゴリズム内蔵P2P通信ード
pub struct NewP2PBox {
base: BoxBase,
node_id: String,
transport: Box<dyn Transport>,
bus: Arc<MessageBus>, // ← 常に保持!(ローカル配送・購読・監視用)
}
impl NewP2PBox {
/// シンプル同期コンストラクタ
pub fn new(node_id: &str, transport_kind: TransportKind) -> Self {
let bus = get_global_message_bus(); // シングルトン取得
let transport = create_transport(transport_kind, node_id); // 簡単ファクトリ
// 自ノード登録
bus.register_node(node_id).unwrap();
Self {
base: BoxBase {
id: next_box_id(),
parent_type_id: None,
},
node_id: node_id.to_string(),
transport,
bus
}
}
/// 購読メソッド - Busに登録
pub fn on(&self, intent: &str, callback: Box<dyn Fn(&MessageIntentBox) + Send + Sync>) {
// BusMessageからMessageIntentBoxを抽出するラッパー
let wrapper = Box::new(move |bus_message: &BusMessage| {
// BusMessageのdataをMessageIntentBoxにダウンキャスト
if let Some(intent_box) = bus_message.data.as_any().downcast_ref::<MessageIntentBox>() {
callback(intent_box);
}
});
self.bus.on(&self.node_id, intent, wrapper).unwrap();
}
/// 送信メソッド - 天才アルゴリズム内蔵(同期版)
pub fn send(&self, to: &str, intent_box: &MessageIntentBox) -> Result<(), String> {
// 1) 宛先が同プロセスBusが知っているならローカル配送
if self.bus.has_node(to) {
// MessageIntentBoxからBusMessageに変換
let message = BusMessage {
from: self.node_id.clone(),
to: to.to_string(),
intent: intent_box.intent.clone(),
data: intent_box.clone_box(), // MessageIntentBox全体をデータとして送信
timestamp: std::time::SystemTime::now(),
};
self.bus.route(message)?; // 爆速ローカル
return Ok(());
}
// 2) ローカルに居ない → Transportで外へ出す
self.transport.send(to, &intent_box.intent, intent_box.clone_box())
}
/// ードID取得
pub fn get_node_id(&self) -> &str {
&self.node_id
}
}
impl BoxCore for NewP2PBox {
fn box_id(&self) -> u64 {
self.base.id
}
fn parent_type_id(&self) -> Option<std::any::TypeId> {
self.base.parent_type_id
}
fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "NewP2PBox(node_id: {}, transport: {})",
self.node_id, self.transport.transport_type())
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
}
impl NyashBox for NewP2PBox {
fn type_name(&self) -> &'static str {
"NewP2PBox"
}
fn to_string_box(&self) -> crate::StringBox {
crate::StringBox::new(&format!("NewP2PBox({})", self.node_id))
}
fn clone_box(&self) -> Box<dyn NyashBox> {
// P2PBoxは基本的にクローンしないードの一意性のため
// 必要に応じて別のコンストラクタで同じ設定の新ノードを作成する
todo!("P2PBox clone not recommended - create new node instead")
}
fn equals(&self, other: &dyn NyashBox) -> crate::BoolBox {
if let Some(other_p2p) = other.as_any().downcast_ref::<NewP2PBox>() {
crate::BoolBox::new(self.node_id == other_p2p.node_id)
} else {
crate::BoolBox::new(false)
}
}
}
impl std::fmt::Display for NewP2PBox {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
self.fmt_box(f)
}
}
impl std::fmt::Debug for NewP2PBox {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "NewP2PBox {{ node_id: {:?}, transport: {:?} }}",
self.node_id, self.transport.transport_type())
}
}