Always retry forever
This commit is contained in:
parent
2e827b6da5
commit
a75b3469a3
2 changed files with 4 additions and 10 deletions
|
|
@ -303,7 +303,7 @@ When the server broadcasts updates via WebSocket:
|
||||||
|
|
||||||
7. **Key resolution with stale documentIds**: When `resolveIdempotencyKeys` returns a documentId, check `getDocumentByDocumentId` first. If another document already has that ID (assigned through normal sync), remove the stale pending doc instead of creating a duplicate.
|
7. **Key resolution with stale documentIds**: When `resolveIdempotencyKeys` returns a documentId, check `getDocumentByDocumentId` first. If another document already has that ID (assigned through normal sync), remove the stale pending doc instead of creating a duplicate.
|
||||||
|
|
||||||
8. **`resolveIdempotencyKeys` must not use `retryForever`**: The HTTP call to `/documents/resolve-keys` is an optimization. If it fails (e.g., SyncReset aborts the fetch), return an empty map and let the pending creates retry normally with their keys. Using `retryForever` can cause deadlocks — the sync pipeline stalls waiting for the retry while the WebSocket is disconnected.
|
8. **`resolveIdempotencyKeys` uses `retryForever`**: The HTTP call to `/documents/resolve-keys` retries forever like all other sync service calls. `SyncResetError` is re-thrown by `retryForever`, so the pipeline properly aborts on WebSocket disconnect without deadlocking.
|
||||||
|
|
||||||
### E2E Test Configuration
|
### E2E Test Configuration
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -375,7 +375,7 @@ export class SyncService {
|
||||||
`Resolving ${keys.length} idempotency keys`
|
`Resolving ${keys.length} idempotency keys`
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
return this.retryForever(async () => {
|
||||||
const response = await this.client(
|
const response = await this.client(
|
||||||
this.getUrl("/documents/resolve-keys"),
|
this.getUrl("/documents/resolve-keys"),
|
||||||
{
|
{
|
||||||
|
|
@ -386,12 +386,11 @@ export class SyncService {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
this.logger.warn(
|
throw new Error(
|
||||||
`Failed to resolve idempotency keys: ${await SyncService.errorFromResponse(
|
`Failed to resolve idempotency keys: ${await SyncService.errorFromResponse(
|
||||||
response
|
response
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
return new Map();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const result: { resolved: Record<string, string> } =
|
const result: { resolved: Record<string, string> } =
|
||||||
|
|
@ -406,12 +405,7 @@ export class SyncService {
|
||||||
);
|
);
|
||||||
|
|
||||||
return resolved;
|
return resolved;
|
||||||
} catch (e) {
|
});
|
||||||
this.logger.warn(
|
|
||||||
`Failed to resolve idempotency keys: ${e}`
|
|
||||||
);
|
|
||||||
return new Map();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ping(): Promise<PingResponse> {
|
public async ping(): Promise<PingResponse> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue