implement job runner and scheduler
This commit is contained in:
parent
328a70ff9b
commit
2b2a3f1cc0
11 changed files with 1572 additions and 284 deletions
|
|
@ -5,7 +5,15 @@ from pathlib import Path
|
|||
from typing import Any, cast
|
||||
|
||||
from repub.datastar import RefreshBroker, render_sse_event, render_stream
|
||||
from repub.model import Job, Source, SourceFeed, SourcePangea, create_source
|
||||
from repub.model import (
|
||||
Job,
|
||||
JobExecution,
|
||||
JobExecutionStatus,
|
||||
Source,
|
||||
SourceFeed,
|
||||
SourcePangea,
|
||||
create_source,
|
||||
)
|
||||
from repub.web import (
|
||||
create_app,
|
||||
get_refresh_broker,
|
||||
|
|
@ -141,15 +149,20 @@ def test_render_stream_yields_on_connect_and_refresh() -> None:
|
|||
asyncio.run(run())
|
||||
|
||||
|
||||
def test_render_dashboard_shows_dashboard_information_architecture() -> None:
|
||||
def test_render_dashboard_shows_dashboard_information_architecture(
|
||||
monkeypatch, tmp_path: Path
|
||||
) -> None:
|
||||
db_path = tmp_path / "dashboard-render.db"
|
||||
monkeypatch.setenv("REPUBLISHER_DB_PATH", str(db_path))
|
||||
|
||||
async def run() -> None:
|
||||
body = str(await render_dashboard())
|
||||
app = create_app()
|
||||
body = str(await render_dashboard(app))
|
||||
|
||||
assert "Operational snapshot" in body
|
||||
assert "Running executions" in body
|
||||
assert 'href="/sources"' in body
|
||||
assert 'href="/runs"' in body
|
||||
assert "/job/7/execution/104/logs" in body
|
||||
assert "Create source" in body
|
||||
|
||||
asyncio.run(run())
|
||||
|
|
@ -569,27 +582,97 @@ def test_create_source_action_validates_duplicate_slug_and_pangea_type(
|
|||
asyncio.run(run())
|
||||
|
||||
|
||||
def test_render_runs_shows_running_upcoming_and_completed_tables() -> None:
|
||||
def test_render_runs_shows_running_upcoming_and_completed_tables(
|
||||
monkeypatch, tmp_path: Path
|
||||
) -> None:
|
||||
db_path = tmp_path / "runs-render.db"
|
||||
monkeypatch.setenv("REPUBLISHER_DB_PATH", str(db_path))
|
||||
|
||||
async def run() -> None:
|
||||
body = str(await render_runs())
|
||||
app = create_app()
|
||||
|
||||
source = create_source(
|
||||
name="Runs render source",
|
||||
slug="runs-render-source",
|
||||
source_type="feed",
|
||||
notes="",
|
||||
spider_arguments="",
|
||||
enabled=True,
|
||||
cron_minute="*/30",
|
||||
cron_hour="*",
|
||||
cron_day_of_month="*",
|
||||
cron_day_of_week="*",
|
||||
cron_month="*",
|
||||
feed_url="https://example.com/runs.xml",
|
||||
)
|
||||
job = Job.get(Job.source == source)
|
||||
execution = JobExecution.create(
|
||||
job=job,
|
||||
running_status=JobExecutionStatus.SUCCEEDED,
|
||||
)
|
||||
|
||||
body = str(await render_runs(app))
|
||||
|
||||
assert "Running job executions" in body
|
||||
assert "Upcoming jobs" in body
|
||||
assert "Completed job executions" in body
|
||||
assert "Delete confirmation" in body
|
||||
assert "/job/11/execution/101/logs" in body
|
||||
assert "Already running" in body
|
||||
assert "runs-render-source" in body
|
||||
assert f"/job/{job.id}/execution/{execution.get_id()}/logs" in body
|
||||
assert "Already running" not in body
|
||||
|
||||
asyncio.run(run())
|
||||
|
||||
|
||||
def test_render_execution_logs_uses_app_route() -> None:
|
||||
async def run() -> None:
|
||||
body = str(await render_execution_logs(job_id=7, execution_id=104))
|
||||
def test_render_execution_logs_uses_app_route(monkeypatch, tmp_path: Path) -> None:
|
||||
db_path = tmp_path / "logs-render.db"
|
||||
monkeypatch.setenv("REPUBLISHER_DB_PATH", str(db_path))
|
||||
|
||||
assert "Job 7 / execution 104" in body
|
||||
assert "/job/7/execution/104/logs" in body
|
||||
assert "Streaming text log view" in body
|
||||
async def run() -> None:
|
||||
log_dir = tmp_path / "out" / "logs"
|
||||
app = create_app()
|
||||
app.config["REPUB_LOG_DIR"] = log_dir
|
||||
|
||||
source = create_source(
|
||||
name="Log render source",
|
||||
slug="log-render-source",
|
||||
source_type="feed",
|
||||
notes="",
|
||||
spider_arguments="",
|
||||
enabled=False,
|
||||
cron_minute="*/30",
|
||||
cron_hour="*",
|
||||
cron_day_of_month="*",
|
||||
cron_day_of_week="*",
|
||||
cron_month="*",
|
||||
feed_url="https://example.com/logs.xml",
|
||||
)
|
||||
job = Job.get(Job.source == source)
|
||||
execution = JobExecution.create(
|
||||
job=job,
|
||||
running_status=JobExecutionStatus.RUNNING,
|
||||
)
|
||||
log_path = log_dir / f"job-{job.id}-execution-{execution.get_id()}.log"
|
||||
log_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
log_path.write_text(
|
||||
"\n".join(
|
||||
(
|
||||
"scheduler: run_now requested",
|
||||
"worker: starting simulated crawl",
|
||||
"worker: waiting for more log lines ...",
|
||||
)
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
body = str(
|
||||
await render_execution_logs(
|
||||
app, job_id=job.id, execution_id=int(execution.get_id())
|
||||
)
|
||||
)
|
||||
|
||||
assert f"Job {job.id} / execution {execution.get_id()}" in body
|
||||
assert f"/job/{job.id}/execution/{execution.get_id()}/logs" in body
|
||||
assert "Route: /job/" in body
|
||||
assert "waiting for more log lines" in body
|
||||
|
||||
asyncio.run(run())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue