-
Notifications
You must be signed in to change notification settings - Fork 6
refactor: simplify flash init skeleton for zero-boilerplate flash run #208
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
6079274
docs: add PRD for zero-boilerplate flash run experience
deanq 13a6757
feat(client,scanner): LB route handler passthrough and path-aware dis…
deanq 0782671
refactor(manifest): remove mothership dead code, flat resource structure
deanq 9b38bd8
feat(run): file-system-as-namespace dev server generation
deanq 098aafc
feat(build,lb_handler_generator): invoke LB handler generator, rglob …
deanq ceb099f
fix(serverless): resolve flash run runtime bugs
deanq c4065f3
fix(run): hot-reload regenerates server.py on route changes
deanq d8e14b7
fix(run): suppress watchfiles debug logs from flash run output
deanq dd2491d
fix(run): omit body param from GET/HEAD route handlers
deanq 9896c46
feat(run): proxy LB routes to deployed endpoints, restore --auto-prov…
deanq 440b4b3
fix(run): add project root to sys.path during resource discovery
deanq 1c285ce
feat(run): show resource count and elapsed time during cleanup
deanq 98d471f
fix(run): route LB calls through LoadBalancerSlsStub instead of HTTP …
deanq 76e6927
fix(run): revert LB to remote dispatch, remove QB /run route
deanq e0874e0
refactor(init): simplify skeleton to flat worker files for flash run
deanq bed42ef
fix(run): handle numeric-prefixed directories in server codegen
deanq 5480404
fix(ci): update validate-wheel.sh for flat skeleton template
deanq 8b1e19f
fix: address PR 208 review feedback
deanq 277cd7a
fix(run): match generated QB/LB route calls to @remote function signa…
deanq 6881489
feat(run): replace body: dict with Pydantic models for typed Swagger UI
deanq ef92813
feat(stubs): inject remote dispatch stubs for stacked @remote execution
deanq f262f65
refactor(run): group Swagger UI tags by project directory
deanq ea426c5
fix: address PR 208 review feedback
deanq 9f1928d
fix(serverless): prevent ValueError when deploy mutates config with b…
deanq 35af650
chore: remove PRD.md from branch
deanq File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| """Helpers for the flash run dev server — loaded inside the generated server.py.""" | ||
|
|
||
| import inspect | ||
| from typing import Any, get_type_hints | ||
|
|
||
| from fastapi import HTTPException | ||
| from pydantic import create_model | ||
|
|
||
| from runpod_flash.core.resources.resource_manager import ResourceManager | ||
| from runpod_flash.stubs.load_balancer_sls import LoadBalancerSlsStub | ||
|
|
||
| _resource_manager = ResourceManager() | ||
|
|
||
|
|
||
| def _map_body_to_params(func, body): | ||
| """Map an HTTP request body to function parameters. | ||
|
|
||
| If the body is a dict whose keys match the function's parameter names, | ||
| spread it as kwargs. Otherwise pass the whole body as the value of the | ||
| first parameter (mirrors how FastAPI maps a JSON body to a single param). | ||
| """ | ||
| sig = inspect.signature(func) | ||
| param_names = set(sig.parameters.keys()) | ||
|
|
||
| if isinstance(body, dict) and body.keys() <= param_names: | ||
| return body | ||
|
|
||
| first_param = next(iter(sig.parameters), None) | ||
| if first_param is None: | ||
| return {} | ||
| return {first_param: body} | ||
|
|
||
|
|
||
| def make_input_model(name: str, func) -> type | None: | ||
| """Create a Pydantic model from a function's signature for FastAPI body typing. | ||
|
|
||
| Returns None for zero-param functions or on failure (caller uses ``or dict``). | ||
| """ | ||
| try: | ||
| sig = inspect.signature(func) | ||
| hints = get_type_hints(func) | ||
| except (ValueError, TypeError): | ||
| return None | ||
|
|
||
| _SKIP_KINDS = (inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD) | ||
| fields: dict[str, Any] = {} | ||
| for param_name, param in sig.parameters.items(): | ||
| if param_name == "self" or param.kind in _SKIP_KINDS: | ||
| continue | ||
| annotation = hints.get(param_name, Any) | ||
| if param.default is not inspect.Parameter.empty: | ||
| fields[param_name] = (annotation, param.default) | ||
| else: | ||
| fields[param_name] = (annotation, ...) | ||
|
|
||
| if not fields: | ||
| return None | ||
|
|
||
| return create_model(name, **fields) | ||
|
|
||
|
|
||
| async def call_with_body(func, body): | ||
| """Call func with body kwargs, handling Pydantic models and dicts.""" | ||
| if hasattr(body, "model_dump"): | ||
| return await func(**body.model_dump()) | ||
| raw = body.get("input", body) if isinstance(body, dict) else body | ||
| kwargs = _map_body_to_params(func, raw) | ||
| return await func(**kwargs) | ||
|
|
||
|
|
||
| def to_dict(body) -> dict: | ||
| """Convert Pydantic model or dict to plain dict.""" | ||
| return body.model_dump() if hasattr(body, "model_dump") else body | ||
|
|
||
|
|
||
| async def lb_execute(resource_config, func, body: dict): | ||
| """Dispatch an LB route to the deployed endpoint via LoadBalancerSlsStub. | ||
|
|
||
| Provisions the endpoint via ResourceManager, maps the HTTP body to | ||
| function kwargs, then dispatches through the stub's /execute path | ||
| which serializes the function via cloudpickle to the remote container. | ||
|
|
||
| Args: | ||
| resource_config: The resource config object (e.g. LiveLoadBalancer instance). | ||
| func: The @remote LB route handler function. | ||
| body: Parsed request body (from FastAPI's automatic JSON parsing). | ||
| """ | ||
| try: | ||
| deployed = await _resource_manager.get_or_deploy_resource(resource_config) | ||
| except Exception as e: | ||
| raise HTTPException( | ||
| status_code=503, | ||
| detail=f"Failed to provision '{resource_config.name}': {e}", | ||
| ) | ||
|
|
||
| stub = LoadBalancerSlsStub(deployed) | ||
| kwargs = _map_body_to_params(func, body) | ||
|
|
||
| try: | ||
| return await stub(func, None, None, False, **kwargs) | ||
| except TimeoutError as e: | ||
| raise HTTPException(status_code=504, detail=str(e)) | ||
| except ConnectionError as e: | ||
| raise HTTPException(status_code=502, detail=str(e)) | ||
| except HTTPException: | ||
| raise | ||
| except (ValueError, KeyError, TypeError) as e: | ||
| raise HTTPException(status_code=422, detail=str(e)) | ||
| except Exception as e: | ||
| raise HTTPException(status_code=500, detail=str(e)) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.