Add IDM assignment lifecycle worker contract

This commit is contained in:
2026-07-31 18:07:36 +02:00
parent 5ee85d07d6
commit 50a8d459e7
3 changed files with 184 additions and 0 deletions
+53
View File
@@ -19,6 +19,10 @@ from govoplan_core.core.events import (
PlatformEventOutbox,
publish_platform_event,
)
from govoplan_core.core.idm import (
CAPABILITY_IDM_ASSIGNMENT_LIFECYCLE,
IdmAssignmentLifecycle,
)
from govoplan_core.core.module_management import load_startup_enabled_modules, startup_candidate_module_ids
from govoplan_core.core.mail import CAPABILITY_MAIL_DELIVERY_OUTBOX, MailDeliveryOutboxProvider
from govoplan_core.core.modules import ModuleContext
@@ -62,6 +66,7 @@ celery.conf.update(
"govoplan.postbox.dispatch_routes": {"queue": "postbox"},
"govoplan.events.dispatch_outbox": {"queue": "events"},
"govoplan.events.purge_outbox": {"queue": "events"},
"govoplan.idm.expire_assignments": {"queue": "idm"},
},
worker_prefetch_multiplier=1,
task_acks_late=True,
@@ -117,6 +122,11 @@ celery.conf.update(
"schedule": 24 * 60 * 60.0,
"args": (500,),
},
"idm-assignment-expiry-every-minute": {
"task": "govoplan.idm.expire_assignments",
"schedule": 60.0,
"args": (None, 100),
},
},
)
@@ -238,6 +248,20 @@ def _platform_event_outbox(
return capability
def _idm_assignment_lifecycle(
registry: PlatformRegistry | None = None,
) -> IdmAssignmentLifecycle | None:
registry = registry or _platform_registry()
if not registry.has_capability(CAPABILITY_IDM_ASSIGNMENT_LIFECYCLE):
return None
capability = registry.require_capability(
CAPABILITY_IDM_ASSIGNMENT_LIFECYCLE
)
if not isinstance(capability, IdmAssignmentLifecycle):
raise RuntimeError("IDM assignment lifecycle capability is invalid")
return capability
@celery.task(name="govoplan.campaigns.send_email", bind=True, max_retries=0)
def send_email(self, job_id: str):
"""Send one explicitly queued campaign job.
@@ -485,6 +509,35 @@ def dispatch_postbox_routes(
return result
@celery.task(
name="govoplan.idm.expire_assignments",
bind=True,
max_retries=0,
)
def expire_idm_assignments(
self,
tenant_id: str | None = None,
limit: int = 100,
):
"""Emit idempotent lifecycle events for elapsed IDM assignments."""
from govoplan_core.db.session import get_database
with get_database().SessionLocal() as session:
provider = _idm_assignment_lifecycle()
if provider is None:
return {"selected": 0, "expired": 0, "assignment_ids": []}
result = dict(
provider.process_expired(
session,
tenant_id=tenant_id,
limit=limit,
)
)
session.commit()
return result
@celery.task(
name="govoplan.events.dispatch_outbox",
bind=True,