File size: 2,197 Bytes
732b14f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
"""Phase 3 stubs: job models and queue gating."""

from __future__ import annotations

import json

from app.jobs.models import GenerationJob, JobType


def test_generation_job_roundtrip() -> None:
    job = GenerationJob(
        job_type=JobType.generate,
        report_id="r1",
        tenant_id="t1",
        payload={"template_id": "E1", "bullets": ["note"]},
    )
    raw = job.model_dump_json()
    back = GenerationJob.model_validate_json(raw)
    assert back.job_type == JobType.generate
    assert json.loads(raw)["report_id"] == "r1"


async def test_dispatch_or_enqueue_falls_back_on_redis_error(monkeypatch) -> None:
    import asyncio

    from app.jobs.models import GenerationJob, JobType
    from app.jobs import queue as jq

    monkeypatch.setattr("app.jobs.queue.settings.enable_job_queue", True)
    monkeypatch.setattr("app.jobs.queue.settings.redis_url", "redis://localhost:6379/0")

    async def _boom(_job: GenerationJob) -> None:
        raise ConnectionError("redis down")

    monkeypatch.setattr(jq, "enqueue_generation_job", _boom)

    ran: list[str] = []
    spawned: list[asyncio.Task] = []

    async def _inline() -> None:
        ran.append("yes")

    def _capture_task(coro) -> asyncio.Task:  # type: ignore[no-untyped-def]
        t = asyncio.create_task(coro)
        spawned.append(t)
        return t

    monkeypatch.setattr("app.api.background_tasks.spawn_background_task", _capture_task)

    mode = await jq.dispatch_or_enqueue(
        job=GenerationJob(
            job_type=JobType.generate,
            report_id="r1",
            tenant_id="t1",
            payload={},
        ),
        inline_factory=_inline,
    )
    if spawned:
        await asyncio.gather(*spawned)
    assert mode == "inline"
    assert ran == ["yes"]


def test_job_queue_active_requires_redis(monkeypatch) -> None:
    from app.jobs import queue as jq

    monkeypatch.setattr("app.jobs.queue.settings.enable_job_queue", True)
    monkeypatch.setattr("app.jobs.queue.settings.redis_url", "")
    assert jq.job_queue_active() is False

    monkeypatch.setattr("app.jobs.queue.settings.redis_url", "redis://localhost:6379/0")
    assert jq.job_queue_active() is True