@@ -23,7 +23,7 @@ async def hello_async(request): # Starlette.Request
23232 . ** Backward compatibility** - All existing sync functions must continue to work
24243 . ** Unified API** - Users shouldn't need different decorators for sync vs async
25254 . ** Type safety** - Proper typing for both sync and async cases
26- 5 . ** Automatic detection ** - The system should automatically detect and handle async functions
26+ 5 . ** Flexibility ** - The aio namespace accepts both sync and async functions
27276 . ** Universal support** - Async should work for ALL function types, not just HTTP
2828
2929## Function Types to Support
@@ -106,39 +106,21 @@ Firebase Functions Python supports multiple trigger types that all need async su
106106
107107### Phase 2: Decorator Updates
108108
109- #### 2.1 Universal Decorator Pattern
110- Each decorator should follow this pattern:
109+ #### 2.1 Namespace-based Approach
110+ Instead of modifying existing decorators, we created a new ` aio ` namespace:
111+ - ` firebase_functions.aio.https_fn ` for async HTTP functions
112+ - The aio decorators accept both sync and async functions
113+ - ASGI runtime handles sync functions by running them in a thread pool
111114
112- ``` python
113- def on_some_event (** kwargs ):
114- def decorator (func ):
115- is_async = inspect.iscoroutinefunction(func)
116-
117- if is_async:
118- # Set up async wrapper
119- @functools.wraps (func)
120- async def async_wrapper (* args , ** kwargs ):
121- # Any necessary async setup
122- return await func(* args, ** kwargs)
123-
124- wrapped = async_wrapper
125- runtime_mode = " async"
126- else :
127- # Use existing sync wrapper
128- wrapped = existing_sync_wrapper(func)
129- runtime_mode = " sync"
130-
131- # Set metadata
132- endpoint = create_endpoint(
133- # ... existing endpoint config ...
134- runtime_mode = runtime_mode
135- )
136- _util.set_func_endpoint_attr(wrapped, endpoint)
137-
138- return wrapped
139-
140- return decorator
141- ```
115+ #### 2.2 Shared Implementation
116+ To avoid code duplication, we extracted shared business logic:
117+ - ` _validate_on_call_request_headers() ` - Validates headers and method
118+ - ` _process_on_call_request_body() ` - Processes request body after reading
119+ - ` _format_on_call_response() ` - Formats successful responses
120+ - ` _format_on_call_error() ` - Formats error responses
121+ - ` _add_cors_headers_to_response() ` - Adds CORS headers to any response
122+
123+ The decorators use a shared implementation with an ` asgi ` parameter to differentiate between sync and async modes.
142124
143125#### 2.2 HTTP Functions Special Handling
144126HTTP functions need special care because the request type changes:
@@ -176,16 +158,25 @@ We'll need to handle this in the type system and potentially in request processi
176158
177159### HTTP Functions
178160``` python
161+ from firebase_functions import https_fn
162+ from firebase_functions.aio import https_fn as async_https_fn
163+
179164# Sync (existing)
180165@https_fn.on_request ()
181166def sync_http (request : Request) -> Response:
182167 return Response(" Hello sync" )
183168
184169# Async (new)
185- @https_fn .on_request ()
170+ @async_https_fn .on_request ()
186171async def async_http (request ) -> Response: # Will be Starlette Request
187172 result = await some_async_api_call()
188173 return Response(f " Hello async: { result} " )
174+
175+ # Sync function in aio namespace (also supported)
176+ @async_https_fn.on_request ()
177+ def sync_in_async_http (request ) -> Response:
178+ # This sync function will run in ASGI's thread pool
179+ return Response(" Hello from sync in async" )
189180```
190181
191182### Firestore Functions
@@ -232,12 +223,26 @@ async def async_process_message(event: CloudEvent[MessagePublishedData]) -> None
2322233 . Update documentation and examples
2332244 . Release as minor version update (backward compatible)
234225
226+ ## Implementation Status
227+
228+ ### Completed (Phase 1)
229+ - ✅ HTTP functions (on_request and on_call) with async support
230+ - ✅ Shared business logic to avoid code duplication
231+ - ✅ CORS handling for async functions
232+ - ✅ Type safety with overloads
233+ - ✅ Support for both sync and async functions in aio namespace
234+ - ✅ Comprehensive tests
235+
236+ ### Remaining Work
237+ - Event-triggered functions (Firestore, Database, Storage, etc.)
238+ - Documentation and examples
239+ - Integration with Firebase CLI for deployment
240+
235241## Open Questions
236242
2372431 . Should we support both Flask and Starlette response types for async HTTP functions?
2382442 . How should we handle async context managers and cleanup?
2392453 . Should we provide async versions of Firebase Admin SDK operations?
240- 4 . What's the best way to handle errors in async functions?
241246
242247## Next Steps
243248
0 commit comments