feat(monitoring): dispatch monitoring tasks to desktop via AMQP outbox
Replace SSE /desktop/events with priority AMQP dispatch for monitoring
runs, and add phase1/phase2 infrastructure so desktop workers can lease,
resume, report, skip, and cancel monitoring tasks over the existing
dispatch WebSocket.
- Add monitoring collect outbox worker and phase2 desktop task fields
- Add /desktop/monitoring/tasks/{lease,resume,result,skip,cancel} routes
- Introduce execution-devtools and network-observer on desktop runtime
- Refactor runtime-controller, LoginView, and doubao adapter for the new flow
- Add channelName column to tracking views
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -22,7 +22,7 @@ SET status = 'aborted',
|
||||
WHERE desktop_id = $2
|
||||
AND target_client_id = $3
|
||||
AND status = 'queued'
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at, priority, lane, lane_weight, source, scheduler_group_key, monitor_task_id, supersedes_task_id, control_flags, interrupt_generation, started_at, interrupted_at, interrupt_reason, enqueued_at
|
||||
`
|
||||
|
||||
type CancelDesktopTaskByClientParams struct {
|
||||
@@ -55,6 +55,19 @@ func (q *Queries) CancelDesktopTaskByClient(ctx context.Context, arg CancelDeskt
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Priority,
|
||||
&i.Lane,
|
||||
&i.LaneWeight,
|
||||
&i.Source,
|
||||
&i.SchedulerGroupKey,
|
||||
&i.MonitorTaskID,
|
||||
&i.SupersedesTaskID,
|
||||
&i.ControlFlags,
|
||||
&i.InterruptGeneration,
|
||||
&i.StartedAt,
|
||||
&i.InterruptedAt,
|
||||
&i.InterruptReason,
|
||||
&i.EnqueuedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -70,7 +83,7 @@ SET status = 'aborted',
|
||||
WHERE desktop_id = $2
|
||||
AND lease_token_hash = $3
|
||||
AND status = 'in_progress'
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at, priority, lane, lane_weight, source, scheduler_group_key, monitor_task_id, supersedes_task_id, control_flags, interrupt_generation, started_at, interrupted_at, interrupt_reason, enqueued_at
|
||||
`
|
||||
|
||||
type CancelDesktopTaskByLeaseParams struct {
|
||||
@@ -103,6 +116,19 @@ func (q *Queries) CancelDesktopTaskByLease(ctx context.Context, arg CancelDeskto
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Priority,
|
||||
&i.Lane,
|
||||
&i.LaneWeight,
|
||||
&i.Source,
|
||||
&i.SchedulerGroupKey,
|
||||
&i.MonitorTaskID,
|
||||
&i.SupersedesTaskID,
|
||||
&i.ControlFlags,
|
||||
&i.InterruptGeneration,
|
||||
&i.StartedAt,
|
||||
&i.InterruptedAt,
|
||||
&i.InterruptReason,
|
||||
&i.EnqueuedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -119,7 +145,7 @@ SET status = $1,
|
||||
WHERE desktop_id = $4
|
||||
AND lease_token_hash = $5
|
||||
AND status = 'in_progress'
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at, priority, lane, lane_weight, source, scheduler_group_key, monitor_task_id, supersedes_task_id, control_flags, interrupt_generation, started_at, interrupted_at, interrupt_reason, enqueued_at
|
||||
`
|
||||
|
||||
type CompleteDesktopTaskParams struct {
|
||||
@@ -160,6 +186,19 @@ func (q *Queries) CompleteDesktopTask(ctx context.Context, arg CompleteDesktopTa
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Priority,
|
||||
&i.Lane,
|
||||
&i.LaneWeight,
|
||||
&i.Source,
|
||||
&i.SchedulerGroupKey,
|
||||
&i.MonitorTaskID,
|
||||
&i.SupersedesTaskID,
|
||||
&i.ControlFlags,
|
||||
&i.InterruptGeneration,
|
||||
&i.StartedAt,
|
||||
&i.InterruptedAt,
|
||||
&i.InterruptReason,
|
||||
&i.EnqueuedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -249,7 +288,7 @@ VALUES (
|
||||
$10,
|
||||
$11
|
||||
)
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at, priority, lane, lane_weight, source, scheduler_group_key, monitor_task_id, supersedes_task_id, control_flags, interrupt_generation, started_at, interrupted_at, interrupt_reason, enqueued_at
|
||||
`
|
||||
|
||||
type CreateDesktopTaskParams struct {
|
||||
@@ -302,6 +341,19 @@ func (q *Queries) CreateDesktopTask(ctx context.Context, arg CreateDesktopTaskPa
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Priority,
|
||||
&i.Lane,
|
||||
&i.LaneWeight,
|
||||
&i.Source,
|
||||
&i.SchedulerGroupKey,
|
||||
&i.MonitorTaskID,
|
||||
&i.SupersedesTaskID,
|
||||
&i.ControlFlags,
|
||||
&i.InterruptGeneration,
|
||||
&i.StartedAt,
|
||||
&i.InterruptedAt,
|
||||
&i.InterruptReason,
|
||||
&i.EnqueuedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -359,7 +411,7 @@ SET lease_expires_at = now() + interval '10 minutes',
|
||||
WHERE desktop_id = $1
|
||||
AND lease_token_hash = $2
|
||||
AND status = 'in_progress'
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at, priority, lane, lane_weight, source, scheduler_group_key, monitor_task_id, supersedes_task_id, control_flags, interrupt_generation, started_at, interrupted_at, interrupt_reason, enqueued_at
|
||||
`
|
||||
|
||||
type ExtendDesktopTaskLeaseParams struct {
|
||||
@@ -391,6 +443,19 @@ func (q *Queries) ExtendDesktopTaskLease(ctx context.Context, arg ExtendDesktopT
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Priority,
|
||||
&i.Lane,
|
||||
&i.LaneWeight,
|
||||
&i.Source,
|
||||
&i.SchedulerGroupKey,
|
||||
&i.MonitorTaskID,
|
||||
&i.SupersedesTaskID,
|
||||
&i.ControlFlags,
|
||||
&i.InterruptGeneration,
|
||||
&i.StartedAt,
|
||||
&i.InterruptedAt,
|
||||
&i.InterruptReason,
|
||||
&i.EnqueuedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -422,7 +487,7 @@ func (q *Queries) FinishDesktopTaskAttempt(ctx context.Context, arg FinishDeskto
|
||||
}
|
||||
|
||||
const getDesktopTaskByDesktopID = `-- name: GetDesktopTaskByDesktopID :one
|
||||
SELECT id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at
|
||||
SELECT id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at, priority, lane, lane_weight, source, scheduler_group_key, monitor_task_id, supersedes_task_id, control_flags, interrupt_generation, started_at, interrupted_at, interrupt_reason, enqueued_at
|
||||
FROM desktop_tasks
|
||||
WHERE desktop_id = $1
|
||||
AND workspace_id = $2
|
||||
@@ -458,6 +523,19 @@ func (q *Queries) GetDesktopTaskByDesktopID(ctx context.Context, arg GetDesktopT
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Priority,
|
||||
&i.Lane,
|
||||
&i.LaneWeight,
|
||||
&i.Source,
|
||||
&i.SchedulerGroupKey,
|
||||
&i.MonitorTaskID,
|
||||
&i.SupersedesTaskID,
|
||||
&i.ControlFlags,
|
||||
&i.InterruptGeneration,
|
||||
&i.StartedAt,
|
||||
&i.InterruptedAt,
|
||||
&i.InterruptReason,
|
||||
&i.EnqueuedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -472,7 +550,11 @@ WITH candidate AS (
|
||||
$4::text IS NULL
|
||||
OR dt.kind = $4::text
|
||||
)
|
||||
ORDER BY dt.created_at ASC, dt.desktop_id ASC
|
||||
ORDER BY dt.lane_weight DESC,
|
||||
dt.priority DESC,
|
||||
COALESCE(dt.enqueued_at, dt.created_at) ASC,
|
||||
dt.created_at ASC,
|
||||
dt.desktop_id ASC
|
||||
LIMIT 1
|
||||
FOR UPDATE SKIP LOCKED
|
||||
)
|
||||
@@ -485,7 +567,7 @@ SET active_attempt_id = $1,
|
||||
updated_at = now()
|
||||
FROM candidate
|
||||
WHERE t.desktop_id = candidate.desktop_id
|
||||
RETURNING t.id, t.desktop_id, t.job_id, t.tenant_id, t.workspace_id, t.target_account_id, t.target_client_id, t.platform_id, t.kind, t.payload, t.status, t.dedup_key, t.active_attempt_id, t.lease_token_hash, t.lease_expires_at, t.attempts, t.result, t.error, t.created_at, t.updated_at
|
||||
RETURNING t.id, t.desktop_id, t.job_id, t.tenant_id, t.workspace_id, t.target_account_id, t.target_client_id, t.platform_id, t.kind, t.payload, t.status, t.dedup_key, t.active_attempt_id, t.lease_token_hash, t.lease_expires_at, t.attempts, t.result, t.error, t.created_at, t.updated_at, t.priority, t.lane, t.lane_weight, t.source, t.scheduler_group_key, t.monitor_task_id, t.supersedes_task_id, t.control_flags, t.interrupt_generation, t.started_at, t.interrupted_at, t.interrupt_reason, t.enqueued_at
|
||||
`
|
||||
|
||||
type LeaseNextQueuedDesktopTaskParams struct {
|
||||
@@ -524,6 +606,19 @@ func (q *Queries) LeaseNextQueuedDesktopTask(ctx context.Context, arg LeaseNextQ
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Priority,
|
||||
&i.Lane,
|
||||
&i.LaneWeight,
|
||||
&i.Source,
|
||||
&i.SchedulerGroupKey,
|
||||
&i.MonitorTaskID,
|
||||
&i.SupersedesTaskID,
|
||||
&i.ControlFlags,
|
||||
&i.InterruptGeneration,
|
||||
&i.StartedAt,
|
||||
&i.InterruptedAt,
|
||||
&i.InterruptReason,
|
||||
&i.EnqueuedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -539,7 +634,7 @@ SET active_attempt_id = $1,
|
||||
WHERE desktop_id = $3
|
||||
AND target_client_id = $4
|
||||
AND status = 'queued'
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at, priority, lane, lane_weight, source, scheduler_group_key, monitor_task_id, supersedes_task_id, control_flags, interrupt_generation, started_at, interrupted_at, interrupt_reason, enqueued_at
|
||||
`
|
||||
|
||||
type LeaseQueuedDesktopTaskByDesktopIDParams struct {
|
||||
@@ -578,6 +673,19 @@ func (q *Queries) LeaseQueuedDesktopTaskByDesktopID(ctx context.Context, arg Lea
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Priority,
|
||||
&i.Lane,
|
||||
&i.LaneWeight,
|
||||
&i.Source,
|
||||
&i.SchedulerGroupKey,
|
||||
&i.MonitorTaskID,
|
||||
&i.SupersedesTaskID,
|
||||
&i.ControlFlags,
|
||||
&i.InterruptGeneration,
|
||||
&i.StartedAt,
|
||||
&i.InterruptedAt,
|
||||
&i.InterruptReason,
|
||||
&i.EnqueuedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -628,7 +736,7 @@ SET status = CASE
|
||||
WHERE desktop_id = $4
|
||||
AND workspace_id = $5
|
||||
AND status = 'unknown'
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at, priority, lane, lane_weight, source, scheduler_group_key, monitor_task_id, supersedes_task_id, control_flags, interrupt_generation, started_at, interrupted_at, interrupt_reason, enqueued_at
|
||||
`
|
||||
|
||||
type ReconcileDesktopTaskParams struct {
|
||||
@@ -669,6 +777,19 @@ func (q *Queries) ReconcileDesktopTask(ctx context.Context, arg ReconcileDesktop
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Priority,
|
||||
&i.Lane,
|
||||
&i.LaneWeight,
|
||||
&i.Source,
|
||||
&i.SchedulerGroupKey,
|
||||
&i.MonitorTaskID,
|
||||
&i.SupersedesTaskID,
|
||||
&i.ControlFlags,
|
||||
&i.InterruptGeneration,
|
||||
&i.StartedAt,
|
||||
&i.InterruptedAt,
|
||||
&i.InterruptReason,
|
||||
&i.EnqueuedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -684,7 +805,7 @@ SET status = 'aborted',
|
||||
WHERE desktop_id = $2
|
||||
AND workspace_id = $3
|
||||
AND status = 'queued'
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, result, error, created_at, updated_at, priority, lane, lane_weight, source, scheduler_group_key, monitor_task_id, supersedes_task_id, control_flags, interrupt_generation, started_at, interrupted_at, interrupt_reason, enqueued_at
|
||||
`
|
||||
|
||||
type TenantCancelDesktopTaskParams struct {
|
||||
@@ -717,6 +838,19 @@ func (q *Queries) TenantCancelDesktopTask(ctx context.Context, arg TenantCancelD
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Priority,
|
||||
&i.Lane,
|
||||
&i.LaneWeight,
|
||||
&i.Source,
|
||||
&i.SchedulerGroupKey,
|
||||
&i.MonitorTaskID,
|
||||
&i.SupersedesTaskID,
|
||||
&i.ControlFlags,
|
||||
&i.InterruptGeneration,
|
||||
&i.StartedAt,
|
||||
&i.InterruptedAt,
|
||||
&i.InterruptReason,
|
||||
&i.EnqueuedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
@@ -8,6 +8,19 @@ import (
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type AiPlatform struct {
|
||||
ID int64 `json:"id"`
|
||||
AiPlatformID string `json:"ai_platform_id"`
|
||||
Name string `json:"name"`
|
||||
ShortName string `json:"short_name"`
|
||||
AccentColor string `json:"accent_color"`
|
||||
LoginUrl pgtype.Text `json:"login_url"`
|
||||
Status string `json:"status"`
|
||||
SortOrder int32 `json:"sort_order"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
type Article struct {
|
||||
ID int64 `json:"id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
@@ -150,26 +163,39 @@ type DesktopPublishJob struct {
|
||||
}
|
||||
|
||||
type DesktopTask struct {
|
||||
ID int64 `json:"id"`
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
JobID pgtype.UUID `json:"job_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
TargetAccountID pgtype.UUID `json:"target_account_id"`
|
||||
TargetClientID pgtype.UUID `json:"target_client_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
Kind string `json:"kind"`
|
||||
Payload []byte `json:"payload"`
|
||||
Status string `json:"status"`
|
||||
DedupKey pgtype.Text `json:"dedup_key"`
|
||||
ActiveAttemptID pgtype.UUID `json:"active_attempt_id"`
|
||||
LeaseTokenHash []byte `json:"lease_token_hash"`
|
||||
LeaseExpiresAt pgtype.Timestamptz `json:"lease_expires_at"`
|
||||
Attempts int32 `json:"attempts"`
|
||||
Result []byte `json:"result"`
|
||||
Error []byte `json:"error"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
ID int64 `json:"id"`
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
JobID pgtype.UUID `json:"job_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
TargetAccountID pgtype.UUID `json:"target_account_id"`
|
||||
TargetClientID pgtype.UUID `json:"target_client_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
Kind string `json:"kind"`
|
||||
Payload []byte `json:"payload"`
|
||||
Status string `json:"status"`
|
||||
DedupKey pgtype.Text `json:"dedup_key"`
|
||||
ActiveAttemptID pgtype.UUID `json:"active_attempt_id"`
|
||||
LeaseTokenHash []byte `json:"lease_token_hash"`
|
||||
LeaseExpiresAt pgtype.Timestamptz `json:"lease_expires_at"`
|
||||
Attempts int32 `json:"attempts"`
|
||||
Result []byte `json:"result"`
|
||||
Error []byte `json:"error"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
Priority int32 `json:"priority"`
|
||||
Lane string `json:"lane"`
|
||||
LaneWeight int32 `json:"lane_weight"`
|
||||
Source string `json:"source"`
|
||||
SchedulerGroupKey pgtype.Text `json:"scheduler_group_key"`
|
||||
MonitorTaskID pgtype.Int8 `json:"monitor_task_id"`
|
||||
SupersedesTaskID pgtype.UUID `json:"supersedes_task_id"`
|
||||
ControlFlags []byte `json:"control_flags"`
|
||||
InterruptGeneration int32 `json:"interrupt_generation"`
|
||||
StartedAt pgtype.Timestamptz `json:"started_at"`
|
||||
InterruptedAt pgtype.Timestamptz `json:"interrupted_at"`
|
||||
InterruptReason pgtype.Text `json:"interrupt_reason"`
|
||||
EnqueuedAt pgtype.Timestamptz `json:"enqueued_at"`
|
||||
}
|
||||
|
||||
type DesktopTaskAttempt struct {
|
||||
|
||||
Reference in New Issue
Block a user