11from collections .abc import Mapping , Sequence
22from dataclasses import dataclass
3- from time import time
43from typing import Optional , Self , cast
54from uuid import UUID
65
@@ -130,9 +129,20 @@ def _get_route_health_key(self, route_id: str) -> str:
130129 """
131130 return f"route:health:{ route_id } "
132131
133- def _is_health_status_valid (self , status : str , timestamp_str : str ) -> bool :
132+ async def _get_redis_time (self ) -> int :
134133 """
135- Check if health status is healthy and timestamp is not stale.
134+ Get current Unix timestamp from Redis server using TIME command.
135+ This ensures consistent timestamps across distributed systems.
136+
137+ :return: Current Unix timestamp in seconds
138+ """
139+ result = await self ._client .client .time ()
140+ seconds_bytes , _ = result
141+ return int (seconds_bytes )
142+
143+ async def _validate_health_status (self , status : str , timestamp_str : str ) -> bool :
144+ """
145+ Validate health status by checking if it's healthy and timestamp is not stale.
136146
137147 :param status: The status string ("1" for healthy, "0" for unhealthy)
138148 :param timestamp_str: The timestamp string value from Redis
@@ -142,7 +152,7 @@ def _is_health_status_valid(self, status: str, timestamp_str: str) -> bool:
142152 return False
143153 try :
144154 timestamp = int (timestamp_str )
145- current_time = int ( time () )
155+ current_time = await self . _get_redis_time ( )
146156 return (current_time - timestamp ) <= MAX_HEALTH_STALENESS_SEC
147157 except (ValueError , TypeError ):
148158 return False
@@ -323,10 +333,10 @@ async def get_route_health_status(self, route_id: str) -> Optional[HealthStatus]
323333 data = {k .decode (): v .decode () for k , v in result .items ()}
324334
325335 # Parse boolean values using validation helper (checks both status and staleness)
326- readiness = self ._is_health_status_valid (
336+ readiness = await self ._validate_health_status (
327337 data .get ("readiness" , "0" ), data .get ("last_readiness" , "0" )
328338 )
329- liveness = self ._is_health_status_valid (
339+ liveness = await self ._validate_health_status (
330340 data .get ("liveness" , "0" ), data .get ("last_liveness" , "0" )
331341 )
332342 last_check = int (data ["last_check" ]) if "last_check" in data else 0
@@ -345,7 +355,7 @@ async def initialize_routes_health_status_batch(self, route_ids: list[str]) -> N
345355 if not route_ids :
346356 return
347357
348- current_time = str (int ( time () ))
358+ current_time = str (await self . _get_redis_time ( ))
349359 batch = Batch (is_atomic = False )
350360
351361 for route_id in route_ids :
@@ -373,7 +383,7 @@ async def update_route_readiness(self, route_id: str, readiness: bool) -> None:
373383 key = self ._get_route_health_key (route_id )
374384 data : Mapping [str | bytes , str | bytes ] = {
375385 "readiness" : "1" if readiness else "0" ,
376- "last_readiness" : str (int ( time () )),
386+ "last_readiness" : str (await self . _get_redis_time ( )),
377387 }
378388
379389 batch = Batch (is_atomic = False )
@@ -393,7 +403,7 @@ async def update_route_liveness(self, route_id: str, liveness: bool) -> None:
393403 key = self ._get_route_health_key (route_id )
394404 data : Mapping [str | bytes , str | bytes ] = {
395405 "liveness" : "1" if liveness else "0" ,
396- "last_liveness" : str (int ( time () )),
406+ "last_liveness" : str (await self . _get_redis_time ( )),
397407 }
398408
399409 batch = Batch (is_atomic = False )
@@ -415,7 +425,7 @@ async def check_route_health_status(
415425 if not route_ids :
416426 return {}
417427
418- current_time = str (int ( time () ))
428+ current_time = str (await self . _get_redis_time ( ))
419429 batch = Batch (is_atomic = False )
420430
421431 # Single batch: update last_check, refresh TTL, and get all data
@@ -447,13 +457,15 @@ async def check_route_health_status(
447457 # Parse existing data
448458 data = {k .decode (): v .decode () for k , v in result .items ()}
449459 # Parse boolean values using validation helper (checks both status and staleness)
460+ readiness = await self ._validate_health_status (
461+ data .get ("readiness" , "0" ), data .get ("last_readiness" , "0" )
462+ )
463+ liveness = await self ._validate_health_status (
464+ data .get ("liveness" , "0" ), data .get ("last_liveness" , "0" )
465+ )
450466 health_statuses [route_id ] = HealthStatus (
451- readiness = self ._is_health_status_valid (
452- data .get ("readiness" , "0" ), data .get ("last_readiness" , "0" )
453- ),
454- liveness = self ._is_health_status_valid (
455- data .get ("liveness" , "0" ), data .get ("last_liveness" , "0" )
456- ),
467+ readiness = readiness ,
468+ liveness = liveness ,
457469 last_check = int (data ["last_check" ]) if "last_check" in data else 0 ,
458470 )
459471
@@ -470,7 +482,7 @@ async def update_routes_readiness_batch(self, route_readiness: Mapping[str, bool
470482 if not route_readiness :
471483 return
472484
473- current_time = str (int ( time () ))
485+ current_time = str (await self . _get_redis_time ( ))
474486 batch = Batch (is_atomic = False )
475487 for route_id , readiness in route_readiness .items ():
476488 key = self ._get_route_health_key (route_id )
0 commit comments