import * as BackgroundTask from 'expo-background-task'; import * as TaskManager from 'expo-task-manager'; import pLimit from 'p-limit'; import { getUploadTaskStatus, initUploadTable, insertUploadTask } from '../db'; import { getMediaByDateRange } from './media'; import { processAndUploadMedia } from './uploader'; const BACKGROUND_UPLOAD_TASK = 'background-upload-task'; const CONCURRENCY_LIMIT = 3; // 后台上传并发数,例如同时上传3个文件 const limit = pLimit(CONCURRENCY_LIMIT); // 注册后台任务 export const registerBackgroundUploadTask = async () => { try { // 初始化数据库表 await initUploadTable(); const isRegistered = await TaskManager.isTaskRegisteredAsync(BACKGROUND_UPLOAD_TASK); if (isRegistered) { console.log('Background task already registered.'); } else { await BackgroundTask.registerTaskAsync(BACKGROUND_UPLOAD_TASK, { minimumInterval: 15 * 60, // 15 分钟 }); console.log('Background task registered successfully.'); } return true; } catch (error) { console.error('Error registering background task:', error); return false; } }; // 定义后台任务 TaskManager.defineTask(BACKGROUND_UPLOAD_TASK, async () => { try { console.log('Running background upload task...'); const now = new Date(); const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000); // 获取最近24小时的媒体文件 const media = await getMediaByDateRange(oneDayAgo, now); if (media.length === 0) { console.log('No new media files to upload in the last 24 hours.'); return BackgroundTask.BackgroundTaskResult.Success; } console.log(`Found ${media.length} media files to potentially upload.`); // 并发上传文件 let successCount = 0; let skippedCount = 0; let failedCount = 0; const uploadPromises = media.map((file) => limit(async () => { try { const existingTask = await getUploadTaskStatus(file.uri); if (!existingTask) { await insertUploadTask(file.uri, file.filename); } else if (existingTask.status === 'success' || existingTask.status === 'skipped') { console.log(`File ${file.uri} already ${existingTask.status}, skipping processing.`); return { status: 'skipped' }; // 返回状态以便统计 } const result = await processAndUploadMedia(file); if (result === null) { return { status: 'skipped' }; } else if (result.originalSuccess) { return { status: 'success' }; } else { return { status: 'failed' }; } } catch (e) { console.error('Upload failed for', file.uri, e); return { status: 'failed' }; } }) ); const results = await Promise.all(uploadPromises); results.forEach(result => { if (result.status === 'success') { successCount++; } else if (result.status === 'skipped') { skippedCount++; } else if (result.status === 'failed') { failedCount++; } }); console.log(`Background upload task finished. Successful: ${successCount}, Skipped: ${skippedCount}, Failed: ${failedCount}, Total: ${media.length}`); return BackgroundTask.BackgroundTaskResult.Success; } catch (error) { console.error('Background task error:', error); return BackgroundTask.BackgroundTaskResult.Failed; } });