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) <noreply@anthropic.com>
@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) <noreply@anthropic.com>
@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) <noreply@anthropic.com>
@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
@xr843 xr843 deleted the refactor/sessionmaker-service-inner-api branch April 2, 2026 05:35
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