@@ -18,15 +18,28 @@ use crate::entity::web::link::Link;
1818use crate :: entity:: web:: web_metadata:: WebMetadata ;
1919use crate :: entity:: web:: web_page:: WebPage ;
2020use crate :: error:: PiResult ;
21- use crate :: { ExternalData , FetchError , FetchResponse } ;
21+ use crate :: { ExternalData , FetchError , FetchRequest , FetchResponse } ;
2222use chrono:: { DateTime , Utc } ;
2323use serde:: { Deserialize , Serialize } ;
24+ use std:: any:: Any ;
2425use std:: cmp:: Ordering ;
2526use std:: sync:: Arc ;
2627use strum:: { Display , EnumString } ;
2728use ts_rs:: TS ;
2829use utoipa:: ToSchema ;
2930
31+ pub trait Node : Send + Sync {
32+ fn process ( & self , node_id : NodeId , engine : Arc < & Engine > ) -> PiResult < ( ) > ;
33+ fn as_any ( & self ) -> & dyn Any ;
34+ fn get_labels ( & self ) -> Vec < NodeLabel > ;
35+ }
36+
37+ pub trait Fetchable : Node {
38+ fn make_fetch_requests ( & self , node_id : NodeId , engine : Arc < & Engine > ) -> PiResult < Vec < FetchRequest > > ;
39+ fn handle_fetch_response ( & self , node_id : NodeId , engine : Arc < & Engine > , response : FetchResponse ) -> PiResult < ( ) > ;
40+ fn handle_fetch_error ( & self , node_id : NodeId , engine : Arc < & Engine > , error : FetchError ) -> PiResult < ( ) > ;
41+ }
42+
3043#[ derive( Clone , Display , Deserialize , Serialize ) ]
3144pub enum Payload {
3245 Link ( Link ) ,
@@ -112,6 +125,118 @@ pub struct NodeItem {
112125 pub written_at : DateTime < Utc > ,
113126}
114127
128+ pub struct TypedNodeItem < T : Node > {
129+ pub id : NodeId ,
130+ pub node : T ,
131+ pub flags : NodeFlags ,
132+ pub written_at : DateTime < Utc > ,
133+ }
134+
135+ impl < T : Node > TypedNodeItem < T > {
136+ pub fn new ( id : NodeId , node : T ) -> Self {
137+ Self {
138+ id,
139+ node,
140+ flags : NodeFlags :: empty ( ) ,
141+ written_at : Utc :: now ( ) ,
142+ }
143+ }
144+
145+ pub fn process ( & self , engine : Arc < & Engine > ) -> PiResult < ( ) > {
146+ self . node . process ( self . id , engine)
147+ }
148+
149+ pub fn make_fetch_requests ( & self , engine : Arc < & Engine > ) -> PiResult < Vec < FetchRequest > >
150+ where
151+ T : Fetchable
152+ {
153+ self . node . make_fetch_requests ( self . id , engine)
154+ }
155+
156+ pub fn handle_fetch_response ( & self , engine : Arc < & Engine > , response : FetchResponse ) -> PiResult < ( ) >
157+ where
158+ T : Fetchable
159+ {
160+ self . node . handle_fetch_response ( self . id , engine, response)
161+ }
162+
163+ pub fn handle_fetch_error ( & self , engine : Arc < & Engine > , error : FetchError ) -> PiResult < ( ) >
164+ where
165+ T : Fetchable
166+ {
167+ self . node . handle_fetch_error ( self . id , engine, error)
168+ }
169+
170+ pub fn get_labels ( & self ) -> Vec < NodeLabel > {
171+ self . node . get_labels ( )
172+ }
173+
174+ pub fn get_node ( & self ) -> & T {
175+ & self . node
176+ }
177+
178+ pub fn get_node_mut ( & mut self ) -> & mut T {
179+ & mut self . node
180+ }
181+ }
182+
183+ pub enum AnyTypedNode {
184+ Domain ( TypedNodeItem < crate :: entity:: web:: domain:: Domain > ) ,
185+ // Link(TypedNodeItem<crate::entity::web::link::Link>),
186+ // WebPage(TypedNodeItem<crate::entity::web::web_page::WebPage>),
187+ // Add more as you implement them
188+ }
189+
190+ impl AnyTypedNode {
191+ pub fn process ( & self , engine : Arc < & Engine > ) -> PiResult < ( ) > {
192+ match self {
193+ AnyTypedNode :: Domain ( node) => node. process ( engine) ,
194+ // AnyTypedNode::Link(node) => node.process(engine),
195+ // AnyTypedNode::WebPage(node) => node.process(engine),
196+ }
197+ }
198+
199+ pub fn handle_fetch_response ( & self , engine : Arc < & Engine > , response : FetchResponse ) -> PiResult < ( ) > {
200+ match self {
201+ AnyTypedNode :: Domain ( node) => node. handle_fetch_response ( engine, response) ,
202+ }
203+ }
204+
205+ pub fn handle_fetch_error ( & self , engine : Arc < & Engine > , error : FetchError ) -> PiResult < ( ) > {
206+ match self {
207+ AnyTypedNode :: Domain ( node) => node. handle_fetch_error ( engine, error) ,
208+ }
209+ }
210+
211+ pub fn get_labels ( & self ) -> Vec < NodeLabel > {
212+ match self {
213+ AnyTypedNode :: Domain ( node) => node. get_labels ( ) ,
214+ }
215+ }
216+
217+ pub fn get_id ( & self ) -> NodeId {
218+ match self {
219+ AnyTypedNode :: Domain ( node) => node. id ,
220+ }
221+ }
222+ }
223+
224+ pub fn create_typed_node ( id : NodeId , labels : & [ NodeLabel ] , payload : & Payload ) -> Option < AnyTypedNode > {
225+ use crate :: entity:: web:: domain:: Domain ;
226+
227+ if labels. contains ( & NodeLabel :: DomainName ) {
228+ if let Payload :: Text ( domain_name) = payload {
229+ return Some ( AnyTypedNode :: Domain ( TypedNodeItem :: new ( id, Domain :: new ( domain_name. clone ( ) ) ) ) ) ;
230+ }
231+ }
232+
233+ // Add more entity types here as you implement them
234+ // if labels.contains(&NodeLabel::Link) { ... }
235+ // if labels.contains(&NodeLabel::WebPage) { ... }
236+
237+ None
238+ }
239+
115240impl NodeItem {
116241 pub ( super ) fn process ( & self , arced_engine : Arc < & Engine > ) -> PiResult < ( ) > {
117242 if self . labels . contains ( & NodeLabel :: DomainName ) {
@@ -213,12 +338,6 @@ impl NodeItem {
213338 }
214339}
215340
216- impl NodeItem {
217- pub fn get_label ( & self ) -> String {
218- self . payload . to_string ( )
219- }
220- }
221-
222341impl Ord for NodeItem {
223342 fn cmp ( & self , other : & Self ) -> Ordering {
224343 self . id . cmp ( & other. id )
0 commit comments