99import logging
1010from typing import List , Optional
1111
12- from tetra_rp .core .resources import ServerlessResource
12+ from tetra_rp .core .resources import ServerlessResource , ResourceManager
1313from .client import LoadBalancerSls
1414
1515log = logging .getLogger (__name__ )
@@ -25,12 +25,12 @@ def create_load_balancer_sls_class(
2525 """
2626 Create a LoadBalancerSls-enabled class following existing deployment patterns.
2727
28- This function follows the same synchronous pattern as create_remote_class but uses
29- LoadBalancerSls for execution. The deployment will happen lazily when methods are called .
28+ This function creates a wrapper that deploys the LoadBalancerSls endpoint dynamically
29+ using GraphQL and uses the deployed endpoint URL for LoadBalancerSls execution .
3030
3131 Args:
3232 cls: The class to be wrapped for LoadBalancerSls execution
33- resource_config: Configuration object specifying the serverless resource
33+ resource_config: Configuration object specifying the serverless resource (with type="LB")
3434 dependencies: List of pip packages to install
3535 system_dependencies: List of system packages to install
3636 extra: Additional parameters for execution
@@ -43,18 +43,75 @@ def create_load_balancer_sls_class(
4343 # Follow the same deployment pattern as existing system
4444 log .info (f"Creating LoadBalancerSls class for { cls .__name__ } " )
4545
46- # For now, use the hardcoded URL as requested
47- # TODO: Integrate with resource_config to get actual deployed endpoint URL
48- endpoint_url = "https://9ttr6h4l3f17w3.api.runpod.ai"
46+ # Verify this is a LoadBalancer resource
47+ if getattr ( resource_config , 'type' , None ) != 'LB' :
48+ raise ValueError ( f"Expected LoadBalancer resource with type='LB', got type=' { getattr ( resource_config , 'type' , None ) } '" )
4949
50- # Note: resource_config parameter will be used in future for actual deployment
50+ # Create a deployment wrapper that handles async deployment
51+ class LoadBalancerSlsClassWrapper :
52+ def __init__ (self ):
53+ self ._deployed_endpoint_url = None
54+ self ._deployment_lock = None
55+
56+ async def _ensure_deployed (self ):
57+ """Ensure the endpoint is deployed and get the URL."""
58+ if self ._deployed_endpoint_url :
59+ return self ._deployed_endpoint_url
60+
61+ # Use ResourceManager to handle caching properly
62+ resource_manager = ResourceManager ()
63+ deployed_resource = await resource_manager .get_or_deploy_resource (resource_config )
5164
52- log .info (f"Using LoadBalancerSls endpoint: { endpoint_url } " )
65+ # Construct the endpoint URL from the deployed endpoint ID
66+ # Format: https://ENDPOINT_ID.api.runpod.ai
67+ self ._deployed_endpoint_url = f"https://{ deployed_resource .id } .api.runpod.ai"
68+
69+ log .info (f"LoadBalancerSls endpoint ready: { self ._deployed_endpoint_url } " )
70+ return self ._deployed_endpoint_url
71+
72+ def __call__ (self , * args , ** kwargs ):
73+ """Create an instance that handles dynamic deployment."""
74+ return LoadBalancerSlsInstanceWrapper (
75+ cls , self , dependencies , system_dependencies , args , kwargs
76+ )
77+
78+ return LoadBalancerSlsClassWrapper ()
5379
54- # Create LoadBalancerSls instance following existing patterns
55- runtime = LoadBalancerSls (endpoint_url = endpoint_url )
5680
57- # Return the wrapped class using LoadBalancerSls
58- return runtime .remote_class (
59- dependencies = dependencies , system_dependencies = system_dependencies
60- )(cls )
81+ class LoadBalancerSlsInstanceWrapper :
82+ """Instance wrapper that handles async deployment and method routing."""
83+
84+ def __init__ (self , original_cls , class_wrapper , dependencies , system_dependencies , args , kwargs ):
85+ self ._original_cls = original_cls
86+ self ._class_wrapper = class_wrapper
87+ self ._dependencies = dependencies
88+ self ._system_dependencies = system_dependencies
89+ self ._args = args
90+ self ._kwargs = kwargs
91+ self ._runtime = None
92+
93+ async def _get_runtime (self ):
94+ """Get or create the LoadBalancerSls runtime with deployed endpoint."""
95+ if not self ._runtime :
96+ endpoint_url = await self ._class_wrapper ._ensure_deployed ()
97+ self ._runtime = LoadBalancerSls (endpoint_url = endpoint_url )
98+
99+ # Apply the remote_class decorator
100+ self ._wrapped_class = self ._runtime .remote_class (
101+ dependencies = self ._dependencies ,
102+ system_dependencies = self ._system_dependencies
103+ )(self ._original_cls )
104+
105+ # Create the actual instance
106+ self ._instance = self ._wrapped_class (* self ._args , ** self ._kwargs )
107+
108+ return self ._runtime , self ._instance
109+
110+ def __getattr__ (self , name ):
111+ """Route method calls through the deployed runtime."""
112+ async def async_method_wrapper (* args , ** kwargs ):
113+ runtime , instance = await self ._get_runtime ()
114+ method = getattr (instance , name )
115+ return await method (* args , ** kwargs )
116+
117+ return async_method_wrapper
0 commit comments