test: migrate retention delete archived workflow run tests to testcon… (#34020)

This commit is contained in:
Desel72
2026-03-24 08:52:10 -05:00
committed by GitHub
parent 2a35f8a625
commit 4f87625df5
2 changed files with 70 additions and 216 deletions

View File

@ -141,3 +141,73 @@ class TestArchivedWorkflowRunDeletion:
db_session_with_containers.expunge_all()
deleted_run = db_session_with_containers.get(WorkflowRun, run_id)
assert deleted_run is None
def test_delete_run_dry_run(self, db_session_with_containers):
"""Dry run should return success without actually deleting."""
tenant_id = str(uuid4())
run = self._create_workflow_run(
db_session_with_containers,
tenant_id=tenant_id,
created_at=datetime.now(UTC),
)
run_id = run.id
deleter = ArchivedWorkflowRunDeletion(dry_run=True)
result = deleter._delete_run(run)
assert result.success is True
assert result.run_id == run_id
# Run should still exist because it's a dry run
db_session_with_containers.expire_all()
assert db_session_with_containers.get(WorkflowRun, run_id) is not None
def test_delete_run_exception_returns_error(self, db_session_with_containers):
"""Exception during deletion should return failure result."""
from unittest.mock import MagicMock, patch
tenant_id = str(uuid4())
run = self._create_workflow_run(
db_session_with_containers,
tenant_id=tenant_id,
created_at=datetime.now(UTC),
)
deleter = ArchivedWorkflowRunDeletion(dry_run=False)
with patch.object(deleter, "_get_workflow_run_repo") as mock_get_repo:
mock_repo = MagicMock()
mock_get_repo.return_value = mock_repo
mock_repo.delete_runs_with_related.side_effect = Exception("Database error")
result = deleter._delete_run(run)
assert result.success is False
assert result.error == "Database error"
def test_delete_by_run_id_success(self, db_session_with_containers):
"""Successfully delete an archived workflow run by ID."""
tenant_id = str(uuid4())
base_time = datetime.now(UTC)
run = self._create_workflow_run(
db_session_with_containers,
tenant_id=tenant_id,
created_at=base_time,
)
self._create_archive_log(db_session_with_containers, run=run)
run_id = run.id
deleter = ArchivedWorkflowRunDeletion()
result = deleter.delete_by_run_id(run_id)
assert result.success is True
db_session_with_containers.expunge_all()
assert db_session_with_containers.get(WorkflowRun, run_id) is None
def test_get_workflow_run_repo_caches_instance(self, db_session_with_containers):
"""_get_workflow_run_repo should return a cached repo on subsequent calls."""
deleter = ArchivedWorkflowRunDeletion()
repo1 = deleter._get_workflow_run_repo()
repo2 = deleter._get_workflow_run_repo()
assert repo1 is repo2
assert deleter.workflow_run_repo is repo1

View File

@ -1,216 +0,0 @@
from datetime import datetime
from unittest.mock import MagicMock, patch
import pytest
from sqlalchemy.orm import Session
from models.workflow import WorkflowRun
from services.retention.workflow_run.delete_archived_workflow_run import ArchivedWorkflowRunDeletion, DeleteResult
class TestArchivedWorkflowRunDeletion:
@pytest.fixture
def mock_db(self):
with patch("services.retention.workflow_run.delete_archived_workflow_run.db") as mock_db:
mock_db.engine = MagicMock()
yield mock_db
@pytest.fixture
def mock_sessionmaker(self):
with patch("services.retention.workflow_run.delete_archived_workflow_run.sessionmaker") as mock_sm:
mock_session = MagicMock(spec=Session)
mock_sm.return_value.return_value.__enter__.return_value = mock_session
yield mock_sm, mock_session
@pytest.fixture
def mock_workflow_run_repo(self):
with patch(
"services.retention.workflow_run.delete_archived_workflow_run.APIWorkflowRunRepository"
) as mock_repo_cls:
mock_repo = MagicMock()
yield mock_repo
def test_delete_by_run_id_success(self, mock_db, mock_sessionmaker):
mock_sm, mock_session = mock_sessionmaker
run_id = "run-123"
tenant_id = "tenant-456"
mock_run = MagicMock(spec=WorkflowRun)
mock_run.id = run_id
mock_run.tenant_id = tenant_id
mock_session.get.return_value = mock_run
deletion = ArchivedWorkflowRunDeletion()
with patch.object(deletion, "_get_workflow_run_repo") as mock_get_repo:
mock_repo = MagicMock()
mock_get_repo.return_value = mock_repo
mock_repo.get_archived_run_ids.return_value = [run_id]
with patch.object(deletion, "_delete_run") as mock_delete_run:
expected_result = DeleteResult(run_id=run_id, tenant_id=tenant_id, success=True)
mock_delete_run.return_value = expected_result
result = deletion.delete_by_run_id(run_id)
assert result == expected_result
mock_session.get.assert_called_once_with(WorkflowRun, run_id)
mock_repo.get_archived_run_ids.assert_called_once()
mock_delete_run.assert_called_once_with(mock_run)
def test_delete_by_run_id_not_found(self, mock_db, mock_sessionmaker):
mock_sm, mock_session = mock_sessionmaker
run_id = "run-123"
mock_session.get.return_value = None
deletion = ArchivedWorkflowRunDeletion()
with patch.object(deletion, "_get_workflow_run_repo"):
result = deletion.delete_by_run_id(run_id)
assert result.success is False
assert "not found" in result.error
assert result.run_id == run_id
def test_delete_by_run_id_not_archived(self, mock_db, mock_sessionmaker):
mock_sm, mock_session = mock_sessionmaker
run_id = "run-123"
mock_run = MagicMock(spec=WorkflowRun)
mock_run.id = run_id
mock_session.get.return_value = mock_run
deletion = ArchivedWorkflowRunDeletion()
with patch.object(deletion, "_get_workflow_run_repo") as mock_get_repo:
mock_repo = MagicMock()
mock_get_repo.return_value = mock_repo
mock_repo.get_archived_run_ids.return_value = []
result = deletion.delete_by_run_id(run_id)
assert result.success is False
assert "is not archived" in result.error
def test_delete_batch(self, mock_db, mock_sessionmaker):
mock_sm, mock_session = mock_sessionmaker
deletion = ArchivedWorkflowRunDeletion()
mock_run1 = MagicMock(spec=WorkflowRun)
mock_run1.id = "run-1"
mock_run2 = MagicMock(spec=WorkflowRun)
mock_run2.id = "run-2"
with patch.object(deletion, "_get_workflow_run_repo") as mock_get_repo:
mock_repo = MagicMock()
mock_get_repo.return_value = mock_repo
mock_repo.get_archived_runs_by_time_range.return_value = [mock_run1, mock_run2]
with patch.object(deletion, "_delete_run") as mock_delete_run:
mock_delete_run.side_effect = [
DeleteResult(run_id="run-1", tenant_id="t1", success=True),
DeleteResult(run_id="run-2", tenant_id="t1", success=True),
]
results = deletion.delete_batch(tenant_ids=["t1"], start_date=datetime.now(), end_date=datetime.now())
assert len(results) == 2
assert results[0].run_id == "run-1"
assert results[1].run_id == "run-2"
assert mock_delete_run.call_count == 2
def test_delete_run_dry_run(self):
deletion = ArchivedWorkflowRunDeletion(dry_run=True)
mock_run = MagicMock(spec=WorkflowRun)
mock_run.id = "run-123"
mock_run.tenant_id = "tenant-456"
result = deletion._delete_run(mock_run)
assert result.success is True
assert result.run_id == "run-123"
def test_delete_run_success(self):
deletion = ArchivedWorkflowRunDeletion(dry_run=False)
mock_run = MagicMock(spec=WorkflowRun)
mock_run.id = "run-123"
mock_run.tenant_id = "tenant-456"
with patch.object(deletion, "_get_workflow_run_repo") as mock_get_repo:
mock_repo = MagicMock()
mock_get_repo.return_value = mock_repo
mock_repo.delete_runs_with_related.return_value = {"workflow_runs": 1}
result = deletion._delete_run(mock_run)
assert result.success is True
assert result.deleted_counts == {"workflow_runs": 1}
def test_delete_run_exception(self):
deletion = ArchivedWorkflowRunDeletion(dry_run=False)
mock_run = MagicMock(spec=WorkflowRun)
mock_run.id = "run-123"
with patch.object(deletion, "_get_workflow_run_repo") as mock_get_repo:
mock_repo = MagicMock()
mock_get_repo.return_value = mock_repo
mock_repo.delete_runs_with_related.side_effect = Exception("Database error")
result = deletion._delete_run(mock_run)
assert result.success is False
assert result.error == "Database error"
def test_delete_trigger_logs(self):
mock_session = MagicMock(spec=Session)
run_ids = ["run-1", "run-2"]
with patch(
"services.retention.workflow_run.delete_archived_workflow_run.SQLAlchemyWorkflowTriggerLogRepository"
) as mock_repo_cls:
mock_repo = MagicMock()
mock_repo_cls.return_value = mock_repo
mock_repo.delete_by_run_ids.return_value = 5
count = ArchivedWorkflowRunDeletion._delete_trigger_logs(mock_session, run_ids)
assert count == 5
mock_repo_cls.assert_called_once_with(mock_session)
mock_repo.delete_by_run_ids.assert_called_once_with(run_ids)
def test_delete_node_executions(self):
mock_session = MagicMock(spec=Session)
mock_run = MagicMock(spec=WorkflowRun)
mock_run.id = "run-1"
runs = [mock_run]
with patch(
"repositories.factory.DifyAPIRepositoryFactory.create_api_workflow_node_execution_repository"
) as mock_create_repo:
mock_repo = MagicMock()
mock_create_repo.return_value = mock_repo
mock_repo.delete_by_runs.return_value = (1, 2)
with patch("services.retention.workflow_run.delete_archived_workflow_run.sessionmaker") as mock_sm:
result = ArchivedWorkflowRunDeletion._delete_node_executions(mock_session, runs)
assert result == (1, 2)
mock_create_repo.assert_called_once()
mock_repo.delete_by_runs.assert_called_once_with(mock_session, ["run-1"])
def test_get_workflow_run_repo(self, mock_db):
deletion = ArchivedWorkflowRunDeletion()
with patch(
"repositories.factory.DifyAPIRepositoryFactory.create_api_workflow_run_repository"
) as mock_create_repo:
mock_repo = MagicMock()
mock_create_repo.return_value = mock_repo
# First call
repo1 = deletion._get_workflow_run_repo()
assert repo1 == mock_repo
assert deletion.workflow_run_repo == mock_repo
# Second call (should return cached)
repo2 = deletion._get_workflow_run_repo()
assert repo2 == mock_repo
mock_create_repo.assert_called_once()