refactor(api): extract workflow statistic query service (#41271)

This commit is contained in:
非法操作 authored and GitHub committed 2026-08-27 02:41:02 +00:00
1 parent ce31cdc585
commit 5a6191b96b
6 files changed
+409 -146

No files matched your search

@@ -5,13 +5,14 @@ from __future__ import annotations
import uuid
from collections.abc import Iterator
from inspect import unwrap
from types import SimpleNamespace
from unittest.mock import MagicMock, patch
import pytest
from flask import Flask
from pydantic import ValidationError
from sqlalchemy import Engine
from sqlalchemy.orm import Session, sessionmaker
from sqlalchemy.orm import Session
from werkzeug.exceptions import BadRequest, NotFound
from controllers.console import console_ns
@@ -70,7 +71,6 @@ from models import App, Site
from models.account import Account, AccountStatus
from models.engine import db
from models.trigger import WorkflowWebhookTrigger
from repositories.sqlalchemy_api_workflow_run_repository import DifyAPISQLAlchemyWorkflowRunRepository
from services.app_site_service import (
AppSiteAppNotFoundError,
AppSiteChanges,
@@ -106,6 +106,15 @@ def _make_app(
return app
def _make_request_context() -> RequestContext:
return RequestContext(
request_id="request-1",
trace_id="trace-1",
account_id=USER_ID,
active_workspace_id=TENANT_ID,
)
@pytest.fixture
def database_app() -> Iterator[Flask]:
app = Flask(__name__)
@@ -690,48 +699,162 @@ class TestWorkflowStatisticEndpoints:
assert query.end is None
def test_workflow_daily_runs_statistic(self, database_app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
repository = DifyAPISQLAlchemyWorkflowRunRepository(
session_maker=sessionmaker(bind=db.engine, expire_on_commit=False)
)
monkeypatch.setattr(
repository,
"get_daily_runs_statistics",
lambda **_kwargs: [{"date": "2024-01-01"}],
)
monkeypatch.setattr(
workflow_statistic_module.DifyAPIRepositoryFactory,
"create_api_workflow_run_repository",
lambda *_args, **_kwargs: repository,
)
service = MagicMock()
service.get_daily_runs.return_value = [{"date": "2024-01-01", "runs": 2}]
monkeypatch.setattr(
workflow_statistic_module,
"parse_time_range",
lambda *_args, **_kwargs: (None, None),
"application_services",
lambda: SimpleNamespace(workflow_statistics=service),
)
self._patch_statistic_time_range(monkeypatch)
api = workflow_statistic_module.WorkflowDailyRunsStatistic()
method = unwrap(api.get)
request_context = _make_request_context()
with database_app.test_request_context("/"):
account = _make_account()
account.timezone = "UTC"
response = method(api, WorkflowStatisticQuery(), account, app_model=_make_app("app-1", tenant_id="t1"))
response = method(
api,
WorkflowStatisticQuery(),
request_context,
app_model=_make_app("app-1", tenant_id="t1"),
)
assert response.get_json() == {"data": [{"date": "2024-01-01"}]}
assert response == {"data": [{"date": "2024-01-01", "runs": 2}]}
service.get_daily_runs.assert_called_once_with(
request_context,
app_id="app-1",
start_date=None,
end_date=None,
timezone="UTC",
)
def test_workflow_daily_terminals_statistic(self, database_app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
repository = DifyAPISQLAlchemyWorkflowRunRepository(
session_maker=sessionmaker(bind=db.engine, expire_on_commit=False)
service = MagicMock()
service.get_daily_terminals.return_value = [{"date": "2024-01-02", "terminal_count": 3}]
monkeypatch.setattr(
workflow_statistic_module,
"application_services",
lambda: SimpleNamespace(workflow_statistics=service),
)
self._patch_statistic_time_range(monkeypatch)
api = workflow_statistic_module.WorkflowDailyTerminalsStatistic()
method = unwrap(api.get)
request_context = _make_request_context()
with database_app.test_request_context("/"):
response = method(
api,
WorkflowStatisticQuery(),
request_context,
app_model=_make_app("app-1", tenant_id="t1"),
)
assert response == {"data": [{"date": "2024-01-02", "terminal_count": 3}]}
service.get_daily_terminals.assert_called_once_with(
request_context,
app_id="app-1",
start_date=None,
end_date=None,
timezone="UTC",
)
def test_workflow_daily_token_cost_statistic(
self,
database_app: Flask,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service = MagicMock()
service.get_daily_token_costs.return_value = [{"date": "2024-01-03", "token_count": 4}]
monkeypatch.setattr(
workflow_statistic_module,
"application_services",
lambda: SimpleNamespace(workflow_statistics=service),
)
self._patch_statistic_time_range(monkeypatch)
api = workflow_statistic_module.WorkflowDailyTokenCostStatistic()
method = unwrap(api.get)
request_context = _make_request_context()
with database_app.test_request_context("/"):
response = method(
api,
WorkflowStatisticQuery(),
request_context,
app_model=_make_app("app-1", tenant_id="t1"),
)
assert response == {"data": [{"date": "2024-01-03", "token_count": 4}]}
service.get_daily_token_costs.assert_called_once_with(
request_context,
app_id="app-1",
start_date=None,
end_date=None,
timezone="UTC",
)
def test_workflow_average_app_interaction_statistic(
self,
database_app: Flask,
monkeypatch: pytest.MonkeyPatch,
) -> None:
service = MagicMock()
service.get_average_app_interactions.return_value = [{"date": "2024-01-04", "interactions": 2.5}]
monkeypatch.setattr(
workflow_statistic_module,
"application_services",
lambda: SimpleNamespace(workflow_statistics=service),
)
self._patch_statistic_time_range(monkeypatch)
api = workflow_statistic_module.WorkflowAverageAppInteractionStatistic()
method = unwrap(api.get)
request_context = _make_request_context()
with database_app.test_request_context("/"):
response = method(
api,
WorkflowStatisticQuery(),
request_context,
app_model=_make_app("app-1", tenant_id="t1"),
)
assert response == {"data": [{"date": "2024-01-04", "interactions": 2.5}]}
service.get_average_app_interactions.assert_called_once_with(
request_context,
app_id="app-1",
start_date=None,
end_date=None,
timezone="UTC",
)
def test_workflow_statistic_invalid_time_range(self, monkeypatch: pytest.MonkeyPatch) -> None:
account = _make_account()
account.timezone = "UTC"
monkeypatch.setattr(
workflow_statistic_module,
"current_account_with_tenant",
lambda: SimpleNamespace(account=account),
)
monkeypatch.setattr(
repository,
"get_daily_terminals_statistics",
lambda **_kwargs: [{"date": "2024-01-02"}],
workflow_statistic_module,
"parse_time_range",
MagicMock(side_effect=ValueError("invalid range")),
)
with pytest.raises(BadRequest, match="invalid range"):
workflow_statistic_module._resolve_statistic_time_range(WorkflowStatisticQuery())
@staticmethod
def _patch_statistic_time_range(monkeypatch: pytest.MonkeyPatch) -> None:
account = _make_account()
account.timezone = "UTC"
monkeypatch.setattr(
workflow_statistic_module.DifyAPIRepositoryFactory,
"create_api_workflow_run_repository",
lambda *_args, **_kwargs: repository,
workflow_statistic_module,
"current_account_with_tenant",
lambda: SimpleNamespace(account=account),
)
monkeypatch.setattr(
workflow_statistic_module,
@@ -739,16 +862,6 @@ class TestWorkflowStatisticEndpoints:
lambda *_args, **_kwargs: (None, None),
)
api = workflow_statistic_module.WorkflowDailyTerminalsStatistic()
method = unwrap(api.get)
with database_app.test_request_context("/"):
account = _make_account()
account.timezone = "UTC"
response = method(api, WorkflowStatisticQuery(), account, app_model=_make_app("app-1", tenant_id="t1"))
assert response.get_json() == {"data": [{"date": "2024-01-02"}]}
class TestWorkflowTriggerEndpoints:
def test_webhook_trigger_payload(self):