Skip to content

Commit a3068ee

Browse files
authored
Add retry mechanism for thread listing failures in syncThreads (#1931)
# READ CAREFULLY THEN REMOVE Remove bullet points that are not relevant. PLEASE REFRAIN FROM USING AI TO WRITE YOUR CODE AND PR DESCRIPTION. IF YOU DO USE AI TO WRITE YOUR CODE PLEASE PROVIDE A DESCRIPTION AND REVIEW IT CAREFULLY. MAKE SURE YOU UNDERSTAND THE CODE YOU ARE SUBMITTING USING AI. - Pull requests that do not follow these guidelines will be closed without review or comment. - If you use AI to write your PR description your pr will be close without review or comment. - If you are unsure about anything, feel free to ask for clarification. ## Description Please provide a clear description of your changes. --- ## Type of Change Please delete options that are not relevant. - [ ] 🐛 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (non-breaking change which adds functionality) - [ ] 💥 Breaking change (fix or feature with breaking changes) - [ ] 📝 Documentation update - [ ] 🎨 UI/UX improvement - [ ] 🔒 Security enhancement - [ ] ⚡ Performance improvement ## Areas Affected Please check all that apply: - [ ] Email Integration (Gmail, IMAP, etc.) - [ ] User Interface/Experience - [ ] Authentication/Authorization - [ ] Data Storage/Management - [ ] API Endpoints - [ ] Documentation - [ ] Testing Infrastructure - [ ] Development Workflow - [ ] Deployment/Infrastructure ## Testing Done Describe the tests you've done: - [ ] Unit tests added/updated - [ ] Integration tests added/updated - [ ] Manual testing performed - [ ] Cross-browser testing (if UI changes) - [ ] Mobile responsiveness verified (if UI changes) ## Security Considerations For changes involving data or authentication: - [ ] No sensitive data is exposed - [ ] Authentication checks are in place - [ ] Input validation is implemented - [ ] Rate limiting is considered (if applicable) ## Checklist - [ ] I have read the [CONTRIBUTING](https://github.com/Mail-0/Zero/blob/staging/.github/CONTRIBUTING.md) document - [ ] My code follows the project's style guidelines - [ ] I have performed a self-review of my code - [ ] I have commented my code, particularly in complex areas - [ ] I have updated the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix/feature works - [ ] All tests pass locally - [ ] Any dependent changes are merged and published ## Additional Notes Add any other context about the pull request here. ## Screenshots/Recordings Add screenshots or recordings here if applicable. --- _By submitting this pull request, I confirm that my contribution is made under the terms of the project's license._ <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Added a retry mechanism to syncThreads so that if thread listing fails, it waits 1 minute and retries the same page instead of skipping it. - **Bug Fixes** - Prevents data loss by ensuring failed thread listing pages are retried, not skipped. <!-- End of auto-generated description by cubic. --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved error handling and retry logic to prevent immediate failures when listing threads, enabling automatic retries after a short delay. * Enhanced logging to provide clearer information about retry attempts and page processing status. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent ee246db commit a3068ee

File tree

1 file changed

+32
-22
lines changed

1 file changed

+32
-22
lines changed

apps/server/src/routes/agent/index.ts

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,35 +1214,45 @@ export class ZeroDriver extends DurableObject<ZeroEnv> {
12141214
}),
12151215
),
12161216
Effect.catchAll((error) => {
1217-
console.error(`[syncThreads] Failed to list threads for folder ${folder}:`, error);
1218-
return Effect.fail(
1219-
new ThreadListError(`Failed to list threads for folder ${folder}`, error),
1217+
console.error(`[syncThreads] Failed to list threads for folder ${folder}, retrying in 1 minute:`, error);
1218+
return Effect.sleep('1 minute').pipe(
1219+
Effect.tap(() => Effect.sync(() =>
1220+
console.log(`[syncThreads] Retrying page ${result.pagesProcessed} for folder ${folder}`)
1221+
)),
1222+
Effect.andThen(() => Effect.succeed({ threads: [], nextPageToken: pageToken }))
12201223
);
12211224
}),
12221225
);
12231226

1224-
// Process threads with controlled concurrency to avoid rate limits
1225-
const threadIds = listResult.threads.map((thread) => thread.id);
1226-
const syncEffects = threadIds.map(syncSingleThread);
1227+
// Only process threads if we actually got some (not a retry with empty result)
1228+
if (listResult.threads.length > 0) {
1229+
// Process threads with controlled concurrency to avoid rate limits
1230+
const threadIds = listResult.threads.map((thread) => thread.id);
1231+
const syncEffects = threadIds.map(syncSingleThread);
12271232

1228-
yield* Effect.all(syncEffects, { concurrency: 1, discard: true }).pipe(
1229-
Effect.tap(() =>
1230-
Effect.sync(() =>
1231-
console.log(`[syncThreads] Completed page ${result.pagesProcessed}`),
1233+
yield* Effect.all(syncEffects, { concurrency: 1, discard: true }).pipe(
1234+
Effect.tap(() =>
1235+
Effect.sync(() =>
1236+
console.log(`[syncThreads] Completed page ${result.pagesProcessed}`),
1237+
),
12321238
),
1233-
),
1234-
Effect.catchAll((error) => {
1235-
console.error(
1236-
`[syncThreads] Failed to process threads on page ${result.pagesProcessed}:`,
1237-
error,
1238-
);
1239-
return Effect.succeed(undefined);
1240-
}),
1241-
);
1239+
Effect.catchAll((error) => {
1240+
console.error(
1241+
`[syncThreads] Failed to process threads on page ${result.pagesProcessed}:`,
1242+
error,
1243+
);
1244+
return Effect.succeed(undefined);
1245+
}),
1246+
);
12421247

1243-
result.synced += listResult.threads.length;
1244-
pageToken = listResult.nextPageToken;
1245-
hasMore = pageToken !== null && shouldLoop;
1248+
result.synced += listResult.threads.length;
1249+
pageToken = listResult.nextPageToken;
1250+
hasMore = pageToken !== null && shouldLoop;
1251+
} else {
1252+
// This was a retry, don't update pageToken or hasMore - retry the same page
1253+
console.log(`[syncThreads] Retrying same page ${result.pagesProcessed} after error`);
1254+
result.pagesProcessed--; // Don't count failed pages
1255+
}
12461256

12471257
// Send state update after first page is processed to give accurate feedback
12481258
if (!firstPageProcessed) {

0 commit comments

Comments
 (0)