Skip to content

Commit 41a7a9f

Browse files
authored
Fix issue with greenlet_spawn when using async sqlalchemy (#1527)
1 parent 1b7a906 commit 41a7a9f

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

fastapi_pagination/ext/sqlalchemy.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from sqlalchemy.sql.elements import TextClause
2525
from typing_extensions import Literal, TypeAlias
2626

27+
from fastapi_pagination.api import create_page
2728
from fastapi_pagination.bases import AbstractParams, CursorRawParams, RawParams
2829
from fastapi_pagination.config import Config
2930
from fastapi_pagination.flow import flow, run_async_flow, run_sync_flow
@@ -315,6 +316,10 @@ def _sqlalchemy_flow(
315316
unique: bool = True,
316317
config: Optional[Config] = None,
317318
) -> Any:
319+
create_page_factory = create_page
320+
if is_async:
321+
create_page_factory = partial(greenlet_spawn, create_page_factory) # type: ignore[assignment]
322+
318323
page = yield from generic_flow(
319324
async_=is_async,
320325
total_flow=partial(_total_flow, query, conn, count_query, subquery_count),
@@ -325,6 +330,7 @@ def _sqlalchemy_flow(
325330
transformer=transformer,
326331
additional_data=additional_data,
327332
config=config,
333+
create_page_factory=create_page_factory,
328334
)
329335

330336
return page

fastapi_pagination/flows.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
__all__ = [
2+
"CreatePageFactory",
23
"CursorFlow",
34
"CursorFlowFunc",
45
"LimitOffsetFlow",
@@ -9,8 +10,9 @@
910
"generic_flow",
1011
]
1112

13+
from collections.abc import Sequence
1214
from contextlib import ExitStack
13-
from typing import Any, Callable, Optional
15+
from typing import Any, Callable, Optional, Protocol
1416

1517
from typing_extensions import TypeAlias
1618

@@ -30,6 +32,18 @@
3032
TotalFlowFunc: TypeAlias = Callable[[], AnyFlow[Optional[int]]]
3133

3234

35+
class CreatePageFactory(Protocol):
36+
def __call__(
37+
self,
38+
items: Sequence[Any],
39+
/,
40+
total: Optional[int] = None,
41+
params: Optional[AbstractParams] = None,
42+
**kwargs: Any,
43+
) -> Any: # pragma: no cover
44+
pass
45+
46+
3347
@flow
3448
def create_page_flow(
3549
items: Any,
@@ -40,6 +54,7 @@ def create_page_flow(
4054
additional_data: Optional[dict[str, Any]] = None,
4155
config: Optional[Config] = None,
4256
async_: bool = False,
57+
create_page_factory: Optional[CreatePageFactory] = None,
4358
) -> Any:
4459
with ExitStack() as stack:
4560
if config and config.page_cls:
@@ -51,13 +66,18 @@ def create_page_flow(
5166
async_=async_,
5267
)
5368

54-
return create_page(
69+
if create_page_factory is None:
70+
create_page_factory = create_page
71+
72+
page = yield create_page_factory(
5573
t_items,
5674
total=total,
5775
params=params,
5876
**(additional_data or {}),
5977
)
6078

79+
return page
80+
6181

6282
@flow
6383
def generic_flow( # noqa: C901
@@ -71,6 +91,7 @@ def generic_flow( # noqa: C901
7191
additional_data: Optional[AdditionalData] = None,
7292
config: Optional[Config] = None,
7393
async_: bool = False,
94+
create_page_factory: Optional[CreatePageFactory] = None,
7495
) -> Any:
7596
types: list[ParamsType] = []
7697
if limit_offset_flow is not None:
@@ -120,6 +141,7 @@ def generic_flow( # noqa: C901
120141
additional_data=additional_data,
121142
config=config,
122143
async_=async_,
144+
create_page_factory=create_page_factory,
123145
)
124146

125147
return page

0 commit comments

Comments
 (0)