Phase 9.75-C: Convert HTTPServerBox, P2PBox, IntentBox to RwLock pattern
Co-authored-by: moe-charm <217100418+moe-charm@users.noreply.github.com>
This commit is contained in:
@ -40,29 +40,38 @@ use crate::boxes::IntentBox;
|
||||
use crate::transport::{Transport, InProcessTransport, TransportError};
|
||||
use crate::messaging::IntentHandler;
|
||||
use std::any::Any;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::RwLock;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// P2PBox内部データ構造
|
||||
pub struct P2PBoxData {
|
||||
/// P2PBox - P2P通信ノード (RwLock pattern)
|
||||
#[derive(Debug)]
|
||||
pub struct P2PBox {
|
||||
base: BoxBase,
|
||||
node_id: String,
|
||||
transport: Arc<Mutex<Box<dyn Transport>>>,
|
||||
node_id: RwLock<String>,
|
||||
transport: RwLock<Box<dyn Transport>>,
|
||||
handlers: RwLock<HashMap<String, Box<dyn NyashBox>>>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for P2PBoxData {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("P2PBoxData")
|
||||
.field("base", &self.base)
|
||||
.field("node_id", &self.node_id)
|
||||
.field("transport", &"<Transport>")
|
||||
.finish()
|
||||
impl Clone for P2PBox {
|
||||
fn clone(&self) -> Self {
|
||||
// State-preserving clone implementation following PR #87 pattern
|
||||
let node_id_val = self.node_id.read().unwrap().clone();
|
||||
// Note: Transport cloning is complex, for now we create a new transport
|
||||
// In a full implementation, we'd need to properly handle transport state
|
||||
let transport_kind = TransportKind::InProcess; // Default for now
|
||||
let new_transport: Box<dyn Transport> = match transport_kind {
|
||||
TransportKind::InProcess => Box::new(InProcessTransport::new(node_id_val.clone())),
|
||||
};
|
||||
let handlers_val = HashMap::new(); // Start fresh for cloned instance
|
||||
|
||||
Self {
|
||||
base: BoxBase::new(), // New unique ID for clone
|
||||
node_id: RwLock::new(node_id_val),
|
||||
transport: RwLock::new(new_transport),
|
||||
handlers: RwLock::new(handlers_val),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// P2PBox - P2P通信ノード(Arc<Mutex>統一パターン)
|
||||
pub type P2PBox = Arc<Mutex<P2PBoxData>>;
|
||||
|
||||
/// P2PBox作成時のトランスポート種類
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TransportKind {
|
||||
InProcess,
|
||||
@ -80,91 +89,105 @@ impl std::str::FromStr for TransportKind {
|
||||
}
|
||||
}
|
||||
|
||||
impl P2PBoxData {
|
||||
impl P2PBox {
|
||||
/// 新しいP2PBoxを作成
|
||||
pub fn new(node_id: String, transport_kind: TransportKind) -> P2PBox {
|
||||
pub fn new(node_id: String, transport_kind: TransportKind) -> Self {
|
||||
let transport: Box<dyn Transport> = match transport_kind {
|
||||
TransportKind::InProcess => Box::new(InProcessTransport::new(node_id.clone())),
|
||||
};
|
||||
|
||||
Arc::new(Mutex::new(P2PBoxData {
|
||||
P2PBox {
|
||||
base: BoxBase::new(),
|
||||
node_id,
|
||||
transport: Arc::new(Mutex::new(transport)),
|
||||
}))
|
||||
node_id: RwLock::new(node_id),
|
||||
transport: RwLock::new(transport),
|
||||
handlers: RwLock::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
/// ノードIDを取得
|
||||
pub fn get_node_id(&self) -> &str {
|
||||
&self.node_id
|
||||
pub fn get_node_id(&self) -> Box<dyn NyashBox> {
|
||||
let node_id = self.node_id.read().unwrap().clone();
|
||||
Box::new(StringBox::new(node_id))
|
||||
}
|
||||
|
||||
/// 特定ノードにメッセージを送信
|
||||
pub fn send(&self, to: &str, intent: IntentBox) -> Result<(), TransportError> {
|
||||
let transport = self.transport.lock().unwrap();
|
||||
transport.send(to, intent, Default::default())
|
||||
pub fn send(&self, to: Box<dyn NyashBox>, intent: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||
let to_str = to.to_string_box().value;
|
||||
|
||||
// Extract IntentBox from the generic Box
|
||||
if let Some(intent_box) = intent.as_any().downcast_ref::<IntentBox>() {
|
||||
let transport = self.transport.read().unwrap();
|
||||
match transport.send(&to_str, intent_box.clone(), Default::default()) {
|
||||
Ok(()) => Box::new(BoolBox::new(true)),
|
||||
Err(_) => Box::new(BoolBox::new(false)),
|
||||
}
|
||||
} else {
|
||||
Box::new(BoolBox::new(false))
|
||||
}
|
||||
}
|
||||
|
||||
/// イベントハンドラーを登録
|
||||
pub fn on(&self, intent_name: &str, handler: IntentHandler) -> Result<(), String> {
|
||||
// InProcessTransportの場合のハンドラー追加
|
||||
// 現在は簡略化された実装
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn on(&self, intent_name: Box<dyn NyashBox>, handler: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||
let intent_str = intent_name.to_string_box().value;
|
||||
|
||||
// For now, we'll store a simplified handler representation
|
||||
// In a full implementation, this would need proper IntentHandler integration
|
||||
let mut handlers = self.handlers.write().unwrap();
|
||||
handlers.insert(intent_str, handler);
|
||||
Box::new(BoolBox::new(true))
|
||||
/// ノードが到達可能かチェック
|
||||
pub fn is_reachable(&self, node_id: &str) -> bool {
|
||||
let transport = self.transport.lock().unwrap();
|
||||
transport.is_reachable(node_id)
|
||||
pub fn is_reachable(&self, node_id: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||
let node_str = node_id.to_string_box().value;
|
||||
let transport = self.transport.read().unwrap();
|
||||
Box::new(BoolBox::new(transport.is_reachable(&node_str)))
|
||||
}
|
||||
|
||||
/// トランスポート種類を取得
|
||||
pub fn get_transport_type(&self) -> String {
|
||||
let transport = self.transport.lock().unwrap();
|
||||
transport.transport_type().to_string()
|
||||
pub fn get_transport_type(&self) -> Box<dyn NyashBox> {
|
||||
let transport = self.transport.read().unwrap();
|
||||
Box::new(StringBox::new(transport.transport_type().to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl NyashBox for P2PBox {
|
||||
fn clone_box(&self) -> Box<dyn NyashBox> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
|
||||
fn to_string_box(&self) -> StringBox {
|
||||
let data = self.lock().unwrap();
|
||||
StringBox::new(format!("P2PBox[{}:{}]", data.node_id, data.get_transport_type()))
|
||||
let node_id = self.node_id.read().unwrap().clone();
|
||||
let transport_type = self.transport.read().unwrap().transport_type().to_string();
|
||||
StringBox::new(format!("P2PBox[{}:{}]", node_id, transport_type))
|
||||
}
|
||||
|
||||
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
|
||||
if let Some(other_p2p) = other.as_any().downcast_ref::<P2PBox>() {
|
||||
let self_data = self.lock().unwrap();
|
||||
let other_data = other_p2p.lock().unwrap();
|
||||
BoolBox::new(self_data.base.id == other_data.base.id)
|
||||
BoolBox::new(self.base.id == other_p2p.base.id)
|
||||
} else {
|
||||
BoolBox::new(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn type_name(&self) -> &'static str {
|
||||
"P2PBox"
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn NyashBox> {
|
||||
// P2PBoxは共有されるので、新しいインスタンスではなく同じ参照を返す
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl BoxCore for P2PBox {
|
||||
fn box_id(&self) -> u64 {
|
||||
self.lock().unwrap().base.id
|
||||
self.base.id
|
||||
}
|
||||
|
||||
fn parent_type_id(&self) -> Option<std::any::TypeId> {
|
||||
self.lock().unwrap().base.parent_type_id
|
||||
self.base.parent_type_id
|
||||
}
|
||||
|
||||
fn fmt_box(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let data = self.lock().unwrap();
|
||||
write!(f, "P2PBox[{}:{}]", data.node_id, data.get_transport_type())
|
||||
let node_id = self.node_id.read().unwrap().clone();
|
||||
let transport_type = self.transport.read().unwrap().transport_type().to_string();
|
||||
write!(f, "P2PBox[{}:{}]", node_id, transport_type)
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
@ -176,8 +199,8 @@ impl BoxCore for P2PBox {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for P2PBoxData {
|
||||
impl std::fmt::Display for P2PBox {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "P2PBox[{}:{}]", self.node_id, self.get_transport_type())
|
||||
self.fmt_box(f)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user