feat: 后台任务并发

This commit is contained in:
Junhui Chen 2025-07-17 00:45:33 +08:00
parent e7e2c05bcd
commit e2c5493c8c
2 changed files with 40 additions and 24 deletions

View File

@ -1,11 +1,15 @@
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 {
@ -45,38 +49,48 @@ TaskManager.defineTask(BACKGROUND_UPLOAD_TASK, async () => {
console.log(`Found ${media.length} media files to potentially upload.`);
// 串行上传文件
// 并发上传文件
let successCount = 0;
let skippedCount = 0;
let failedCount = 0;
for (const file of media) {
try {
const existingTask = await getUploadTaskStatus(file.uri);
if (!existingTask) {
// If not in DB, insert as pending
await insertUploadTask(file.uri, file.filename);
} else if (existingTask.status === 'success' || existingTask.status === 'skipped') {
console.log(`File ${file.uri} already ${existingTask.status}, skipping processing.`);
skippedCount++;
continue; // Skip processing if already successful or skipped
}
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) {
// Skipped by processAndUploadMedia (e.g., already uploaded)
skippedCount++;
} else if (result.originalSuccess) {
successCount++;
} else {
// Failed
failedCount++;
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' };
}
} catch (e) {
console.error('Upload failed for', file.uri, e);
})
);
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}`);

View File

@ -19,6 +19,7 @@
"@react-navigation/elements": "^2.3.8",
"@react-navigation/native": "^7.1.6",
"@reduxjs/toolkit": "^2.8.2",
"@types/p-limit": "^2.2.0",
"@types/react-redux": "^7.1.34",
"expo": "~53.0.12",
"expo-audio": "~0.4.7",
@ -53,6 +54,7 @@
"i18next-http-backend": "^3.0.2",
"lottie-react-native": "7.2.2",
"nativewind": "^4.1.23",
"p-limit": "^6.2.0",
"react": "19.0.0",
"react-dom": "19.0.0",
"react-i18next": "^15.5.3",