Skip to content

refactor: migrate service_api and inner_api to sessionmaker pattern#34379

Merged
asukaminato0721 merged 4 commits intolanggenius:mainfrom
xr843:refactor/sessionmaker-service-inner-api
Apr 1, 2026
Merged

refactor: migrate service_api and inner_api to sessionmaker pattern#34379
asukaminato0721 merged 4 commits intolanggenius:mainfrom
xr843:refactor/sessionmaker-service-inner-api

Conversation

@xr843
Copy link
Copy Markdown
Contributor

@xr843 xr843 commented Apr 1, 2026

Summary

Part of #24245. Migrate Session(db.engine) + manual session.commit() to sessionmaker(db.engine).begin() context manager in service_api and inner_api controllers.

This follows the same pattern established by the previous PRs (#24246, #29628, #33966, #34281-#34284) that already migrated the console controllers.

Changes

  • Replace Session(db.engine) with sessionmaker(db.engine).begin() in 3 files:
    • api/controllers/service_api/app/workflow.py
    • api/controllers/service_api/app/conversation.py
    • api/controllers/inner_api/plugin/wraps.py
  • Remove manual session.commit() calls (handled automatically by the context manager)
  • Replace session.commit() + session.refresh() with session.flush() + session.refresh() in wraps.py (flush sends to DB for refresh, commit happens automatically on context exit)
  • Use expire_on_commit=False where the session object is used outside the context manager
  • Remove unused Session import from workflow.py

Closes part of #24245

…er pattern

Part of langgenius#24245. Replace manual Session(db.engine) + session.commit()
with sessionmaker(db.engine).begin() context manager for automatic
transaction management.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@dosubot dosubot bot added size:S This PR changes 10-29 lines, ignoring generated files. refactor labels Apr 1, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Pyrefly Diff

No changes detected.

Update test mocks to match the refactored code that uses
sessionmaker(db.engine).begin() instead of Session(db.engine).
The mock chain is now: sessionmaker() -> .begin() -> __enter__().

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@xr843 xr843 requested a review from laipz8200 as a code owner April 1, 2026 06:31
@dosubot dosubot bot added size:M This PR changes 30-99 lines, ignoring generated files. and removed size:S This PR changes 10-29 lines, ignoring generated files. labels Apr 1, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Pyrefly Diff

No changes detected.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Pyrefly Diff

base → PR
--- /tmp/pyrefly_base.txt	2026-04-01 06:34:58.249330525 +0000
+++ /tmp/pyrefly_pr.txt	2026-04-01 06:34:47.158389448 +0000
@@ -2077,29 +2077,29 @@
 ERROR Could not find name `Import` [unknown-name]
    --> tests/unit_tests/controllers/inner_api/app/test_dsl.py:117:71
 ERROR Missing argument `tenant_model` in function `controllers.inner_api.plugin.wraps.decorated_view` [missing-argument]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:171:44
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:169:44
 ERROR Missing argument `user_model` in function `controllers.inner_api.plugin.wraps.decorated_view` [missing-argument]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:171:44
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:169:44
 ERROR Missing argument `tenant_model` in function `controllers.inner_api.plugin.wraps.decorated_view` [missing-argument]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:188:31
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:186:31
 ERROR Missing argument `user_model` in function `controllers.inner_api.plugin.wraps.decorated_view` [missing-argument]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:188:31
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:186:31
 ERROR Missing argument `tenant_model` in function `controllers.inner_api.plugin.wraps.decorated_view` [missing-argument]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:203:35
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:201:35
 ERROR Missing argument `user_model` in function `controllers.inner_api.plugin.wraps.decorated_view` [missing-argument]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:203:35
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:201:35
 ERROR Missing argument `tenant_model` in function `controllers.inner_api.plugin.wraps.decorated_view` [missing-argument]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:225:44
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:223:44
 ERROR Missing argument `user_model` in function `controllers.inner_api.plugin.wraps.decorated_view` [missing-argument]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:225:44
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:223:44
 ERROR Argument `type[PluginTestPayload]` is not assignable to parameter `payload_type` with type `type[BaseModel]` in function `controllers.inner_api.plugin.wraps.plugin_data` [bad-argument-type]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:253:35
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:251:35
 ERROR Argument `type[PluginTestPayload]` is not assignable to parameter `payload_type` with type `type[BaseModel]` in function `controllers.inner_api.plugin.wraps.plugin_data` [bad-argument-type]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:268:35
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:266:35
 ERROR Argument `type[TestPluginData.test_should_raise_error_on_invalid_payload.InvalidPayload]` is not assignable to parameter `payload_type` with type `type[BaseModel]` in function `controllers.inner_api.plugin.wraps.plugin_data` [bad-argument-type]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:286:35
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:284:35
 ERROR Argument `type[PluginTestPayload]` is not assignable to parameter `payload_type` with type `type[BaseModel]` in function `controllers.inner_api.plugin.wraps.plugin_data` [bad-argument-type]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:299:35
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:297:35
 ERROR Cannot index into `Iterable[bytes]` [bad-index]
    --> tests/unit_tests/controllers/service_api/app/test_audio.py:213:16
 ERROR Cannot index into `Response` [bad-index]

…() pattern

sessionmaker().begin() context manager auto-commits on exit,
so explicit session.commit() is no longer called in get_user().

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Pyrefly Diff

base → PR
--- /tmp/pyrefly_base.txt	2026-04-01 11:39:18.964249998 +0000
+++ /tmp/pyrefly_pr.txt	2026-04-01 11:39:07.369316640 +0000
@@ -2077,29 +2077,29 @@
 ERROR Could not find name `Import` [unknown-name]
    --> tests/unit_tests/controllers/inner_api/app/test_dsl.py:117:71
 ERROR Missing argument `tenant_model` in function `controllers.inner_api.plugin.wraps.decorated_view` [missing-argument]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:171:44
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:168:44
 ERROR Missing argument `user_model` in function `controllers.inner_api.plugin.wraps.decorated_view` [missing-argument]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:171:44
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:168:44
 ERROR Missing argument `tenant_model` in function `controllers.inner_api.plugin.wraps.decorated_view` [missing-argument]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:188:31
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:185:31
 ERROR Missing argument `user_model` in function `controllers.inner_api.plugin.wraps.decorated_view` [missing-argument]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:188:31
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:185:31
 ERROR Missing argument `tenant_model` in function `controllers.inner_api.plugin.wraps.decorated_view` [missing-argument]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:203:35
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:200:35
 ERROR Missing argument `user_model` in function `controllers.inner_api.plugin.wraps.decorated_view` [missing-argument]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:203:35
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:200:35
 ERROR Missing argument `tenant_model` in function `controllers.inner_api.plugin.wraps.decorated_view` [missing-argument]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:225:44
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:222:44
 ERROR Missing argument `user_model` in function `controllers.inner_api.plugin.wraps.decorated_view` [missing-argument]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:225:44
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:222:44
 ERROR Argument `type[PluginTestPayload]` is not assignable to parameter `payload_type` with type `type[BaseModel]` in function `controllers.inner_api.plugin.wraps.plugin_data` [bad-argument-type]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:253:35
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:250:35
 ERROR Argument `type[PluginTestPayload]` is not assignable to parameter `payload_type` with type `type[BaseModel]` in function `controllers.inner_api.plugin.wraps.plugin_data` [bad-argument-type]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:268:35
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:265:35
 ERROR Argument `type[TestPluginData.test_should_raise_error_on_invalid_payload.InvalidPayload]` is not assignable to parameter `payload_type` with type `type[BaseModel]` in function `controllers.inner_api.plugin.wraps.plugin_data` [bad-argument-type]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:286:35
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:283:35
 ERROR Argument `type[PluginTestPayload]` is not assignable to parameter `payload_type` with type `type[BaseModel]` in function `controllers.inner_api.plugin.wraps.plugin_data` [bad-argument-type]
-   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:299:35
+   --> tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py:296:35
 ERROR Cannot index into `Iterable[bytes]` [bad-index]
    --> tests/unit_tests/controllers/service_api/app/test_audio.py:213:16
 ERROR Cannot index into `Response` [bad-index]

@asukaminato0721 asukaminato0721 requested a review from Copilot April 1, 2026 14:53
@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Apr 1, 2026
@asukaminato0721 asukaminato0721 added this pull request to the merge queue Apr 1, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors service_api and inner_api controllers to use SQLAlchemy’s sessionmaker(...).begin() context manager pattern instead of Session(...) plus manual commit management, aligning these controllers with prior migrations in the codebase.

Changes:

  • Migrated DB session usage in service_api workflow/conversation endpoints to sessionmaker(db.engine).begin().
  • Updated inner_api plugin user lookup/creation to use sessionmaker(...).begin(), replacing commit()+refresh() with flush()+refresh().
  • Adjusted unit tests to patch/stub sessionmaker(...).begin() instead of Session(...).

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
api/controllers/service_api/app/workflow.py Replaces Session(db.engine) with sessionmaker(db.engine).begin() for workflow log retrieval.
api/controllers/service_api/app/conversation.py Migrates conversation list endpoint session handling to sessionmaker(db.engine).begin().
api/controllers/inner_api/plugin/wraps.py Migrates to sessionmaker(...).begin(), uses flush() before refresh(), and sets expire_on_commit=False.
api/tests/unit_tests/controllers/service_api/app/test_workflow.py Updates stubs/mocks/patches to match new sessionmaker(...).begin() usage.
api/tests/unit_tests/controllers/service_api/app/test_conversation.py Updates stubs/mocks to patch sessionmaker instead of Session.
api/tests/unit_tests/controllers/inner_api/plugin/test_plugin_wraps.py Updates patches/assertions for sessionmaker(...).begin() behavior and removes commit() expectation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

# get paginate workflow app logs
workflow_app_service = WorkflowAppService()
with Session(db.engine) as session:
with sessionmaker(db.engine).begin() as session:
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sessionmaker(db.engine).begin() will commit on context exit, and with SQLAlchemy’s default expire_on_commit=True this expires ORM instances. This endpoint returns a structure containing ORM-backed LogView/WorkflowAppLog objects that are marshalled after the method returns (outside the session context), which can trigger DetachedInstanceError when the marshaller accesses expired attributes. Consider using expire_on_commit=False for this sessionmaker (or fully serialize the response data inside the context) to avoid returning expired ORM objects.

Suggested change
with sessionmaker(db.engine).begin() as session:
with sessionmaker(bind=db.engine, expire_on_commit=False).begin() as session:

Copilot uses AI. Check for mistakes.
Merged via the queue into langgenius:main with commit 391007d Apr 1, 2026
31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm This PR has been approved by a maintainer refactor size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants