svcforge: reference implementation
ci / lint (push) Successful in 1m19s
ci / unit (push) Failing after 1m2s
ci / integration (push) Has been skipped
ci / types (push) Successful in 1m37s
ci / security (push) Failing after 38s
ci / dockerfile (push) Successful in 14s
ci / image (api) (push) Has been skipped
ci / image (reconciler) (push) Has been skipped
ci / image (worker) (push) Has been skipped
ci / bump (push) Has been skipped

Complete working build of the system learn-python/ teaches.
164 tests, mypy --strict clean, domain coverage 99%.
This commit is contained in:
Nguyen Minh Phuc
2026-07-17 10:44:54 +00:00
commit 50c2fe2a1e
102 changed files with 12018 additions and 0 deletions
+43
View File
@@ -0,0 +1,43 @@
"""The claim race. If only one test in this repo survives, it should be this one."""
from __future__ import annotations
import asyncio
from svcforge_core.domain.models import TaskKind
from svcforge_core.repo.db import DictPool
from svcforge_core.repo.tasks import TaskRepo
from tests.integration.helpers import make_instance
async def test_skip_locked_claims_each_task_exactly_once(pool: DictPool) -> None:
"""50 workers, 50 tasks, one claim each — no double-claims, no lost tasks.
This is the test that fails if you split the claim into select-then-update.
"""
repo = TaskRepo(pool)
inst = await make_instance(pool)
ids = {await repo.enqueue_standalone(inst, TaskKind.PROVISION) for _ in range(50)}
async with asyncio.TaskGroup() as tg:
claims = [tg.create_task(repo.claim(f"w{i}")) for i in range(50)]
got = [c.result() for c in claims]
assert all(t is not None for t in got)
assert sorted(t.id for t in got if t is not None) == sorted(ids) # each exactly once
assert all(t.attempts == 1 for t in got if t is not None)
async def test_more_workers_than_tasks_get_none_not_a_duplicate(pool: DictPool) -> None:
"""Contention must produce None for the losers, never a second claim on one row."""
repo = TaskRepo(pool)
inst = await make_instance(pool)
await repo.enqueue_standalone(inst, TaskKind.PROVISION)
async with asyncio.TaskGroup() as tg:
claims = [tg.create_task(repo.claim(f"w{i}")) for i in range(10)]
got = [c.result() for c in claims]
won = [t for t in got if t is not None]
assert len(won) == 1
assert len([t for t in got if t is None]) == 9