Skip to content

Commit 381a21c

Browse files
committed
- ruff and mypy fixes
- multilang (py,js,rb,sh,go) support - changes in limits (retries)
1 parent cc616ee commit 381a21c

6 files changed

Lines changed: 93 additions & 21 deletions

File tree

backend/app/config.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from typing import Optional
22

3+
from app.runtime_registry import SUPPORTED_RUNTIMES as RUNTIME_MATRIX
4+
from pydantic import Field
35
from pydantic_settings import BaseSettings
46

57

@@ -24,9 +26,9 @@ class Settings(BaseSettings):
2426
K8S_POD_MEMORY_REQUEST: str = "128Mi"
2527
K8S_POD_EXECUTION_TIMEOUT: int = 5 # in seconds
2628

27-
SUPPORTED_RUNTIMES: dict[str, list[str]] = {
28-
"python": ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
29-
}
29+
SUPPORTED_RUNTIMES: dict[str, list[str]] = Field(
30+
default_factory=lambda: RUNTIME_MATRIX
31+
)
3032

3133
PROMETHEUS_URL: str = "http://prometheus:9090"
3234

backend/app/core/metrics.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from typing import Any, TypeVar
22

3-
from app.config import get_settings
43
from prometheus_client import Counter, Gauge, Histogram
54

65
ALLOWED_STATUSES = ["success", "error", "timeout", "invalid_input"]

backend/app/runtime_registry.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
from __future__ import annotations
2+
3+
from typing import Dict, List, NamedTuple
4+
5+
6+
class RuntimeConfig(NamedTuple):
7+
image: str # Full Docker image reference
8+
file_name: str # Name that will be mounted under /scripts/
9+
command: List[str] # Entrypoint executed inside the container
10+
11+
12+
LANGUAGE_SPECS: Dict[str, dict] = {
13+
"python": {
14+
"versions": ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"],
15+
"image_tpl": "python:{version}-slim",
16+
"file_ext": "py",
17+
"interpreter": ["python"],
18+
},
19+
"node": {
20+
"versions": ["18", "20", "22"],
21+
"image_tpl": "node:{version}-alpine",
22+
"file_ext": "js",
23+
"interpreter": ["node"],
24+
},
25+
"ruby": {
26+
"versions": ["3.1", "3.2", "3.3"],
27+
"image_tpl": "ruby:{version}-alpine",
28+
"file_ext": "rb",
29+
"interpreter": ["ruby"],
30+
},
31+
"bash": {
32+
"versions": ["5.1", "5.2", "5.3"],
33+
"image_tpl": "bash:{version}",
34+
"file_ext": "sh",
35+
"interpreter": ["bash"],
36+
},
37+
"go": {
38+
"versions": ["1.20", "1.21", "1.22"],
39+
"image_tpl": "golang:{version}-alpine",
40+
"file_ext": "go",
41+
"interpreter": ["bash", "-c", "go run /scripts/main.go"],
42+
},
43+
}
44+
45+
def _make_runtime_configs() -> Dict[str, Dict[str, RuntimeConfig]]:
46+
registry: Dict[str, Dict[str, RuntimeConfig]] = {}
47+
48+
for lang, spec in LANGUAGE_SPECS.items():
49+
versions = spec["versions"]
50+
image_tpl: str = spec["image_tpl"]
51+
file_ext: str = spec["file_ext"]
52+
interpreter_cmd: List[str] = spec["interpreter"]
53+
54+
file_name = f"main.{file_ext}"
55+
full_path = f"/scripts/{file_name}"
56+
57+
registry[lang] = {
58+
v: RuntimeConfig(
59+
image=image_tpl.format(version=v),
60+
file_name=file_name,
61+
command=(
62+
interpreter_cmd
63+
if "{file}" in " ".join(interpreter_cmd)
64+
else interpreter_cmd + [full_path]
65+
),
66+
)
67+
for v in versions
68+
}
69+
70+
return registry
71+
72+
73+
RUNTIME_REGISTRY: Dict[str, Dict[str, RuntimeConfig]] = _make_runtime_configs()
74+
75+
SUPPORTED_RUNTIMES: Dict[str, List[str]] = {
76+
lang: list(versions.keys()) for lang, versions in RUNTIME_REGISTRY.items()
77+
}

backend/app/schemas/execution.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from datetime import datetime, timezone
2-
from typing import Dict, List, Optional
2+
from typing import Dict, Optional
33
from uuid import uuid4
44

55
from pydantic import BaseModel, Field, computed_field
@@ -59,8 +59,8 @@ class ExecutionRequest(BaseModel):
5959
script: str
6060
lang: str = Field(
6161
default="python", description="Language name"
62-
),
63-
lang_version: Optional[str] = Field(
62+
)
63+
lang_version: str = Field(
6464
default="3.11", description="Language version to use for execution"
6565
)
6666

backend/app/services/execution_service.py

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
ExecutionRepository,
1717
get_execution_repository,
1818
)
19+
from app.runtime_registry import RUNTIME_REGISTRY
1920
from app.schemas.execution import ExecutionCreate, ExecutionInDB, ExecutionUpdate
2021
from app.services.kubernetes_service import (
2122
KubernetesPodError,
@@ -52,26 +53,19 @@ async def get_k8s_resource_limits(self) -> Dict[str, Any]:
5253
}
5354

5455
async def _start_k8s_execution(
55-
self, execution_id_str: str,
56+
self,
57+
execution_id_str: str,
5658
script: str,
5759
lang: str,
5860
lang_version: str
5961
) -> None:
6062
try:
61-
# Python-specific configuration
62-
image = f"{lang}:{lang_version}-slim"
63-
64-
# TODO: decouple from file format smh
65-
command = ["python", "/scripts/script.py"]
66-
config_map_data = {
67-
"script.py": script
68-
}
69-
63+
runtime_cfg = RUNTIME_REGISTRY[lang][lang_version]
7064
await self.k8s_service.create_execution_pod(
7165
execution_id=execution_id_str,
72-
image=image,
73-
command=command,
74-
config_map_data=config_map_data
66+
image=runtime_cfg.image,
67+
command=runtime_cfg.command,
68+
config_map_data={runtime_cfg.file_name: script},
7569
)
7670

7771
await self.execution_repo.update_execution(

backend/app/services/kubernetes_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ async def shutdown_all(self) -> None:
5151

5252
class KubernetesService:
5353
NAMESPACE = "default"
54-
POD_RETRY_ATTEMPTS = 60
54+
POD_RETRY_ATTEMPTS = 15
5555
POD_RETRY_INTERVAL = 1
5656
POD_SUCCESS_STATES = {"Succeeded", "Failed"}
5757
SHUTDOWN_TIMEOUT = 30

0 commit comments

Comments
 (0)