summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test_contributions_api.py4
-rw-r--r--tests/test_ingestion.py48
-rw-r--r--tests/test_migrations.py3
3 files changed, 54 insertions, 1 deletions
diff --git a/tests/test_contributions_api.py b/tests/test_contributions_api.py
index 22d0af3..f2b8564 100644
--- a/tests/test_contributions_api.py
+++ b/tests/test_contributions_api.py
@@ -63,6 +63,9 @@ def test_public_read_registers_actor_for_lazy_indexing(client: TestClient, db_se
assert response.status_code == 200
assert response.json()["is_indexed"] is False
assert response.json()["indexing_state"] == "pending"
+ assert response.json()["is_backfilled"] is False
+ assert response.json()["backfill_state"] == "pending"
+ assert response.json()["backfill_completed_at"] is None
assert response.json()["last_polled_at"] is None
assert tracked_actor is not None
assert tracked_actor.is_active is True
@@ -107,6 +110,7 @@ def test_contribution_stats_api(client: TestClient, db_session) -> None:
assert response.json()["current_streak"] == 2
assert response.json()["is_indexed"] is True
assert response.json()["indexing_state"] == "indexed"
+ assert response.json()["is_backfilled"] is False
def test_invalid_date_input_returns_400(client: TestClient) -> None:
diff --git a/tests/test_ingestion.py b/tests/test_ingestion.py
index 3b7db16..857f1aa 100644
--- a/tests/test_ingestion.py
+++ b/tests/test_ingestion.py
@@ -4,10 +4,11 @@ from sqlalchemy import select
from srht_contrib.config import Settings
from srht_contrib.jobs.poller import PollerService
-from srht_contrib.models import SyncState, TrackedActor, TrackedRepository
+from srht_contrib.models import ServiceBackfillState, SyncState, TrackedActor, TrackedRepository
from srht_contrib.schemas import NormalizedEvent
from srht_contrib.services.git import GitIngestionService, GitPollResult
from srht_contrib.services.todo import TodoIngestionService, TodoPollResult
+from srht_contrib.services.types import BackfillBatchResult
class StubClient:
@@ -37,6 +38,9 @@ class RecordingTodoService:
events = self.events_by_call.pop(0)
return TodoPollResult(events=events, cursor="2026-03-31T00:00:00+00:00")
+ def fetch_backfill_batch(self, actor: str, cursor_state: dict | None = None) -> BackfillBatchResult:
+ return BackfillBatchResult(events=[], cursor_state=None, complete=True)
+
class EmptyGitService:
service_name = "git"
@@ -54,6 +58,30 @@ class EmptyGitService:
def fetch_recent_events(self, actor: str, since: datetime | None = None, repositories=None) -> GitPollResult:
return GitPollResult(events=[], cursor="2026-03-31T00:00:00+00:00")
+ def fetch_backfill_batch(self, actor: str, cursor_state: dict | None = None) -> BackfillBatchResult:
+ return BackfillBatchResult(events=[], cursor_state=None, complete=True)
+
+
+class BackfillingTodoService:
+ service_name = "todo"
+
+ def fetch_recent_events(self, actor: str, since: datetime | None = None) -> TodoPollResult:
+ return TodoPollResult(events=[], cursor="2026-03-31T00:00:00+00:00")
+
+ def fetch_backfill_batch(self, actor: str, cursor_state: dict | None = None) -> BackfillBatchResult:
+ event = NormalizedEvent(
+ service="todo",
+ event_type="ticket_created",
+ actor=actor,
+ repo_name="todo",
+ resource_id="backfill-ticket",
+ external_uid=f"todo:backfill:{actor}",
+ occurred_at=datetime(2024, 1, 1, 12, 0, tzinfo=UTC),
+ weight=1.0,
+ raw_payload_json=None,
+ )
+ return BackfillBatchResult(events=[event], cursor_state=None, complete=True)
+
def make_settings(**overrides) -> Settings:
values = {
@@ -424,3 +452,21 @@ def test_scheduled_poll_polls_known_actors_and_seeds_default_actor(db_session) -
assert [actor.actor for actor in tracked_actors] == ["~default", "~known"]
assert all(actor.last_poll_status == "indexed" for actor in tracked_actors)
assert all(actor.last_polled_at is not None for actor in tracked_actors)
+
+
+def test_poll_marks_backfill_complete_and_persists_service_state(db_session) -> None:
+ poller = PollerService(todo_service=BackfillingTodoService(), git_service=EmptyGitService())
+
+ inserted = poller.poll_all(db_session, "~ccleberg")
+
+ tracked_actor = db_session.scalar(select(TrackedActor).where(TrackedActor.actor == "~ccleberg"))
+ service_states = db_session.scalars(
+ select(ServiceBackfillState).where(ServiceBackfillState.actor == "~ccleberg").order_by(ServiceBackfillState.service)
+ ).all()
+
+ assert inserted == 1
+ assert tracked_actor is not None
+ assert tracked_actor.backfill_status == "completed"
+ assert tracked_actor.backfill_completed_at is not None
+ assert [state.service for state in service_states] == ["git", "todo"]
+ assert all(state.status == "completed" for state in service_states)
diff --git a/tests/test_migrations.py b/tests/test_migrations.py
index 505ddb3..6173693 100644
--- a/tests/test_migrations.py
+++ b/tests/test_migrations.py
@@ -21,6 +21,7 @@ def test_alembic_upgrade_creates_schema(tmp_path) -> None:
"actor_aliases",
"alembic_version",
"contribution_events",
+ "service_backfill_states",
"sync_states",
"tracked_actors",
"tracked_repositories",
@@ -117,6 +118,7 @@ def test_alembic_upgrade_adopts_legacy_schema(tmp_path) -> None:
assert "uq_tracked_repository_service_actor_name" in unique_constraints
assert actor == Settings().default_actor
assert "tracked_actors" in inspector.get_table_names()
+ assert "service_backfill_states" in inspector.get_table_names()
def test_alembic_prefers_database_url_from_environment(tmp_path, monkeypatch) -> None:
@@ -131,3 +133,4 @@ def test_alembic_prefers_database_url_from_environment(tmp_path, monkeypatch) ->
inspector = inspect(create_engine(database_url))
assert "actor_aliases" in inspector.get_table_names()
assert "tracked_actors" in inspector.get_table_names()
+ assert "service_backfill_states" in inspector.get_table_names()