001project_wildgrowth/ios/WildGrowth/WildGrowth/TaskStatusPoller.swift

144 lines
4.6 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Foundation
import SwiftUI
// MARK: -
//
@MainActor
class TaskStatusPoller: ObservableObject {
// MARK: - Published Properties
@Published var status: TaskStatus = .pending
@Published var progress: Int = 0
@Published var currentStep: String?
@Published var errorMessage: String?
@Published var courseId: String?
@Published var taskCreatedAt: String? // ISO 8601
// MARK: - Private Properties
private let taskId: String
private var timer: Timer?
private let pollInterval: TimeInterval = 2.0 // 2
private let maxPollTime: TimeInterval = 900.0 // 15
private var startTime: Date?
private var isPolling: Bool = false
// MARK: - Callbacks
var onStatusChanged: ((TaskStatus) -> Void)?
var onCompleted: ((String) -> Void)? // courseId
var onFailed: ((String) -> Void)? // errorMessage
var onTimeout: (() -> Void)?
// MARK: - Initialization
init(taskId: String) {
self.taskId = taskId
}
// MARK: - Public Methods
///
func start() {
guard !isPolling else {
print("⚠️ [TaskStatusPoller] 已经在轮询中,跳过")
return
}
print("🔵 [TaskStatusPoller] 开始轮询: taskId=\(taskId)")
isPolling = true
startTime = Date()
// 线
Task { @MainActor in
print("🔵 [TaskStatusPoller] 立即执行第一次轮询")
await poll()
}
//
timer = Timer.scheduledTimer(withTimeInterval: pollInterval, repeats: true) { [weak self] _ in
Task { @MainActor [weak self] in
await self?.poll()
}
}
print("✅ [TaskStatusPoller] 轮询器已启动,定时器已设置")
}
///
func stop() {
isPolling = false
timer?.invalidate()
timer = nil
}
// MARK: - Private Methods
private func poll() async {
guard isPolling else {
print("⚠️ [TaskStatusPoller] 轮询已停止,跳过")
return
}
print("🔵 [TaskStatusPoller] 开始轮询: taskId=\(taskId)")
//
if let startTime = startTime,
Date().timeIntervalSince(startTime) > maxPollTime {
print("⏰ [TaskStatusPoller] 轮询超时")
stop()
onTimeout?()
return
}
do {
print("🔵 [TaskStatusPoller] 调用 getTaskStatus API...")
let statusData = try await AICourseService.shared.getTaskStatus(taskId: taskId)
print("✅ [TaskStatusPoller] 获取状态成功: status=\(statusData.status), progress=\(statusData.progress)")
//
let newStatus = TaskStatus(rawValue: statusData.status) ?? .pending
if newStatus != status {
print("🔄 [TaskStatusPoller] 状态变化: \(status) -> \(newStatus)")
status = newStatus
onStatusChanged?(newStatus)
}
progress = statusData.progress
currentStep = statusData.currentStep
errorMessage = statusData.errorMessage
courseId = statusData.courseId
taskCreatedAt = statusData.createdAt //
//
if newStatus.isCompleted {
print("✅ [TaskStatusPoller] 任务完成")
stop()
// courseId 使
onCompleted?(statusData.courseId)
} else if newStatus.isFailed {
print("❌ [TaskStatusPoller] 任务失败")
stop()
onFailed?(statusData.errorMessage ?? "生成失败")
}
} catch {
//
print("❌ [TaskStatusPoller] 轮询失败: \(error.localizedDescription)")
print("❌ [TaskStatusPoller] 错误类型: \(type(of: error))")
}
}
deinit {
// timer MainActor self Swift 6
let t = timer
timer = nil
isPolling = false
Task { @MainActor in
t?.invalidate()
}
}
}