# Copyright (c) 2023-present Plane Software, Inc. and contributors # SPDX-License-Identifier: AGPL-3.0-only # See the LICENSE file for details. import json import logging from uuid import uuid4 from django.core.serializers.json import DjangoJSONEncoder from django.db import transaction from django.utils import timezone from plane.settings.redis import redis_instance logger = logging.getLogger(__name__) ISSUE_EVENT_CHANNEL_PREFIX = "plane:issue-events:project" def issue_event_channel(project_id): return f"{ISSUE_EVENT_CHANNEL_PREFIX}:{project_id}" def publish_issue_event_on_commit(event_type, issue, actor_id=None, changed_fields=None): payload = { "event_id": str(uuid4()), "type": event_type, "workspace_id": str(issue.workspace_id), "workspace_slug": issue.workspace.slug if getattr(issue, "workspace", None) else None, "project_id": str(issue.project_id), "issue_id": str(issue.id), "sequence_id": issue.sequence_id, "updated_at": issue.updated_at or timezone.now(), "actor_id": str(actor_id) if actor_id else None, "changed_fields": sorted(set(changed_fields or [])), } def _publish(): try: redis_instance().publish( issue_event_channel(issue.project_id), json.dumps(payload, cls=DjangoJSONEncoder), ) except Exception: logger.exception("Failed to publish issue realtime event") transaction.on_commit(_publish)