63
63
from bittensor .utils import networking
64
64
65
65
66
+ """
67
+ The quantum of time to sleep in waiting loops, in seconds.
68
+ """
69
+ TIME_SLEEP_INTERVAL : float = 1e-3
70
+
71
+
66
72
class FastAPIThreadedServer (uvicorn .Server ):
67
73
"""
68
74
The ``FastAPIThreadedServer`` class is a specialized server implementation for the Axon server in the Bittensor network.
@@ -109,27 +115,36 @@ class FastAPIThreadedServer(uvicorn.Server):
109
115
_thread : threading .Thread = None
110
116
_started : bool = False
111
117
112
- def set_exception (self , ex ):
118
+ def set_exception (self , exception : Exception ) -> None :
119
+ """
120
+ Set self._exception in a thread safe manner, so the worker thread can communicate exceptions to the main thread.
121
+ """
113
122
with self ._lock :
114
- self ._exception = ex
123
+ self ._exception = exception
115
124
116
- def get_exception (self ):
125
+ def get_exception (self ) -> Optional [ Exception ] :
117
126
with self ._lock :
118
127
return self ._exception
119
128
120
- def set_thread (self , thread ):
129
+ def set_thread (self , thread : threading .Thread ):
130
+ """
131
+ Set self._thread in a thread safe manner, so the main thread can get the worker thread object.
132
+ """
121
133
with self ._lock :
122
134
self ._thread = thread
123
135
124
- def get_thread (self ):
136
+ def get_thread (self ) -> Optional [ threading . Thread ] :
125
137
with self ._lock :
126
138
return self ._thread
127
139
128
- def set_started (self , started ):
140
+ def set_started (self , started : bool ) -> None :
141
+ """
142
+ Set self._started in a thread safe manner, so the main thread can get the worker thread status.
143
+ """
129
144
with self ._lock :
130
145
self ._started = started
131
146
132
- def get_started (self ):
147
+ def get_started (self ) -> bool :
133
148
with self ._lock :
134
149
return self ._started
135
150
@@ -143,9 +158,8 @@ async def startup(self, sockets: Optional[List[socket.socket]] = None) -> None:
143
158
"""
144
159
Adds a thread-safe call to set a 'started' flag on the object.
145
160
"""
146
- ret = await super ().startup (sockets )
161
+ await super ().startup (sockets )
147
162
self .set_started (True )
148
- return ret
149
163
150
164
@contextlib .contextmanager
151
165
def run_in_thread (self ):
@@ -161,9 +175,9 @@ def run_in_thread(self):
161
175
thread = threading .Thread (target = self .run , daemon = True )
162
176
thread .start ()
163
177
try :
164
- t0 = time .time ()
165
- while not self .get_started () and time .time ()- t0 < 1 :
166
- time .sleep (1e-3 )
178
+ time_start = time .time ()
179
+ while not self .get_started () and time .time () - time_start < 1 :
180
+ time .sleep (TIME_SLEEP_INTERVAL )
167
181
if not self .get_started ():
168
182
raise Exception ("failed to start server" )
169
183
yield thread
@@ -181,7 +195,7 @@ def _wrapper_run(self):
181
195
while not self .should_exit :
182
196
if not thread .is_alive ():
183
197
raise Exception ("worker thread died" )
184
- time .sleep (1e-3 )
198
+ time .sleep (TIME_SLEEP_INTERVAL )
185
199
except Exception as e :
186
200
self .set_exception (e )
187
201
@@ -458,23 +472,25 @@ def info(self) -> "bittensor.AxonInfo":
458
472
placeholder2 = 0 ,
459
473
)
460
474
461
- # Our instantiator should be able to test axon.exception to see if any
462
- # exception occurred.
463
475
@property
464
- def exception (self ):
476
+ def exception (self ) -> Optional [Exception ]:
477
+ """
478
+ Axon objects expose exceptions that occurred internally through the .exception property.
479
+ """
465
480
# for future use: setting self._exception to signal an exception
466
- e = getattr (self ,' _exception' , None )
467
- if e :
468
- return e
481
+ exception = getattr (self , " _exception" , None )
482
+ if exception :
483
+ return exception
469
484
return self .fast_server .get_exception ()
470
485
471
- # Our instantiator should be able to test axon.is_running() to see if all
472
- # required threads etc are running.
473
- def is_running (self ):
474
- t = self .fast_server .get_thread ()
475
- if t is None :
486
+ def is_running (self ) -> bool :
487
+ """
488
+ Axon objects can be queried using .is_running() to test whether worker threads are running.
489
+ """
490
+ thread = self .fast_server .get_thread ()
491
+ if thread is None :
476
492
return False
477
- return t .is_alive ()
493
+ return thread .is_alive ()
478
494
479
495
def attach (
480
496
self ,
0 commit comments