Harden public demo for 0.3.16
release / verify-publish (push) Failing after 6s
deploy / deploy (push) Canceled after 0s

This commit is contained in:
Jens
2026-08-12 11:42:00 +02:00
parent 2419e6bf01
commit a6c8a79e31
17 changed files with 228 additions and 24 deletions
+3 -2
View File
@@ -8,7 +8,7 @@ from django.urls import reverse
from apps.notifications.models import DigestOutbox, ReminderOutbox
from apps.profiles.models import ProfileRevision
from apps.sources.models import SourceRun
from apps.sources.models import Source, SourceRun
from ..models import ApplicationTimelineEvent, Feedback, JobVersion
@@ -37,7 +37,8 @@ ACTIVITY_FILTERS = (
def _source_events() -> list[ActivityEvent]:
events = []
for run in SourceRun.objects.select_related("source").order_by("-started_at")[:100]:
runs = SourceRun.objects.exclude(source__source_type=Source.Type.EMAIL)
for run in runs.select_related("source").order_by("-started_at")[:100]:
detail = (
f"{run.extracted_count} geëxtraheerd · {run.created_count} nieuw · "
f"{run.duplicate_count} duplicaat"
+5 -2
View File
@@ -57,7 +57,8 @@ def annotate_latest_profile_score(
def _recent_dashboard_activity(user: User) -> list[dict[str, Any]]:
activity: list[dict[str, Any]] = []
for run in SourceRun.objects.select_related("source").order_by("-started_at")[:4]:
source_runs = SourceRun.objects.exclude(source__source_type=Source.Type.EMAIL)
for run in source_runs.select_related("source").order_by("-started_at")[:4]:
activity.append(
{
"occurred_at": run.started_at,
@@ -154,7 +155,9 @@ def build_dashboard_cockpit(user: User, profile: SearchProfile | None) -> dict[s
"source_counts": source_counts,
"recent_activity": _recent_dashboard_activity(user),
"day_conclusion": day_conclusion,
"latest_scan": SourceRun.objects.order_by("-started_at").first(),
"latest_scan": SourceRun.objects.exclude(source__source_type=Source.Type.EMAIL)
.order_by("-started_at")
.first(),
}
+50 -7
View File
@@ -122,11 +122,10 @@ def demo_environment_seeded(user) -> bool:
def seed_demo_environment(user) -> None:
"""Maak (idempotent) een fictieve demo-omgeving voor ``user``."""
if demo_environment_seeded(user):
return
"""Maak of herstel een fictieve, tijdsbestendige demo-omgeving voor ``user``."""
from apps.jobs.models import Application, Employer, JobPosting, ScoreRun
from apps.sources.models import MailboxConnection, Source, SourceRun
from apps.sources.platforms import PLATFORM_ALERTS
profile, _ = SearchProfile.objects.get_or_create(
user=user,
@@ -185,7 +184,7 @@ def seed_demo_environment(user) -> None:
},
)
slug = _digest("demo-job", str(index), title, employer_name)
job, job_created = JobPosting.objects.get_or_create(
job, _ = JobPosting.objects.update_or_create(
canonical_key=slug,
defaults={
"employer": employer,
@@ -221,6 +220,11 @@ def seed_demo_environment(user) -> None:
)
created_jobs.append(job)
ScoreRun.objects.filter(
job=job,
profile=profile,
model_version="demo-seed",
).delete()
ScoreRun.objects.create(
job=job,
profile=profile,
@@ -244,7 +248,7 @@ def seed_demo_environment(user) -> None:
# Een kleine sollicitatiepijplijn voor de demo.
if created_jobs:
Application.objects.get_or_create(
Application.objects.update_or_create(
user=user,
job=created_jobs[0],
defaults={
@@ -257,7 +261,7 @@ def seed_demo_environment(user) -> None:
},
)
if len(created_jobs) > 3:
Application.objects.get_or_create(
Application.objects.update_or_create(
user=user,
job=created_jobs[3],
defaults={
@@ -267,3 +271,42 @@ def seed_demo_environment(user) -> None:
"notes": "Sollicitatie verstuurd. Demo-data.",
},
)
# Platformmailboxen zijn zichtbare ingressconfiguratie, geen crawlbare URL-bronnen.
# De demo gebruikt uitsluitend fictieve adressen en wordt door de scheduler overgeslagen.
for platform in PLATFORM_ALERTS:
MailboxConnection.objects.update_or_create(
user=user,
platform=platform,
defaults={
"provider": MailboxConnection.Provider.OUTLOOK,
"username": "alerts@example.test",
"mailbox": f"VacatureRadar/{platform}",
"enabled": True,
"poll_interval_minutes": MailboxConnection.PollInterval.THIRTY_MINUTES,
"next_poll_at": now + timedelta(minutes=30),
"last_polled_at": now - timedelta(minutes=5),
"last_success_at": now - timedelta(minutes=5),
"last_error_category": "",
"last_error_message": "",
"lease_token": "",
"lease_expires_at": None,
},
)
source, _ = Source.objects.update_or_create(
source_type=Source.Type.EMAIL,
domain=f"{platform}.mailbox.local",
defaults={
"name": f"{PLATFORM_ALERTS[platform].label} vacaturemailbox",
"base_url": "",
"status": Source.Status.ACTIVE,
"policy": Source.Policy.ALLOW,
"policy_reason": "Mailboxingress; niet via URL-fetch gepland.",
"parser_key": "email-alert",
"failure_count": 0,
"last_failure_at": None,
"next_run_at": None,
"metadata": {"demo": True, "mailbox_ingress": True},
},
)
SourceRun.objects.filter(source=source).delete()
+3 -1
View File
@@ -188,7 +188,8 @@ def schedule_due_sources() -> dict[str, int]:
now = timezone.now()
due = Source.objects.filter(
status__in=[Source.Status.ACTIVE, Source.Status.TRIAL],
).filter(Q(next_run_at__isnull=True) | Q(next_run_at__lte=now))
).exclude(source_type=Source.Type.EMAIL)
due = due.filter(Q(next_run_at__isnull=True) | Q(next_run_at__lte=now))
ids = list(due.values_list("id", flat=True).distinct()[:200])
for source_id in ids:
fetch_source.delay(source_id)
@@ -200,6 +201,7 @@ def schedule_mailbox_polls() -> dict[str, int]:
now = timezone.now()
due_ids = list(
MailboxConnection.objects.filter(enabled=True, next_poll_at__lte=now)
.exclude(user__username=settings.DEMO_USERNAME)
.filter(Q(lease_expires_at__isnull=True) | Q(lease_expires_at__lte=now))
.values_list("id", flat=True)[:100]
)