@@ -2074,7 +2074,9 @@ async def get_data( # noqa: PLR0915
2074
2074
elif table_name == "enduser" and budget_id_list is not None :
2075
2075
if query_type == "find_all" :
2076
2076
response = await self .db .litellm_endusertable .find_many (
2077
- where = {"budget_id" : {"in" : budget_id_list }}
2077
+ where = {"budget_id" : {"in" : budget_id_list }},
2078
+ order = {"litellm_budget_table" : {"created_at" : "desc" }},
2079
+ include = {"litellm_budget_table" : True }
2078
2080
)
2079
2081
return response
2080
2082
elif table_name == "team" :
@@ -3025,6 +3027,79 @@ async def _cache_user_row(user_id: str, cache: DualCache, db: PrismaClient):
3025
3027
return
3026
3028
3027
3029
3030
+ async def preload_users_into_cache (
3031
+ prisma_client : PrismaClient ,
3032
+ user_api_key_cache : DualCache ,
3033
+ limit : int = 1000 ,
3034
+ ) -> Dict [str , Any ]:
3035
+ """
3036
+ Pre-load users from database into cache on startup.
3037
+
3038
+ Args:
3039
+ prisma_client: Database client
3040
+ user_api_key_cache: Cache instance to store users
3041
+ limit: Maximum number of users to pre-load (must be > 0 and <= 10000)
3042
+ Returns:
3043
+ Dict with preload statistics
3044
+ """
3045
+ try :
3046
+ verbose_proxy_logger .info (f"Starting user preload: limit={ limit } " )
3047
+ users = await prisma_client .db .litellm_endusertable .find_many (
3048
+ take = limit ,
3049
+ order = {"litellm_budget_table" : {"created_at" : "desc" }},
3050
+ include = {"litellm_budget_table" : True }
3051
+ )
3052
+
3053
+ if not users :
3054
+ verbose_proxy_logger .info ("No users found in database to preload" )
3055
+ return {"preloaded_count" : 0 , "total_users" : 0 }
3056
+
3057
+ preloaded_count = 0
3058
+ failed_count = 0
3059
+
3060
+ for user in users :
3061
+ try :
3062
+ cache_key = "end_user_id:{}" .format (user .user_id )
3063
+ existing_cache = user_api_key_cache .get_cache (key = cache_key )
3064
+ if existing_cache is not None :
3065
+ continue
3066
+
3067
+
3068
+ user_api_key_cache .set_cache (
3069
+ key = cache_key ,
3070
+ value = user .dict ()
3071
+ )
3072
+
3073
+ preloaded_count += 1
3074
+
3075
+ if preloaded_count % 100 == 0 :
3076
+ verbose_proxy_logger .debug (f"Preloaded { preloaded_count } users..." )
3077
+
3078
+ except Exception as e :
3079
+ failed_count += 1
3080
+ verbose_proxy_logger .warning (f"Failed to preload user { user .user_id } : { e } " )
3081
+ continue
3082
+
3083
+ result = {
3084
+ "preloaded_count" : preloaded_count ,
3085
+ "failed_count" : failed_count ,
3086
+ "total_users" : len (users ),
3087
+ "limit" : limit
3088
+ }
3089
+
3090
+ verbose_proxy_logger .info (
3091
+ f"User preload completed: { preloaded_count } users cached, "
3092
+ f"{ failed_count } failed, { len (users )} total users in database"
3093
+ )
3094
+
3095
+ return result
3096
+
3097
+ except Exception as e :
3098
+ error_msg = f"Error during user preload: { e } "
3099
+ verbose_proxy_logger .error (error_msg )
3100
+ return {"error" : error_msg , "preloaded_count" : 0 }
3101
+
3102
+
3028
3103
async def send_email (
3029
3104
receiver_email : Optional [str ] = None ,
3030
3105
subject : Optional [str ] = None ,
0 commit comments