99WEATHER_CACHE_TTL = 600
1010GEOCODING_CACHE_TTL = 3600
1111
12- # Redis Connection
13- redis_url = os .getenv ("REDIS_URL" , "redis://localhost:6379/0" )
14- try :
15- redis_client = redis .from_url (redis_url , decode_responses = True )
16- # Test connection
17- redis_client .ping ()
18- logger .info (f"Connected to Redis at { redis_url } " )
19- except Exception as e :
20- logger .warning (f"Failed to connect to Redis: { e } . Fallback to in-memory cache." )
21- redis_client = None
12+ # Redis Connection Setup
13+ # We do NOT connect or ping here to avoid startup crashes in Serverless environments
14+ # if the Redis URL is invalid or unreachable (e.g. localhost in Vercel).
15+
16+ redis_url = os .getenv ("REDIS_URL" , "" )
17+ redis_client = None
18+
19+ # Determine if we should attempt Redis connection
20+ # In Vercel, if REDIS_URL is missing or is localhost, we skip directly to memory cache
21+ should_use_redis = bool (redis_url and "localhost" not in redis_url )
22+
23+ if os .getenv ("IS_DOCKER" ) or os .getenv ("IS_LOCAL" ):
24+ # Force attempt if explicitly in Docker/Local dev, even if localhost
25+ should_use_redis = bool (redis_url )
26+
27+ if should_use_redis :
28+ try :
29+ # Create client but don't ping immediately (lazy connection)
30+ # Socket timeout is critical to avoid hanging the serverless function
31+ redis_client = redis .from_url (
32+ redis_url ,
33+ decode_responses = True ,
34+ socket_timeout = 2.0 ,
35+ socket_connect_timeout = 2.0
36+ )
37+ logger .info (f"Redis client configured for { redis_url } " )
38+ except Exception as e :
39+ logger .warning (f"Failed to configure Redis client: { e } . Using in-memory cache." )
40+ redis_client = None
41+ else :
42+ logger .info ("Redis disabled or invalid URL. Using in-memory cache." )
2243
2344# In-memory fallback
2445_memory_cache = {}
@@ -30,6 +51,7 @@ def _get_from_redis(key: str) -> Optional[Any]:
3051 val = redis_client .get (key )
3152 return json .loads (val ) if val else None
3253 except Exception as e :
54+ # If Redis fails during operation, log and fallback to memory (optional, currently just returns None)
3355 logger .error (f"Redis get error: { e } " )
3456 return None
3557
@@ -41,6 +63,8 @@ def _set_in_redis(key: str, value: Any, ttl: int) -> None:
4163 redis_client .setex (key , ttl , json .dumps (value ))
4264 except Exception as e :
4365 logger .error (f"Redis set error: { e } " )
66+ # Fallback to memory on write failure
67+ _memory_cache [key ] = value
4468
4569def get_geocoding_cache (key : str ) -> Optional [List [City ]]:
4670 """Get cached geocoding results"""
0 commit comments