fix monitor desktop task recovery
This commit is contained in:
@@ -2012,6 +2012,10 @@ func (s *DesktopTaskService) recoverClientTasks(
|
||||
if err != nil {
|
||||
return response.ErrInternal(50195, "desktop_task_recovery_payload_failed", "failed to encode monitor desktop task recovery payload")
|
||||
}
|
||||
monitorUnrecoverableErrorJSON, monitorUnrecoverableReason, _, err := desktopTaskRecoveryPayload(mode, "monitor_unrecoverable")
|
||||
if err != nil {
|
||||
return response.ErrInternal(50195, "desktop_task_recovery_payload_failed", "failed to encode monitor desktop task recovery payload")
|
||||
}
|
||||
|
||||
tx, err := s.pool.Begin(ctx)
|
||||
if err != nil {
|
||||
@@ -2069,7 +2073,9 @@ func (s *DesktopTaskService) recoverClientTasks(
|
||||
return failErr
|
||||
}
|
||||
if len(failedMonitorTaskIDs) == 0 {
|
||||
continue
|
||||
finalStatus = "aborted"
|
||||
monitorErrorForTask = monitorUnrecoverableErrorJSON
|
||||
monitorReasonForTask = monitorUnrecoverableReason
|
||||
}
|
||||
}
|
||||
} else if item.MonitorTaskID.Valid {
|
||||
@@ -2078,7 +2084,9 @@ func (s *DesktopTaskService) recoverClientTasks(
|
||||
return requeueErr
|
||||
}
|
||||
if len(requeuedMonitorTaskIDs) == 0 {
|
||||
continue
|
||||
finalStatus = "aborted"
|
||||
monitorErrorForTask = monitorUnrecoverableErrorJSON
|
||||
monitorReasonForTask = monitorUnrecoverableReason
|
||||
}
|
||||
}
|
||||
if _, execErr := tx.Exec(ctx, `
|
||||
@@ -2414,6 +2422,10 @@ func (s *DesktopTaskService) RecoverExpiredMonitorTasks(ctx context.Context, lim
|
||||
if err != nil {
|
||||
return result, response.ErrInternal(50195, "desktop_task_recovery_payload_failed", "failed to encode monitor desktop task recovery payload")
|
||||
}
|
||||
unrecoverableErrorJSON, unrecoverableReason, _, err := desktopTaskRecoveryPayload(desktopTaskRecoveryModeLeaseExpiry, "monitor_unrecoverable")
|
||||
if err != nil {
|
||||
return result, response.ErrInternal(50195, "desktop_task_recovery_payload_failed", "failed to encode monitor desktop task recovery payload")
|
||||
}
|
||||
|
||||
tx, err := s.pool.Begin(ctx)
|
||||
if err != nil {
|
||||
@@ -2464,39 +2476,70 @@ func (s *DesktopTaskService) RecoverExpiredMonitorTasks(ctx context.Context, lim
|
||||
requeuedMonitorTaskSet := int64Set(requeuedMonitorTaskIDs)
|
||||
recoverableDesktopIDs := make([]uuid.UUID, 0, len(recovered))
|
||||
recoverable := make([]recoveredDesktopTaskLease, 0, len(recovered))
|
||||
unrecoverableDesktopIDs := make([]uuid.UUID, 0, len(recovered))
|
||||
unrecoverable := make([]recoveredDesktopTaskLease, 0, len(recovered))
|
||||
for _, item := range recovered {
|
||||
if !item.MonitorTaskID.Valid {
|
||||
continue
|
||||
}
|
||||
if _, ok := requeuedMonitorTaskSet[item.MonitorTaskID.Int64]; !ok {
|
||||
item.Status = "aborted"
|
||||
item.ErrorJSON = unrecoverableErrorJSON
|
||||
unrecoverableDesktopIDs = append(unrecoverableDesktopIDs, item.TaskID)
|
||||
unrecoverable = append(unrecoverable, item)
|
||||
continue
|
||||
}
|
||||
recoverableDesktopIDs = append(recoverableDesktopIDs, item.TaskID)
|
||||
recoverable = append(recoverable, item)
|
||||
}
|
||||
if len(recoverableDesktopIDs) == 0 {
|
||||
if len(recoverableDesktopIDs) == 0 && len(unrecoverableDesktopIDs) == 0 {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
updateRows, err := tx.Query(ctx, requeueExpiredMonitorDesktopTasksSQL(), recoverableDesktopIDs, errorJSON, reason)
|
||||
if err != nil {
|
||||
s.logWarn("expired desktop monitor recovery update failed", err)
|
||||
return result, response.ErrInternal(50197, "desktop_task_recovery_query_failed", "failed to select recoverable desktop tasks")
|
||||
}
|
||||
defer updateRows.Close()
|
||||
|
||||
updatedDesktopIDs := make(map[uuid.UUID]struct{}, len(recoverableDesktopIDs))
|
||||
for updateRows.Next() {
|
||||
var desktopID uuid.UUID
|
||||
if scanErr := updateRows.Scan(&desktopID); scanErr != nil {
|
||||
s.logWarn("expired desktop monitor recovery update scan failed", scanErr)
|
||||
return result, response.ErrInternal(50198, "desktop_task_recovery_scan_failed", "failed to parse recovered desktop tasks")
|
||||
if len(recoverableDesktopIDs) > 0 {
|
||||
updateRows, err := tx.Query(ctx, requeueExpiredMonitorDesktopTasksSQL(), recoverableDesktopIDs, errorJSON, reason)
|
||||
if err != nil {
|
||||
s.logWarn("expired desktop monitor recovery update failed", err)
|
||||
return result, response.ErrInternal(50197, "desktop_task_recovery_query_failed", "failed to select recoverable desktop tasks")
|
||||
}
|
||||
defer updateRows.Close()
|
||||
|
||||
for updateRows.Next() {
|
||||
var desktopID uuid.UUID
|
||||
if scanErr := updateRows.Scan(&desktopID); scanErr != nil {
|
||||
s.logWarn("expired desktop monitor recovery update scan failed", scanErr)
|
||||
return result, response.ErrInternal(50198, "desktop_task_recovery_scan_failed", "failed to parse recovered desktop tasks")
|
||||
}
|
||||
updatedDesktopIDs[desktopID] = struct{}{}
|
||||
}
|
||||
if err := updateRows.Err(); err != nil {
|
||||
s.logWarn("expired desktop monitor recovery update rows failed", err)
|
||||
return result, response.ErrInternal(50198, "desktop_task_recovery_scan_failed", "failed to iterate recovered desktop tasks")
|
||||
}
|
||||
updatedDesktopIDs[desktopID] = struct{}{}
|
||||
}
|
||||
if err := updateRows.Err(); err != nil {
|
||||
s.logWarn("expired desktop monitor recovery update rows failed", err)
|
||||
return result, response.ErrInternal(50198, "desktop_task_recovery_scan_failed", "failed to iterate recovered desktop tasks")
|
||||
|
||||
abortedDesktopIDs := make(map[uuid.UUID]struct{}, len(unrecoverableDesktopIDs))
|
||||
if len(unrecoverableDesktopIDs) > 0 {
|
||||
abortRows, err := tx.Query(ctx, abortExpiredMonitorDesktopTasksSQL(), unrecoverableDesktopIDs, unrecoverableErrorJSON, unrecoverableReason)
|
||||
if err != nil {
|
||||
s.logWarn("expired desktop monitor unrecoverable update failed", err)
|
||||
return result, response.ErrInternal(50197, "desktop_task_recovery_query_failed", "failed to select recoverable desktop tasks")
|
||||
}
|
||||
defer abortRows.Close()
|
||||
|
||||
for abortRows.Next() {
|
||||
var desktopID uuid.UUID
|
||||
if scanErr := abortRows.Scan(&desktopID); scanErr != nil {
|
||||
s.logWarn("expired desktop monitor unrecoverable update scan failed", scanErr)
|
||||
return result, response.ErrInternal(50198, "desktop_task_recovery_scan_failed", "failed to parse recovered desktop tasks")
|
||||
}
|
||||
abortedDesktopIDs[desktopID] = struct{}{}
|
||||
}
|
||||
if err := abortRows.Err(); err != nil {
|
||||
s.logWarn("expired desktop monitor unrecoverable update rows failed", err)
|
||||
return result, response.ErrInternal(50198, "desktop_task_recovery_scan_failed", "failed to iterate recovered desktop tasks")
|
||||
}
|
||||
}
|
||||
|
||||
repo := repository.NewDesktopTaskRepository(tx)
|
||||
@@ -2523,12 +2566,36 @@ func (s *DesktopTaskService) RecoverExpiredMonitorTasks(ctx context.Context, lim
|
||||
s.logWarn("expired desktop monitor recovery attempt finish failed", finishErr, zap.String("task_id", item.TaskID.String()))
|
||||
}
|
||||
}
|
||||
for _, item := range unrecoverable {
|
||||
if _, ok := abortedDesktopIDs[item.TaskID]; !ok {
|
||||
continue
|
||||
}
|
||||
if !item.ActiveAttempt.Valid {
|
||||
continue
|
||||
}
|
||||
|
||||
attemptID, convErr := uuid.FromBytes(item.ActiveAttempt.Bytes[:])
|
||||
if convErr != nil {
|
||||
s.logWarn("expired desktop monitor unrecoverable attempt id decode failed", convErr, zap.String("task_id", item.TaskID.String()))
|
||||
continue
|
||||
}
|
||||
|
||||
if finishErr := repo.FinishAttempt(ctx, repository.FinishDesktopTaskAttemptParams{
|
||||
TaskID: item.TaskID,
|
||||
AttemptID: attemptID,
|
||||
FinalStatus: literalStringPtr("aborted"),
|
||||
Error: unrecoverableErrorJSON,
|
||||
}); finishErr != nil {
|
||||
s.logWarn("expired desktop monitor unrecoverable attempt finish failed", finishErr, zap.String("task_id", item.TaskID.String()))
|
||||
}
|
||||
}
|
||||
|
||||
if err := tx.Commit(ctx); err != nil {
|
||||
return result, response.ErrInternal(50199, "desktop_task_recovery_commit_failed", "failed to commit desktop task recovery")
|
||||
}
|
||||
|
||||
result.Requeued = len(updatedDesktopIDs)
|
||||
result.Failed = len(abortedDesktopIDs)
|
||||
|
||||
for _, item := range recoverable {
|
||||
if _, ok := updatedDesktopIDs[item.TaskID]; !ok {
|
||||
@@ -2541,10 +2608,22 @@ func (s *DesktopTaskService) RecoverExpiredMonitorTasks(ctx context.Context, lim
|
||||
}
|
||||
s.publishTaskEvent(ctx, task, "task_available")
|
||||
}
|
||||
for _, item := range unrecoverable {
|
||||
if _, ok := abortedDesktopIDs[item.TaskID]; !ok {
|
||||
continue
|
||||
}
|
||||
task, getErr := s.repo.GetByDesktopID(ctx, item.TaskID, item.WorkspaceID)
|
||||
if getErr != nil {
|
||||
s.logWarn("expired desktop monitor unrecoverable reload after commit failed", getErr, zap.String("task_id", item.TaskID.String()))
|
||||
continue
|
||||
}
|
||||
s.publishTaskEvent(ctx, task, "task_completed")
|
||||
}
|
||||
|
||||
if result.Requeued > 0 && s.logger != nil {
|
||||
if (result.Requeued > 0 || result.Failed > 0) && s.logger != nil {
|
||||
s.logger.Info("expired desktop monitor tasks recovered",
|
||||
zap.Int("requeued", result.Requeued),
|
||||
zap.Int("failed", result.Failed),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2594,6 +2673,25 @@ func requeueExpiredMonitorDesktopTasksSQL() string {
|
||||
`
|
||||
}
|
||||
|
||||
func abortExpiredMonitorDesktopTasksSQL() string {
|
||||
return `
|
||||
UPDATE desktop_tasks
|
||||
SET status = 'aborted',
|
||||
error = $2,
|
||||
result = NULL,
|
||||
active_attempt_id = NULL,
|
||||
lease_token_hash = NULL,
|
||||
lease_expires_at = NULL,
|
||||
interrupted_at = COALESCE(interrupted_at, NOW()),
|
||||
interrupt_reason = COALESCE(interrupt_reason, $3),
|
||||
updated_at = NOW()
|
||||
WHERE desktop_id = ANY($1::uuid[])
|
||||
AND kind = 'monitor'
|
||||
AND status = 'in_progress'
|
||||
RETURNING desktop_id
|
||||
`
|
||||
}
|
||||
|
||||
func (s *DesktopTaskService) requeueMonitorCollectTasksForDesktopRecovery(ctx context.Context, monitorTaskIDs []int64, errorJSON []byte) ([]int64, error) {
|
||||
if s == nil || s.monitoringPool == nil || len(monitorTaskIDs) == 0 {
|
||||
return nil, nil
|
||||
|
||||
Reference in New Issue
Block a user