add seed fake logs

This commit is contained in:
hjlarry 2025-12-12 10:19:44 +08:00
parent dd949a23e1
commit 912ca2bcfe
2 changed files with 136 additions and 0 deletions

View File

@ -4,6 +4,7 @@ import json
import logging import logging
import secrets import secrets
from typing import Any from typing import Any
from uuid import uuid4
import click import click
import sqlalchemy as sa import sqlalchemy as sa
@ -41,6 +42,14 @@ from models.provider import Provider, ProviderModel
from models.provider_ids import DatasourceProviderID, ToolProviderID from models.provider_ids import DatasourceProviderID, ToolProviderID
from models.source import DataSourceApiKeyAuthBinding, DataSourceOauthBinding from models.source import DataSourceApiKeyAuthBinding, DataSourceOauthBinding
from models.tools import ToolOAuthSystemClient from models.tools import ToolOAuthSystemClient
from models.trigger import AppTriggerType, WorkflowTriggerLog, WorkflowTriggerStatus
from models.workflow import (
WorkflowAppLog,
WorkflowNodeExecutionModel,
WorkflowNodeExecutionTriggeredFrom,
WorkflowPause,
WorkflowRun,
)
from services.account_service import AccountService, RegisterService, TenantService from services.account_service import AccountService, RegisterService, TenantService
from services.clear_free_plan_expired_workflow_run_logs import WorkflowRunCleanup from services.clear_free_plan_expired_workflow_run_logs import WorkflowRunCleanup
from services.clear_free_plan_tenant_expired_logs import ClearFreePlanTenantExpiredLogs from services.clear_free_plan_tenant_expired_logs import ClearFreePlanTenantExpiredLogs
@ -893,6 +902,131 @@ def clean_workflow_runs(
click.echo(click.style("Workflow run cleanup completed.", fg="green")) click.echo(click.style("Workflow run cleanup completed.", fg="green"))
@click.command(
"seed-expired-workflow-runs",
help="Test-only: create synthetic expired workflow runs (with related records) for cleanup validation.",
)
@click.option("--days-ago", default=40, show_default=True, help="Backdate created_at to N days ago.")
@click.option("--limit", default=5, show_default=True, help="Number of workflow runs to create.")
@click.option(
"--tenant-id",
default=None,
help="Optional tenant id to use; if omitted, a random tenant id is generated.",
)
def seed_expired_workflow_runs(days_ago: int, limit: int, tenant_id: str | None) -> None:
base_time = datetime.datetime.now() - datetime.timedelta(days=days_ago)
tenant = tenant_id or str(uuid4())
with sessionmaker(db.engine, expire_on_commit=False).begin() as session:
for i in range(limit):
run_id = str(uuid4())
app_id = str(uuid4())
workflow_id = str(uuid4())
creator_id = str(uuid4())
created_at = base_time - datetime.timedelta(minutes=i)
run = WorkflowRun(
id=run_id,
tenant_id=tenant,
app_id=app_id,
workflow_id=workflow_id,
type="workflow",
triggered_from="app-run",
version="v1",
graph="{}",
inputs="{}",
status="succeeded",
outputs="{}",
error=None,
elapsed_time=0.1,
total_tokens=0,
total_steps=0,
created_by_role="account",
created_by=creator_id,
created_at=created_at,
finished_at=created_at + datetime.timedelta(seconds=1),
exceptions_count=0,
)
node_execution = WorkflowNodeExecutionModel(
id=str(uuid4()),
tenant_id=tenant,
app_id=app_id,
workflow_id=workflow_id,
triggered_from=WorkflowNodeExecutionTriggeredFrom.WORKFLOW_RUN.value,
workflow_run_id=run_id,
index=0,
predecessor_node_id=None,
node_execution_id=None,
node_id="start",
node_type="start",
title="Seeded node",
inputs="{}",
process_data="{}",
outputs="{}",
status="succeeded",
error=None,
elapsed_time=0.1,
execution_metadata="{}",
created_by_role="account",
created_by=creator_id,
created_at=created_at,
finished_at=created_at + datetime.timedelta(seconds=1),
)
app_log = WorkflowAppLog(
tenant_id=tenant,
app_id=app_id,
workflow_id=workflow_id,
workflow_run_id=run_id,
created_from="service-api",
created_by_role="account",
created_by=creator_id
)
trigger_log = WorkflowTriggerLog(
tenant_id=tenant,
app_id=app_id,
workflow_id=workflow_id,
workflow_run_id=run_id,
root_node_id=None,
trigger_metadata="{}",
trigger_type=AppTriggerType.TRIGGER_WEBHOOK,
trigger_data="{}",
inputs="{}",
outputs="{}",
status=WorkflowTriggerStatus.SUCCEEDED,
error=None,
queue_name="seed",
celery_task_id=None,
created_by_role="account",
created_by=creator_id,
retry_count=0,
elapsed_time=0.1,
total_tokens=0,
triggered_at=created_at,
finished_at=created_at + datetime.timedelta(seconds=1),
)
pause = WorkflowPause(
workflow_id=workflow_id,
workflow_run_id=run_id,
resumed_at=None,
state_object_key="seeded-state",
created_at=created_at,
updated_at=created_at,
)
session.add_all([run, node_execution, app_log, trigger_log, pause])
click.echo(
click.style(
f"Created {limit} synthetic workflow runs (tenant={tenant}) backdated ~{days_ago} days.",
fg="green",
)
)
@click.option("-f", "--force", is_flag=True, help="Skip user confirmation and force the command to execute.") @click.option("-f", "--force", is_flag=True, help="Skip user confirmation and force the command to execute.")
@click.command("clear-orphaned-file-records", help="Clear orphaned file records.") @click.command("clear-orphaned-file-records", help="Clear orphaned file records.")
def clear_orphaned_file_records(force: bool): def clear_orphaned_file_records(force: bool):

View File

@ -22,6 +22,7 @@ def init_app(app: DifyApp):
reset_email, reset_email,
reset_encrypt_key_pair, reset_encrypt_key_pair,
reset_password, reset_password,
seed_expired_workflow_runs,
setup_datasource_oauth_client, setup_datasource_oauth_client,
setup_system_tool_oauth_client, setup_system_tool_oauth_client,
setup_system_trigger_oauth_client, setup_system_trigger_oauth_client,
@ -56,6 +57,7 @@ def init_app(app: DifyApp):
transform_datasource_credentials, transform_datasource_credentials,
install_rag_pipeline_plugins, install_rag_pipeline_plugins,
clean_workflow_runs, clean_workflow_runs,
seed_expired_workflow_runs,
] ]
for cmd in cmds_to_register: for cmd in cmds_to_register:
app.cli.add_command(cmd) app.cli.add_command(cmd)