functualize-lambda 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""Functualize Lambda Adapter Plugin — AWS Lambda delivery for FunctualizeApp.
|
|
2
|
+
|
|
3
|
+
Implements the AdapterPlugin Protocol with adapter_type="lambda".
|
|
4
|
+
Supports two deployment patterns:
|
|
5
|
+
|
|
6
|
+
1. Fat Lambda (internal routing):
|
|
7
|
+
- Single Lambda function handling multiple jobs
|
|
8
|
+
- Event contains {"job": "job_name", "kwargs": {...}}
|
|
9
|
+
- Adapter routes to the correct job via app.execute()
|
|
10
|
+
|
|
11
|
+
2. Thin Lambda (per-job handler):
|
|
12
|
+
- One Lambda function per job, routing handled by infrastructure
|
|
13
|
+
- Use make_handler(job_name) to create a bound handler
|
|
14
|
+
|
|
15
|
+
Both patterns work with the static wiring fast path for <5ms cold start
|
|
16
|
+
when using JobSources(functions=[...]) with fully-explicit config.
|
|
17
|
+
|
|
18
|
+
Usage (fat Lambda):
|
|
19
|
+
app = FunctualizeApp("my-app", job_sources=JobSources(functions=[deploy, rollback]))
|
|
20
|
+
adapter = LambdaAdapter()
|
|
21
|
+
adapter(app)
|
|
22
|
+
|
|
23
|
+
def handler(event, context):
|
|
24
|
+
return adapter.run(event, context)
|
|
25
|
+
|
|
26
|
+
Usage (thin Lambda):
|
|
27
|
+
app = FunctualizeApp("my-app", job_sources=JobSources(functions=[deploy]))
|
|
28
|
+
adapter = LambdaAdapter()
|
|
29
|
+
adapter(app)
|
|
30
|
+
|
|
31
|
+
handler = adapter.make_handler("deploy")
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
from __future__ import annotations
|
|
35
|
+
|
|
36
|
+
from collections.abc import Callable
|
|
37
|
+
from typing import TYPE_CHECKING, Any
|
|
38
|
+
|
|
39
|
+
if TYPE_CHECKING:
|
|
40
|
+
from functualize.app.core import FunctualizeApp
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class LambdaAdapter:
|
|
44
|
+
"""AWS Lambda delivery adapter.
|
|
45
|
+
|
|
46
|
+
Satisfies the AdapterPlugin Protocol. Supports fat-Lambda (internal
|
|
47
|
+
routing via event["job"]) and thin-Lambda (per-job handler via
|
|
48
|
+
make_handler()) deployment patterns.
|
|
49
|
+
|
|
50
|
+
PluginMetadata attributes:
|
|
51
|
+
name: "functualize-lambda"
|
|
52
|
+
version: "1.0.0"
|
|
53
|
+
description: "AWS Lambda adapter supporting fat and thin Lambda patterns"
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
name: str = "functualize-lambda"
|
|
57
|
+
version: str = "1.0.0"
|
|
58
|
+
description: str = "AWS Lambda adapter supporting fat and thin Lambda patterns"
|
|
59
|
+
adapter_type: str = "lambda"
|
|
60
|
+
|
|
61
|
+
def __init__(self) -> None:
|
|
62
|
+
self._app: FunctualizeApp | None = None
|
|
63
|
+
|
|
64
|
+
def __call__(self, app: FunctualizeApp) -> None:
|
|
65
|
+
"""Setup phase — store app reference.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
app: The FunctualizeApp kernel instance.
|
|
69
|
+
"""
|
|
70
|
+
self._app = app
|
|
71
|
+
|
|
72
|
+
def run(self, *args: Any, **kwargs: Any) -> Any:
|
|
73
|
+
"""Fat Lambda entrypoint — route event to the correct job.
|
|
74
|
+
|
|
75
|
+
Parses the event to determine which job to execute and with
|
|
76
|
+
what arguments, then delegates to the kernel's execute method.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
*args: Expected to be (event, context) where event is a dict
|
|
80
|
+
containing "job" (required) and "kwargs" (optional).
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Dict with "statusCode" (200 or 500) and "body" (result or
|
|
84
|
+
error message).
|
|
85
|
+
|
|
86
|
+
Raises:
|
|
87
|
+
RuntimeError: If run() is called before __call__(app).
|
|
88
|
+
"""
|
|
89
|
+
if self._app is None:
|
|
90
|
+
raise RuntimeError("LambdaAdapter.run() called before __call__(app)")
|
|
91
|
+
|
|
92
|
+
# Extract event and context from positional args
|
|
93
|
+
event: dict[str, Any] = args[0] if args else kwargs.get("event", {})
|
|
94
|
+
# context is available but not used by the adapter itself
|
|
95
|
+
# _context = args[1] if len(args) > 1 else kwargs.get("context")
|
|
96
|
+
|
|
97
|
+
return self._handle_event(event)
|
|
98
|
+
|
|
99
|
+
def make_handler(self, job_name: str) -> Callable[..., Any]:
|
|
100
|
+
"""Create a thin-Lambda handler bound to a specific job.
|
|
101
|
+
|
|
102
|
+
Returns a callable with the standard Lambda signature
|
|
103
|
+
(event, context) that always executes the specified job.
|
|
104
|
+
Event kwargs can still be provided via event.get("kwargs", {}).
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
job_name: The name of the job this handler will execute.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
A callable(event, context) -> dict suitable as a Lambda handler.
|
|
111
|
+
|
|
112
|
+
Raises:
|
|
113
|
+
RuntimeError: If make_handler() is called before __call__(app).
|
|
114
|
+
"""
|
|
115
|
+
if self._app is None:
|
|
116
|
+
raise RuntimeError(
|
|
117
|
+
"LambdaAdapter.make_handler() called before __call__(app)"
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
app = self._app
|
|
121
|
+
|
|
122
|
+
def handler(event: dict[str, Any], context: Any) -> dict[str, Any]:
|
|
123
|
+
"""Thin Lambda handler for job '{job_name}'."""
|
|
124
|
+
job_kwargs = event.get("kwargs", {})
|
|
125
|
+
try:
|
|
126
|
+
result = app.execute(job_name, **job_kwargs)
|
|
127
|
+
return {"statusCode": 200, "body": result.return_value}
|
|
128
|
+
except Exception as exc:
|
|
129
|
+
return {"statusCode": 500, "body": str(exc)}
|
|
130
|
+
|
|
131
|
+
# Set a useful name for debugging/logging
|
|
132
|
+
handler.__name__ = f"lambda_handler_{job_name}"
|
|
133
|
+
handler.__qualname__ = (
|
|
134
|
+
f"LambdaAdapter.make_handler.<locals>.handler[{job_name}]"
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
return handler
|
|
138
|
+
|
|
139
|
+
def shutdown(self) -> None:
|
|
140
|
+
"""No-op shutdown. Lambda functions are stateless."""
|
|
141
|
+
pass
|
|
142
|
+
|
|
143
|
+
def _handle_event(self, event: dict[str, Any]) -> dict[str, Any]:
|
|
144
|
+
"""Internal: parse event and execute the job.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
event: Lambda event dict with "job" and optional "kwargs".
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
Dict with "statusCode" and "body".
|
|
151
|
+
"""
|
|
152
|
+
assert self._app is not None
|
|
153
|
+
|
|
154
|
+
try:
|
|
155
|
+
job_name = event["job"]
|
|
156
|
+
except (KeyError, TypeError) as exc:
|
|
157
|
+
return {
|
|
158
|
+
"statusCode": 400,
|
|
159
|
+
"body": f"Missing required field 'job' in event: {exc}",
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
job_kwargs = event.get("kwargs", {})
|
|
163
|
+
|
|
164
|
+
try:
|
|
165
|
+
result = self._app.execute(job_name, **job_kwargs)
|
|
166
|
+
return {"statusCode": 200, "body": result.return_value}
|
|
167
|
+
except Exception as exc:
|
|
168
|
+
return {"statusCode": 500, "body": str(exc)}
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
__all__ = ["LambdaAdapter"]
|
|
File without changes
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: functualize-lambda
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: AWS Lambda adapter plugin for functualize - supports fat and thin Lambda deployment patterns
|
|
5
|
+
Author-email: Mohammad Hakim Adiprasetya <viltohmyst@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: Typing :: Typed
|
|
13
|
+
Requires-Python: >=3.11
|
|
14
|
+
Requires-Dist: functualize<1.0.0,>=0.1.0
|
|
15
|
+
Provides-Extra: dev
|
|
16
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
17
|
+
Requires-Dist: pytest>=7.4.0; extra == 'dev'
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# functualize-lambda
|
|
21
|
+
|
|
22
|
+
> **Status: Published** — Independently installable from PyPI.
|
|
23
|
+
|
|
24
|
+
AWS Lambda adapter plugin for [functualize](https://github.com/raicing-ai/functualize).
|
|
25
|
+
|
|
26
|
+
Supports two deployment patterns:
|
|
27
|
+
|
|
28
|
+
1. **Fat Lambda** — Single Lambda function with internal routing via `event["job"]`
|
|
29
|
+
2. **Thin Lambda** — One Lambda per job via `make_handler(job_name)`
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install functualize-lambda
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
### Fat Lambda (internal routing)
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from functualize.app import FunctualizeApp, JobSources
|
|
43
|
+
from functualize_lambda import LambdaAdapter
|
|
44
|
+
|
|
45
|
+
app = FunctualizeApp("my-app", job_sources=JobSources(functions=[deploy, rollback]))
|
|
46
|
+
adapter = LambdaAdapter()
|
|
47
|
+
adapter(app)
|
|
48
|
+
|
|
49
|
+
def handler(event, context):
|
|
50
|
+
return adapter.run(event, context)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Events should have the shape: `{"job": "job_name", "kwargs": {"key": "value"}}`
|
|
54
|
+
|
|
55
|
+
### Thin Lambda (per-job handler)
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from functualize.app import FunctualizeApp, JobSources
|
|
59
|
+
from functualize_lambda import LambdaAdapter
|
|
60
|
+
|
|
61
|
+
app = FunctualizeApp("my-app", job_sources=JobSources(functions=[deploy]))
|
|
62
|
+
adapter = LambdaAdapter()
|
|
63
|
+
adapter(app)
|
|
64
|
+
|
|
65
|
+
handler = adapter.make_handler("deploy")
|
|
66
|
+
```
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
functualize_lambda/__init__.py,sha256=TSn9ClHmglDhZIp4hdSFSG9XtVl2LwYLfKM4ZudLREo,5701
|
|
2
|
+
functualize_lambda/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
functualize_lambda-0.1.0.dist-info/METADATA,sha256=jHSOSlr3i7uRUbzyteecFwWYQfaK1wTF-6ViAF5ohYU,1917
|
|
4
|
+
functualize_lambda-0.1.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
5
|
+
functualize_lambda-0.1.0.dist-info/entry_points.txt,sha256=bSyXWEPfxQ3wPPDVYr5knz8NMvGwJmWO7BgdkQYZrXU,64
|
|
6
|
+
functualize_lambda-0.1.0.dist-info/RECORD,,
|