Initial commit from monorepo
This commit is contained in:
168
teams_app/temporal_client.py
Normal file
168
teams_app/temporal_client.py
Normal file
@@ -0,0 +1,168 @@
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
import uuid
|
||||
from dataclasses import asdict
|
||||
from typing import Tuple
|
||||
|
||||
from temporalio.client import Client
|
||||
|
||||
from .models import Team
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Default Temporal connection settings; override via env.
|
||||
TEMPORAL_ADDRESS = os.getenv("TEMPORAL_ADDRESS", "temporal:7233")
|
||||
TEMPORAL_NAMESPACE = os.getenv("TEMPORAL_NAMESPACE", "default")
|
||||
TEMPORAL_TASK_QUEUE = os.getenv("TEMPORAL_TASK_QUEUE", "platform-worker")
|
||||
|
||||
|
||||
async def _start_team_created_async(team: Team) -> Tuple[str, str]:
|
||||
"""
|
||||
Start the team_created workflow in Temporal and return (workflow_id, run_id).
|
||||
"""
|
||||
client = await Client.connect(TEMPORAL_ADDRESS, namespace=TEMPORAL_NAMESPACE)
|
||||
|
||||
# We re-use team.uuid as workflow_id to keep idempotency.
|
||||
handle = await client.start_workflow(
|
||||
"team_created_workflow", # workflow name registered in worker
|
||||
{
|
||||
"team_id": team.uuid,
|
||||
"team_name": team.name,
|
||||
"owner_id": getattr(getattr(team.owner, "profile", None), "logto_id", "") or getattr(team.owner, "username", ""),
|
||||
"logto_org_id": team.logto_org_id or "",
|
||||
},
|
||||
id=team.uuid,
|
||||
task_queue=TEMPORAL_TASK_QUEUE,
|
||||
)
|
||||
return handle.id, handle.run_id
|
||||
|
||||
|
||||
def start_team_created(team: Team) -> Tuple[str, str]:
|
||||
"""
|
||||
Sync wrapper for Django mutation handlers.
|
||||
"""
|
||||
try:
|
||||
return asyncio.run(_start_team_created_async(team))
|
||||
except Exception:
|
||||
logger.exception("Failed to start Temporal workflow for team %s", team.uuid)
|
||||
raise
|
||||
|
||||
|
||||
async def _start_address_workflow_async(
|
||||
team_uuid: str,
|
||||
name: str,
|
||||
address: str,
|
||||
latitude: float | None = None,
|
||||
longitude: float | None = None,
|
||||
country_code: str | None = None,
|
||||
is_default: bool = False,
|
||||
) -> Tuple[str, str]:
|
||||
"""
|
||||
Start the create_address workflow in Temporal.
|
||||
Returns (workflow_id, run_id).
|
||||
"""
|
||||
client = await Client.connect(TEMPORAL_ADDRESS, namespace=TEMPORAL_NAMESPACE)
|
||||
|
||||
workflow_id = f"address-{uuid.uuid4()}"
|
||||
|
||||
handle = await client.start_workflow(
|
||||
"create_address",
|
||||
{
|
||||
"workflow_id": workflow_id,
|
||||
"team_uuid": team_uuid,
|
||||
"name": name,
|
||||
"address": address,
|
||||
"latitude": latitude,
|
||||
"longitude": longitude,
|
||||
"country_code": country_code,
|
||||
"is_default": is_default,
|
||||
},
|
||||
id=workflow_id,
|
||||
task_queue=TEMPORAL_TASK_QUEUE,
|
||||
)
|
||||
|
||||
logger.info("Started address workflow %s for team %s", workflow_id, team_uuid)
|
||||
return handle.id, handle.result_run_id
|
||||
|
||||
|
||||
def start_address_workflow(
|
||||
team_uuid: str,
|
||||
name: str,
|
||||
address: str,
|
||||
latitude: float | None = None,
|
||||
longitude: float | None = None,
|
||||
country_code: str | None = None,
|
||||
is_default: bool = False,
|
||||
) -> Tuple[str, str]:
|
||||
"""
|
||||
Sync wrapper for starting address workflow.
|
||||
"""
|
||||
try:
|
||||
return asyncio.run(_start_address_workflow_async(
|
||||
team_uuid=team_uuid,
|
||||
name=name,
|
||||
address=address,
|
||||
latitude=latitude,
|
||||
longitude=longitude,
|
||||
country_code=country_code,
|
||||
is_default=is_default,
|
||||
))
|
||||
except Exception:
|
||||
logger.exception("Failed to start address workflow for team %s", team_uuid)
|
||||
raise
|
||||
|
||||
|
||||
async def _start_invite_workflow_async(
|
||||
team_uuid: str,
|
||||
email: str,
|
||||
role: str,
|
||||
invited_by: str,
|
||||
expires_at: str,
|
||||
) -> Tuple[str, str]:
|
||||
"""
|
||||
Start the invite_user workflow in Temporal.
|
||||
Returns (workflow_id, run_id).
|
||||
"""
|
||||
client = await Client.connect(TEMPORAL_ADDRESS, namespace=TEMPORAL_NAMESPACE)
|
||||
|
||||
workflow_id = f"invite-{uuid.uuid4()}"
|
||||
|
||||
handle = await client.start_workflow(
|
||||
"invite_user",
|
||||
{
|
||||
"team_uuid": team_uuid,
|
||||
"email": email,
|
||||
"role": role,
|
||||
"invited_by": invited_by,
|
||||
"expires_at": expires_at,
|
||||
},
|
||||
id=workflow_id,
|
||||
task_queue=TEMPORAL_TASK_QUEUE,
|
||||
)
|
||||
|
||||
logger.info("Started invite workflow %s for %s", workflow_id, email)
|
||||
return handle.id, handle.result_run_id
|
||||
|
||||
|
||||
def start_invite_workflow(
|
||||
team_uuid: str,
|
||||
email: str,
|
||||
role: str,
|
||||
invited_by: str,
|
||||
expires_at: str,
|
||||
) -> Tuple[str, str]:
|
||||
"""
|
||||
Sync wrapper for starting invite workflow.
|
||||
"""
|
||||
try:
|
||||
return asyncio.run(_start_invite_workflow_async(
|
||||
team_uuid=team_uuid,
|
||||
email=email,
|
||||
role=role,
|
||||
invited_by=invited_by,
|
||||
expires_at=expires_at,
|
||||
))
|
||||
except Exception:
|
||||
logger.exception("Failed to start invite workflow for %s", email)
|
||||
raise
|
||||
Reference in New Issue
Block a user