rewrite phase 1

This commit is contained in:
2026-07-22 23:10:23 +02:00
parent 7527831af6
commit 98ac4abca1
89 changed files with 9179 additions and 2795 deletions
+123
View File
@@ -0,0 +1,123 @@
import asyncio
import sqlite3
from contextlib import closing
from pathlib import Path
import pytest
from agentci.engine.events import PermissionDenied, PermissionGranted
from agentci.engine.model import IncomingCommand, QueueName, TaskKind
from agentci.engine.repository import Repository
MIGRATIONS = Path(__file__).parents[1] / "src" / "agentci" / "migrations"
@pytest.fixture
async def repository(tmp_path: Path) -> Repository:
value = Repository(tmp_path / "state.sqlite3", MIGRATIONS)
await value.initialize()
return value
def command(delivery: str, *, issue: int = 3) -> IncomingCommand:
return IncomingCommand(
delivery_id=delivery,
comment_id=int(delivery.rsplit("-", 1)[-1]),
repo_owner="alice",
repo_name="repo",
issue_number=issue,
pr_number=None,
requester="alice",
body="/agent plan",
)
async def test_concurrent_duplicate_accepts_create_one_job_and_event(
repository: Repository,
) -> None:
results = await asyncio.gather(
repository.accept(command("delivery-1")),
repository.accept(command("delivery-1")),
)
assert sorted(result.duplicate for result in results) == [False, True]
assert len({result.job.id for result in results}) == 1
with closing(sqlite3.connect(repository.database_path)) as connection, connection:
job_count = connection.execute("SELECT COUNT(*) FROM jobs").fetchone()
event_count = connection.execute("SELECT COUNT(*) FROM job_events").fetchone()
assert job_count == (1,)
assert event_count == (1,)
second = await repository.accept(command("delivery-2"))
assert second.job.receive_sequence == results[0].job.receive_sequence + 1
async def test_received_job_blocks_later_execute_task_for_same_target(
repository: Repository,
) -> None:
first = (await repository.accept(command("delivery-1"))).job
second = (await repository.accept(command("delivery-2"))).job
await repository.apply("grant-2", PermissionGranted(job_id=second.id))
assert await repository.claim_task(QueueName.JOBS) is None
await repository.apply("deny-1", PermissionDenied(job_id=first.id))
task = await repository.claim_task(QueueName.JOBS)
assert task is not None
assert task.job_id == second.id
assert task.kind is TaskKind.EXECUTE
async def test_received_job_does_not_block_a_different_target(
repository: Repository,
) -> None:
await repository.accept(command("delivery-1", issue=3))
second = (await repository.accept(command("delivery-2", issue=4))).job
await repository.apply("grant-2", PermissionGranted(job_id=second.id))
task = await repository.claim_task(QueueName.JOBS)
assert task is not None
assert task.job_id == second.id
async def test_claims_multiple_eligible_targets_without_duplicates(
repository: Repository,
) -> None:
first = (await repository.accept(command("delivery-1", issue=3))).job
second = (await repository.accept(command("delivery-2", issue=4))).job
await repository.apply("grant-1", PermissionGranted(job_id=first.id))
await repository.apply("grant-2", PermissionGranted(job_id=second.id))
claimed = [
await repository.claim_task(QueueName.JOBS),
await repository.claim_task(QueueName.JOBS),
]
assert [task.job_id for task in claimed if task is not None] == [first.id, second.id]
assert await repository.claim_task(QueueName.JOBS) is None
async def test_concurrent_claims_do_not_duplicate_task(repository: Repository) -> None:
await repository.accept(command("delivery-1"))
claims = await asyncio.gather(
repository.claim_task(QueueName.CONTROL),
repository.claim_task(QueueName.CONTROL),
)
claimed = [task for task in claims if task is not None]
assert len(claimed) == 1
assert claimed[0].kind is TaskKind.AUTHORIZE
assert claimed[0].queue is QueueName.CONTROL
assert await repository.claim_task(QueueName.CONTROL) is None
async def test_duplicate_event_id_cannot_be_reused_for_another_job(
repository: Repository,
) -> None:
first = (await repository.accept(command("delivery-1", issue=3))).job
second = (await repository.accept(command("delivery-2", issue=4))).job
await repository.apply("permission", PermissionGranted(job_id=first.id))
with pytest.raises(RuntimeError):
await repository.apply("permission", PermissionGranted(job_id=second.id))