mirror of
https://github.com/langgenius/dify.git
synced 2026-04-19 18:27:27 +08:00
fix(api): use lazy workflow persistence for transparent upgrade of old apps
VirtualWorkflowSynthesizer.ensure_workflow() creates a real draft
workflow on first call for a legacy app, persisting it to the database.
On subsequent calls, returns the existing draft.
This is needed because AdvancedChatAppGenerator's worker thread looks
up workflows from the database by ID. Instead of hacking the generator
to skip DB lookups, we treat this as a lazy one-time upgrade: the old
app gets a real workflow that can also be edited in the workflow editor.
Verified: old chat app created on main branch ("What is 2+2?" -> "Four")
and old agent-chat app ("Say hello" -> "Hello!") both successfully
execute through the Agent V2 engine with AGENT_V2_TRANSPARENT_UPGRADE=true.
Made-with: Cursor
This commit is contained in:
@ -133,17 +133,13 @@ class AppGenerateService:
|
||||
from services.workflow.virtual_workflow import VirtualWorkflowSynthesizer
|
||||
|
||||
try:
|
||||
virtual_workflow = VirtualWorkflowSynthesizer.synthesize(app_model)
|
||||
workflow = VirtualWorkflowSynthesizer.ensure_workflow(app_model)
|
||||
logger.info(
|
||||
"[AGENT_V2_UPGRADE] Transparent upgrade for app %s (mode=%s)",
|
||||
"[AGENT_V2_UPGRADE] Transparent upgrade for app %s (mode=%s), wf=%s",
|
||||
app_model.id,
|
||||
effective_mode,
|
||||
workflow.id,
|
||||
)
|
||||
workflow_id_arg = args.get("workflow_id")
|
||||
if not workflow_id_arg:
|
||||
workflow = virtual_workflow
|
||||
else:
|
||||
workflow = cls._get_workflow(app_model, invoke_from, workflow_id_arg)
|
||||
|
||||
if streaming:
|
||||
with rate_limit_context(rate_limit, request_id):
|
||||
|
||||
@ -73,6 +73,36 @@ class VirtualWorkflowSynthesizer:
|
||||
|
||||
return workflow
|
||||
|
||||
@staticmethod
|
||||
def ensure_workflow(app: App) -> Any:
|
||||
"""Ensure the old app has a workflow, creating one if needed.
|
||||
|
||||
On first call for a legacy app, synthesizes a workflow from its
|
||||
AppModelConfig and persists it as a draft. On subsequent calls,
|
||||
returns the existing draft. This is a one-time lazy upgrade:
|
||||
the app gets a real workflow that can be edited in the workflow editor.
|
||||
|
||||
The app's workflow_id is NOT updated (preserving its legacy state),
|
||||
but the workflow is findable via app_id + version="draft".
|
||||
"""
|
||||
from models.workflow import Workflow
|
||||
|
||||
from extensions.ext_database import db
|
||||
|
||||
existing = db.session.query(Workflow).filter_by(
|
||||
app_id=app.id, version="draft"
|
||||
).first()
|
||||
if existing:
|
||||
return existing
|
||||
|
||||
workflow = VirtualWorkflowSynthesizer.synthesize(app)
|
||||
workflow.version = "draft"
|
||||
|
||||
db.session.add(workflow)
|
||||
db.session.commit()
|
||||
logger.info("Created draft workflow %s for legacy app %s", workflow.id, app.id)
|
||||
return workflow
|
||||
|
||||
|
||||
def _extract_model_config(config: AppModelConfig) -> dict[str, Any]:
|
||||
if config.model:
|
||||
|
||||
Reference in New Issue
Block a user