Skip to content

Commit 904632e

Browse files
authored
Merge pull request #52 from YangZhiBoGreenHand/feat/yzb/update-1
feat: use async session
2 parents fcc0746 + 08ee9e2 commit 904632e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1709
-1022
lines changed

app/api/deps.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1-
from sqlmodel import Session
1+
from typing import AsyncGenerator
22

33
from fastapi import Depends, Request
4-
54
from fastapi.security import APIKeyHeader
6-
from config.config import settings
5+
from sqlalchemy.ext.asyncio import AsyncSession
6+
77
from app.exceptions.exception import AuthenticationError, AuthorizationError, ResourceNotFoundError
8-
from app.providers import database
9-
from app.models.token_relation import RelationType, TokenRelationQuery
108
from app.models.token import Token
11-
from app.services.token.token_relation import TokenRelationService
9+
from app.models.token_relation import RelationType, TokenRelationQuery
10+
from app.providers import database
1211
from app.services.token.token import TokenService
12+
from app.services.token.token_relation import TokenRelationService
13+
from config.config import settings
1314

1415

15-
def get_session():
16-
with Session(database.engine) as session:
16+
async def get_async_session() -> AsyncGenerator[AsyncSession, None]:
17+
"""session生成器 作为fast api的Depends选项"""
18+
async with database.async_session_local() as session:
1719
yield session
1820

1921

@@ -49,13 +51,13 @@ async def verify_admin_token(token=Depends(oauth_token)) -> Token:
4951
raise AuthorizationError()
5052

5153

52-
async def get_token(session=Depends(get_session), token=Depends(oauth_token)) -> Token:
54+
async def get_token(session=Depends(get_async_session), token=Depends(oauth_token)) -> Token:
5355
"""
5456
get token info
5557
"""
5658
if token and token != "":
5759
try:
58-
return TokenService.get_token(session=session, token=token)
60+
return await TokenService.get_token(session=session, token=token)
5961
except ResourceNotFoundError:
6062
pass
6163
return None
@@ -90,13 +92,21 @@ async def get_param_from_request(request: Request):
9092
return get_param_from_request
9193

9294

93-
def verify_token_relation(relation_type: RelationType, name: str):
95+
def verify_token_relation(relation_type: RelationType, name: str, ignore_none_relation_id: bool = False):
96+
"""
97+
param relation_type: relation type
98+
param name: param name
99+
param ignore_none_relation_id: if ignore_none_relation_id is set, return where relation_id is None, use for copy thread api
100+
"""
101+
94102
async def verify_authorization(
95-
session=Depends(get_session), token_id=Depends(get_token_id), relation_id=Depends(get_param(name))
103+
session=Depends(get_async_session), token_id=Depends(get_token_id), relation_id=Depends(get_param(name))
96104
):
105+
if token_id and ignore_none_relation_id:
106+
return
97107
if token_id and relation_id:
98108
verify = TokenRelationQuery(token_id=token_id, relation_type=relation_type, relation_id=relation_id)
99-
if TokenRelationService.verify_relation(session=session, verify=verify):
109+
if await TokenRelationService.verify_relation(session=session, verify=verify):
100110
return
101111
raise AuthorizationError()
102112

app/api/routes.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,3 @@ def router_init():
1313
api_router.include_router(files.router, prefix="/files", tags=["files"])
1414
api_router.include_router(token.router, prefix="/tokens", tags=["tokens"])
1515
api_router.include_router(action.router, prefix="/actions", tags=["actions"])
16-

app/api/v1/action.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,75 @@
11
from typing import Dict, List
22

33
from fastapi import APIRouter, Depends
4-
from sqlmodel import Session, select
4+
from sqlalchemy.ext.asyncio import AsyncSession
5+
from sqlmodel import select
56

6-
from app.api.deps import get_session, get_token_id
7+
from app.api.deps import get_async_session, get_token_id
8+
from app.libs.paginate import cursor_page, CommonPage
79
from app.models.action import Action
810
from app.models.token_relation import RelationType
911
from app.providers.auth_provider import auth_policy
1012
from app.schemas.common import DeleteResponse, BaseSuccessDataResponse
1113
from app.schemas.tool.action import ActionBulkCreateRequest, ActionUpdateRequest, ActionRunRequest
1214
from app.services.tool.action import ActionService
13-
from app.libs.paginate import cursor_page, CommonPage
14-
1515

1616
router = APIRouter()
1717

1818

1919
@router.get("", response_model=CommonPage[Action])
20-
def list_actions(*, session: Session = Depends(get_session), token_id=Depends(get_token_id)):
20+
async def list_actions(*, session: AsyncSession = Depends(get_async_session), token_id=Depends(get_token_id)):
2121
"""
2222
Returns a list of Actions.
2323
"""
2424
statement = auth_policy.token_filter(
2525
select(Action), field=Action.id, relation_type=RelationType.Action, token_id=token_id
2626
)
27-
return cursor_page(statement, session)
27+
return await cursor_page(statement, session)
2828

2929

3030
@router.post("", response_model=List[Action])
31-
def create_actions(
32-
*, session: Session = Depends(get_session), body: ActionBulkCreateRequest, token_id=Depends(get_token_id)
31+
async def create_actions(
32+
*, session: AsyncSession = Depends(get_async_session), body: ActionBulkCreateRequest, token_id=Depends(get_token_id)
3333
) -> List[Action]:
3434
"""
3535
Create an action with openapi schema.
3636
"""
3737

38-
return ActionService.create_actions(session=session, body=body, token_id=token_id)
38+
return await ActionService.create_actions(session=session, body=body, token_id=token_id)
3939

4040

4141
@router.get("/{action_id}", response_model=Action)
42-
def get_action(*, session: Session = Depends(get_session), action_id: str) -> Action:
42+
async def get_action(*, session: AsyncSession = Depends(get_async_session), action_id: str) -> Action:
4343
"""
4444
Retrieves an action.
4545
"""
46-
return ActionService.get_action(session=session, action_id=action_id)
46+
return await ActionService.get_action(session=session, action_id=action_id)
4747

4848

4949
@router.post("/{action_id}", response_model=Action)
50-
def modify_action(*, session: Session = Depends(get_session), action_id: str, body: ActionUpdateRequest) -> Action:
50+
async def modify_action(
51+
*, session: AsyncSession = Depends(get_async_session), action_id: str, body: ActionUpdateRequest
52+
) -> Action:
5153
"""
5254
Modifies an action.
5355
"""
54-
return ActionService.modify_action(session=session, action_id=action_id, body=body)
56+
return await ActionService.modify_action(session=session, action_id=action_id, body=body)
5557

5658

5759
@router.delete("/{action_id}", response_model=DeleteResponse)
58-
def delete_action(*, session: Session = Depends(get_session), action_id: str) -> DeleteResponse:
60+
async def delete_action(*, session: AsyncSession = Depends(get_async_session), action_id: str) -> DeleteResponse:
5961
"""
6062
Delete an action.
6163
"""
62-
return ActionService.delete_action(session=session, action_id=action_id)
64+
return await ActionService.delete_action(session=session, action_id=action_id)
6365

6466

6567
@router.post(
6668
"/{action_id}/run",
6769
response_model=BaseSuccessDataResponse,
6870
)
69-
def api_run_action(*, session: Session = Depends(get_session), action_id: str, body: ActionRunRequest):
70-
response: Dict = ActionService.run_action(
71+
async def api_run_action(*, session: AsyncSession = Depends(get_async_session), action_id: str, body: ActionRunRequest):
72+
response: Dict = await ActionService.run_action(
7173
session=session,
7274
action_id=action_id,
7375
parameters=body.parameters,

app/api/v1/assistant.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from fastapi import APIRouter, Depends
2-
from sqlmodel import Session, select
2+
from sqlalchemy.ext.asyncio import AsyncSession
3+
from sqlmodel import select
34

4-
from app.api.deps import get_token_id, get_session
5+
from app.api.deps import get_token_id, get_async_session
56
from app.models.assistant import Assistant, AssistantUpdate, AssistantCreate
67
from app.libs.paginate import cursor_page, CommonPage
78
from app.models.token_relation import RelationType
@@ -13,45 +14,47 @@
1314

1415

1516
@router.get("", response_model=CommonPage[Assistant])
16-
def list_assistants(*, session: Session = Depends(get_session), token_id=Depends(get_token_id)):
17+
async def list_assistants(*, session: AsyncSession = Depends(get_async_session), token_id=Depends(get_token_id)):
1718
"""
1819
Returns a list of assistants.
1920
"""
2021
statement = auth_policy.token_filter(
2122
select(Assistant), field=Assistant.id, relation_type=RelationType.Assistant, token_id=token_id
2223
)
23-
return cursor_page(statement, session)
24+
return await cursor_page(statement, session)
2425

2526

2627
@router.post("", response_model=Assistant)
27-
def create_assistant(
28-
*, session: Session = Depends(get_session), body: AssistantCreate, token_id=Depends(get_token_id)
28+
async def create_assistant(
29+
*, session: AsyncSession = Depends(get_async_session), body: AssistantCreate, token_id=Depends(get_token_id)
2930
) -> Assistant:
3031
"""
3132
Create an assistant with a model and instructions.
3233
"""
33-
return AssistantService.create_assistant(session=session, body=body, token_id=token_id)
34+
return await AssistantService.create_assistant(session=session, body=body, token_id=token_id)
3435

3536

3637
@router.get("/{assistant_id}", response_model=Assistant)
37-
def get_assistant(*, session: Session = Depends(get_session), assistant_id: str) -> Assistant:
38+
async def get_assistant(*, session: AsyncSession = Depends(get_async_session), assistant_id: str) -> Assistant:
3839
"""
3940
Retrieves an assistant.
4041
"""
41-
return AssistantService.get_assistant(session=session, assistant_id=assistant_id)
42+
return await AssistantService.get_assistant(session=session, assistant_id=assistant_id)
4243

4344

4445
@router.post("/{assistant_id}", response_model=Assistant)
45-
def modify_assistant(*, session: Session = Depends(get_session), assistant_id: str, body: AssistantUpdate) -> Assistant:
46+
async def modify_assistant(
47+
*, session: AsyncSession = Depends(get_async_session), assistant_id: str, body: AssistantUpdate
48+
) -> Assistant:
4649
"""
4750
Modifies an assistant.
4851
"""
49-
return AssistantService.modify_assistant(session=session, assistant_id=assistant_id, body=body)
52+
return await AssistantService.modify_assistant(session=session, assistant_id=assistant_id, body=body)
5053

5154

5255
@router.delete("/{assistant_id}", response_model=DeleteResponse)
53-
def delete_assistant(*, session: Session = Depends(get_session), assistant_id: str) -> DeleteResponse:
56+
async def delete_assistant(*, session: AsyncSession = Depends(get_async_session), assistant_id: str) -> DeleteResponse:
5457
"""
5558
Delete an assistant.
5659
"""
57-
return AssistantService.delete_assistant(session=session, assistant_id=assistant_id)
60+
return await AssistantService.delete_assistant(session=session, assistant_id=assistant_id)

app/api/v1/assistant_file.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,60 @@
11
from fastapi import APIRouter, Depends
2-
from sqlmodel import Session, select
2+
from sqlalchemy.ext.asyncio import AsyncSession
3+
from sqlmodel import select
34

4-
from app.api.deps import get_session
5-
from app.models.assistant_file import AssistantFileCreate, AssistantFile
5+
from app.api.deps import get_async_session
66
from app.libs.paginate import cursor_page, CommonPage
7+
from app.models.assistant_file import AssistantFileCreate, AssistantFile
78
from app.schemas.common import DeleteResponse
89
from app.services.assistant.assistant_file import AssistantFileService
910

1011
router = APIRouter()
1112

1213

1314
@router.get("/{assistant_id}/files", response_model=CommonPage[AssistantFile])
14-
def list_assistant_files(
15+
async def list_assistant_files(
1516
*,
16-
session: Session = Depends(get_session),
17+
session: AsyncSession = Depends(get_async_session),
1718
assistant_id: str,
1819
):
1920
"""
2021
Returns a list of assistant files.
2122
"""
22-
return cursor_page(select(AssistantFile).where(AssistantFile.assistant_id == assistant_id), db=session)
23+
return await cursor_page(select(AssistantFile).where(AssistantFile.assistant_id == assistant_id), db=session)
2324

2425

2526
@router.post("/{assistant_id}/files", response_model=AssistantFile)
26-
def create_assistant_file(
27+
async def create_assistant_file(
2728
*,
28-
session: Session = Depends(get_session),
29+
session: AsyncSession = Depends(get_async_session),
2930
assistant_id: str,
3031
body: AssistantFileCreate,
3132
) -> AssistantFile:
3233
"""
3334
Create an assistant file by attaching a [File](/docs/api-reference/files)
3435
to an [assistant](/docs/api-reference/assistants).
3536
"""
36-
return AssistantFileService.create_assistant_file(session=session, assistant_id=assistant_id, body=body)
37+
return await AssistantFileService.create_assistant_file(session=session, assistant_id=assistant_id, body=body)
3738

3839

3940
@router.get("/{assistant_id}/files/{file_id}", response_model=AssistantFile)
40-
def get_assistant_file(*, session: Session = Depends(get_session), assistant_id: str, file_id: str) -> AssistantFile:
41+
async def get_assistant_file(
42+
*, session: AsyncSession = Depends(get_async_session), assistant_id: str, file_id: str
43+
) -> AssistantFile:
4144
"""
4245
Retrieves an AssistantFile.
4346
"""
44-
return AssistantFileService.get_assistant_file(session=session, assistant_id=assistant_id, file_id=file_id)
47+
return await AssistantFileService.get_assistant_file(session=session, assistant_id=assistant_id, file_id=file_id)
4548

4649

4750
@router.delete(
4851
"/{assistant_id}/files/{file_id}",
4952
response_model=DeleteResponse,
5053
)
51-
def delete_assistant_file(
52-
*, session: Session = Depends(get_session), assistant_id: str, file_id: str
54+
async def delete_assistant_file(
55+
*, session: AsyncSession = Depends(get_async_session), assistant_id: str, file_id: str
5356
) -> DeleteResponse:
5457
"""
5558
Delete an assistant file.
5659
"""
57-
return AssistantFileService.delete_assistant_file(session=session, assistant_id=assistant_id, file_id=file_id)
60+
return await AssistantFileService.delete_assistant_file(session=session, assistant_id=assistant_id, file_id=file_id)

app/api/v1/files.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
from typing import Optional, List
55

66
from fastapi import APIRouter, Depends, UploadFile, Form, HTTPException, Query
7-
from sqlmodel import Session
87
from starlette.responses import StreamingResponse
8+
from sqlalchemy.ext.asyncio import AsyncSession
99

10-
from app.api.deps import get_session
10+
from app.api.deps import get_async_session
1111
from app.models import File
1212
from app.schemas.common import DeleteResponse
1313
from app.schemas.files import ListFilesResponse
@@ -22,22 +22,22 @@
2222

2323

2424
@router.get("", response_model=ListFilesResponse)
25-
def list_files(
25+
async def list_files(
2626
*,
2727
purpose: Optional[str] = None,
2828
file_ids: Optional[List[str]] = Query(None, alias="ids[]"),
29-
session: Session = Depends(get_session),
29+
session: AsyncSession = Depends(get_async_session),
3030
) -> ListFilesResponse:
3131
"""
3232
Returns a list of files that belong to the user's organization.
3333
"""
34-
files = FileService.get_file_list(session=session, purpose=purpose, file_ids=file_ids)
34+
files = await FileService.get_file_list(session=session, purpose=purpose, file_ids=file_ids)
3535
return ListFilesResponse(data=files)
3636

3737

3838
@router.post("", response_model=File)
39-
def create_file(
40-
*, session: Session = Depends(get_session), purpose: str = Form(default="assistants"), file: UploadFile
39+
async def create_file(
40+
*, session: AsyncSession = Depends(get_async_session), purpose: str = Form(default="assistants"), file: UploadFile
4141
) -> File:
4242
"""
4343
The size of individual files can be a maximum of 512 MB. See the [Assistants Tools guide]
@@ -51,31 +51,31 @@ def create_file(
5151
if file.size == 0 or file.size > max_size:
5252
raise HTTPException(status_code=413, detail="File too large")
5353

54-
return FileService.create_file(session=session, purpose=purpose, file=file)
54+
return await FileService.create_file(session=session, purpose=purpose, file=file)
5555

5656

5757
@router.delete("/{file_id}", response_model=DeleteResponse)
58-
def delete_file(*, session: Session = Depends(get_session), file_id: str) -> DeleteResponse:
58+
async def delete_file(*, session: AsyncSession = Depends(get_async_session), file_id: str) -> DeleteResponse:
5959
"""
6060
Delete a file.
6161
"""
62-
return FileService.delete_file(session=session, file_id=file_id)
62+
return await FileService.delete_file(session=session, file_id=file_id)
6363

6464

6565
@router.get("/{file_id}", response_model=File)
66-
def retrieve_file(*, session: Session = Depends(get_session), file_id: str) -> File:
66+
async def retrieve_file(*, session: AsyncSession = Depends(get_async_session), file_id: str) -> File:
6767
"""
6868
Returns information about a specific file.
6969
"""
70-
return FileService.get_file(session=session, file_id=file_id)
70+
return await FileService.get_file(session=session, file_id=file_id)
7171

7272

7373
@router.get("/{file_id}/content", response_class=StreamingResponse)
74-
def download_file(*, file_id: str, session: Session = Depends(get_session)):
74+
async def download_file(*, file_id: str, session: AsyncSession = Depends(get_async_session)):
7575
"""
7676
Returns the contents of the specified file.
7777
"""
78-
file_data, filename = FileService.get_file_content(session=session, file_id=file_id)
78+
file_data, filename = await FileService.get_file_content(session=session, file_id=file_id)
7979

8080
response = StreamingResponse(io.BytesIO(file_data), media_type="application/octet-stream")
8181
response.headers["Content-Disposition"] = f"attachment; filename*=UTF-8''{urllib.parse.quote(filename)}"

0 commit comments

Comments
 (0)