package app import ( "context" "crypto/sha1" "encoding/json" "fmt" "time" "github.com/geo-platform/tenant-api/internal/shared/messaging/rabbitmq" "github.com/geo-platform/tenant-api/internal/shared/stream" "github.com/geo-platform/tenant-api/internal/tenant/repository" ) type DesktopTaskEvent struct { Type string `json:"type"` TaskID string `json:"task_id"` JobID string `json:"job_id"` WorkspaceID int64 `json:"workspace_id"` TargetAccountID string `json:"target_account_id"` TargetClientID string `json:"target_client_id"` Platform string `json:"platform"` Title *string `json:"title,omitempty"` BusinessDate *string `json:"business_date,omitempty"` SchedulerGroupKey *string `json:"scheduler_group_key,omitempty"` QuestionText *string `json:"question_text,omitempty"` Status string `json:"status"` Kind string `json:"kind"` Priority int `json:"priority,omitempty"` Lane string `json:"lane,omitempty"` InterruptGeneration int `json:"interrupt_generation,omitempty"` UpdatedAt time.Time `json:"updated_at"` } func publishDesktopTaskEvent(ctx context.Context, client *rabbitmq.Client, event DesktopTaskEvent) error { if client == nil { return nil } payload, err := json.Marshal(event) if err != nil { return err } return client.PublishDesktopTaskEvent(ctx, payload) } func DesktopDispatchEventFromTask(task *repository.DesktopTask, eventType string) stream.DesktopDispatchEvent { if task == nil { return stream.DesktopDispatchEvent{} } title, businessDate, schedulerGroupKey, questionText := deriveDesktopTaskEventMetadataFromPayload(task.Kind, task.Payload) return stream.DesktopDispatchEvent{ Type: eventType, TaskID: task.DesktopID.String(), JobID: task.JobID.String(), WorkspaceID: task.WorkspaceID, TargetAccountID: task.TargetAccountID.String(), TargetClientID: task.TargetClientID.String(), Platform: task.Platform, Title: title, BusinessDate: businessDate, SchedulerGroupKey: schedulerGroupKey, QuestionText: questionText, Status: task.Status, Kind: task.Kind, Priority: task.Priority, Lane: task.Lane, InterruptGeneration: task.InterruptGeneration, UpdatedAt: task.UpdatedAt, } } func deriveDesktopTaskEventMetadataFromPayload( kind string, payload []byte, ) (title *string, businessDate *string, schedulerGroupKey *string, questionText *string) { if len(payload) == 0 { return nil, nil, nil, nil } var envelope map[string]any if err := json.Unmarshal(payload, &envelope); err != nil { return nil, nil, nil, nil } title = firstDesktopTaskEventString(envelope, "title", "question_title", "questionTitle", ) businessDate = firstDesktopTaskEventString(envelope, "business_date", "businessDate", "metric_date", "date", ) questionText = firstDesktopTaskEventString(envelope, "question_text", "questionText", "query", "question", "prompt", "content", ) if explicit := firstDesktopTaskEventString(envelope, "scheduler_group_key", "schedulerGroupKey", ); explicit != nil { return title, businessDate, explicit, questionText } if questionHash := firstDesktopTaskEventString(envelope, "question_hash", "questionHash"); questionHash != nil { return title, businessDate, questionHash, questionText } if questionID := firstDesktopTaskEventString(envelope, "question_id", "questionId"); questionID != nil { value := fmt.Sprintf("qid:%s", *questionID) return title, businessDate, &value, questionText } if kind == "monitor" && questionText != nil { sum := sha1.Sum([]byte(*questionText)) value := fmt.Sprintf("qtxt:%x", sum) return title, businessDate, &value, questionText } return title, businessDate, nil, questionText } func firstDesktopTaskEventString(payload map[string]any, keys ...string) *string { for _, key := range keys { value, exists := payload[key] if !exists { continue } switch typed := value.(type) { case string: if typed != "" { return &typed } case float64: text := fmt.Sprintf("%.0f", typed) return &text case int64: text := fmt.Sprintf("%d", typed) return &text case int: text := fmt.Sprintf("%d", typed) return &text } } return nil }