1- from typing import Any , Callable
1+ from dataclasses import dataclass
2+ from enum import Enum
3+ from typing import Any , Protocol
24
35from context_logger import get_logger
46
79log = get_logger ('Discoverer' )
810
911
12+ class DiscoveryEventType (Enum ):
13+ DISCOVERED = 'discovered'
14+ UPDATED = 'updated'
15+
16+
17+ @dataclass
18+ class DiscoveryEvent :
19+ service : ServiceInfo
20+ type : DiscoveryEventType
21+
22+
23+ class OnDiscoveryEvent (Protocol ):
24+ def __call__ (self , event : DiscoveryEvent ) -> None : ...
25+
26+
1027class Discoverer :
1128
1229 def start (self , address : str , group : Group , query : ServiceQuery | None = None ) -> None :
@@ -21,10 +38,10 @@ def discover(self, query: ServiceQuery | None = None) -> None:
2138 def get_services (self ) -> dict [str , ServiceInfo ]:
2239 raise NotImplementedError ()
2340
24- def register (self , callback : Callable [[ Any ], None ] ) -> None :
41+ def register (self , callback : OnDiscoveryEvent ) -> None :
2542 raise NotImplementedError ()
2643
27- def deregister (self , callback : Callable [[ Any ], None ] ) -> None :
44+ def deregister (self , callback : OnDiscoveryEvent ) -> None :
2845 raise NotImplementedError ()
2946
3047
@@ -36,7 +53,7 @@ def __init__(self, sender: Sender, receiver: Receiver) -> None:
3653 self ._group : Group | None = None
3754 self ._matcher : ServiceMatcher | None = None
3855 self ._services : dict [str , ServiceInfo ] = {}
39- self ._callbacks : list [Callable [[ ServiceInfo ], None ] ] = []
56+ self ._callbacks : list [OnDiscoveryEvent ] = []
4057
4158 def __enter__ (self ) -> Discoverer :
4259 return self
@@ -65,24 +82,24 @@ def discover(self, query: ServiceQuery | None = None) -> None:
6582 self ._sender .send (self ._matcher .query )
6683 log .info ('Service discovery initiated' , query = self ._matcher .query , group = self ._group )
6784 else :
68- log .warning ('Cannot initiate service discovery , discoverer not started' , query = query )
85+ log .warning ('Cannot discover services , discoverer not started' , query = query )
6986
7087 def get_services (self ) -> dict [str , ServiceInfo ]:
7188 return self ._services .copy ()
7289
73- def register (self , callback : Callable [[ Any ], None ] ) -> None :
90+ def register (self , callback : OnDiscoveryEvent ) -> None :
7491 self ._callbacks .append (callback )
7592
76- def deregister (self , callback : Callable [[ Any ], None ] ) -> None :
93+ def deregister (self , callback : OnDiscoveryEvent ) -> None :
7794 self ._callbacks .remove (callback )
7895
79- def _handle_message (self , data : dict [str , Any ]) -> None :
96+ def _handle_message (self , message : dict [str , Any ]) -> None :
8097 service : ServiceInfo | None = None
8198
8299 try :
83- service = ServiceInfo (** data )
100+ service = ServiceInfo (** message )
84101 except Exception as error :
85- log .warn ('Failed to handle received message' , data = data , error = error )
102+ log .warn ('Failed to handle received message' , data = message , error = error )
86103
87104 if service :
88105 self ._handle_service (service )
@@ -91,29 +108,25 @@ def _handle_service(self, service: ServiceInfo) -> None:
91108 if self ._matcher and self ._matcher .matches (service ):
92109 cached = self ._services .get (service .name )
93110
94- if self ._is_update_needed (cached , service ):
95- self ._services [service .name ] = service
96- for callback in self ._callbacks :
97- try :
98- callback (service )
99- except Exception as error :
100- log .warn ('Error in callback execution' , service = service , error = error )
111+ if event := self ._create_event (cached , service ):
112+ self ._handle_event (event )
101113
102- def _is_update_needed (self , cached : ServiceInfo | None , service : ServiceInfo ) -> bool :
114+ def _create_event (self , cached : ServiceInfo | None , service : ServiceInfo ) -> DiscoveryEvent | None :
103115 if cached :
104116 if cached != service :
105117 log .info ('Service updated' , old_service = cached , new_service = service )
106- return True
118+ return DiscoveryEvent ( service , DiscoveryEventType . UPDATED )
107119 else :
108120 log .info ('Service discovered' , service = service )
109- return True
121+ return DiscoveryEvent ( service , DiscoveryEventType . DISCOVERED )
110122
111- return False
123+ return None
112124
113- def _handle_update (self , service : ServiceInfo ) -> None :
125+ def _handle_event (self , event : DiscoveryEvent ) -> None :
126+ service = event .service
114127 self ._services [service .name ] = service
115128 for callback in self ._callbacks :
116129 try :
117- callback (service )
130+ callback (event )
118131 except Exception as error :
119132 log .warn ('Error in callback execution' , service = service , error = error )
0 commit comments