Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions docs/development/troubleshoot.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,37 @@ To fix this:
2. Copy the exact connection URI and API key from your Supertokens dashboard
3. Verify the connection URI format matches what Supertokens provides (should include the protocol, domain, and port if applicable)
4. Ensure there are no extra spaces or characters in the environment variable values

## Google Calendar Repair Fails Or Stops Unexpectedly

When a user triggers repair from the UI (`Repair Google Calendar`) and the flow
does not complete as expected, first classify the failure mode from the message
and websocket behavior.

### Quota / rate-limit during repair

If the user sees:

- `Google Calendar repair hit a Google API limit. Please wait a few minutes and try again.`

then backend detected a Google quota/rate-limit response (`403`/`429`), and this
is usually transient.

Recommended action:

1. wait a few minutes
2. retry repair
3. if this repeats across many users, investigate Google API quota usage for the project

### Revoked token during repair

If access was revoked (for example Google returns `invalid_grant`), backend
prunes Google data and emits `GOOGLE_REVOKED`.

Operational notes:

- this path does **not** end with an `IMPORT_GCAL_END` payload with
`status: "ERRORED"`
- UI should transition to reconnect-required behavior rather than repeatedly
retrying repair
- user action is to reconnect Google, then allow sync/import restart
94 changes: 94 additions & 0 deletions docs/features/google-sync-and-websocket-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,41 @@ Important server-to-client events:
- `IMPORT_GCAL_END`
- `GOOGLE_REVOKED`

### `IMPORT_GCAL_END` Payload Contract

Source files:

- `packages/core/src/types/websocket.types.ts`
- `packages/backend/src/user/services/user.service.ts`
- `packages/backend/src/sync/services/sync.service.ts`

`IMPORT_GCAL_END` now carries an explicit `operation` so the client can distinguish
repair completion from incremental completion.

```ts
type ImportGCalOperation = "INCREMENTAL" | "REPAIR";

type ImportGCalEndPayload =
| {
operation: ImportGCalOperation;
status: "COMPLETED";
eventsCount?: number;
calendarsCount?: number;
}
| {
operation: ImportGCalOperation;
status: "ERRORED" | "IGNORED";
message: string;
};
```

Operational constraints:

- repair path (`restartGoogleCalendarSync`) emits `operation: "REPAIR"`
- incremental path (`importIncremental`) emits `operation: "INCREMENTAL"`
- web listeners should keep a defensive `payload?` handler for compatibility with
older emitters/tests

## Outbound Flow: User Changes An Event In Compass

High-level path:
Expand Down Expand Up @@ -83,6 +118,10 @@ Important error handling behavior:
- response is `204` either way
- invalid/revoked Google token (`invalid_grant`):
- backend prunes Google data, emits `GOOGLE_REVOKED`, returns revoked payload
- invalid/revoked token during repair flow:
- backend repair catches `invalid_grant`, prunes Google data, emits
`GOOGLE_REVOKED`, and exits repair without sending `IMPORT_GCAL_END` with
`status: "ERRORED"`

## Watch And Sync Records

Expand Down Expand Up @@ -205,6 +244,10 @@ The client:
- handles Google revocation
- requests `USER_METADATA` to drive connection-state UI and import restart decisions
- auto-starts import only when metadata says `sync.importGCal === "RESTART"` and the Google connection is usable
- tracks a dedicated repair-in-progress state (`isRepairing`) separate from
background incremental sync (`isProcessing`)
- only shows a toast for repair failures, and de-duplicates it with a stable toast id
(`GOOGLE_REPAIR_FAILED_TOAST_ID`)

## Revoked Token And Reconnect Lifecycle

Expand Down Expand Up @@ -342,6 +385,57 @@ Google import progress is also realtime:
4. backend completes import and emits `IMPORT_GCAL_END`
5. client stores import results and triggers a refetch

### Operation-Aware Import Completion Semantics

Source files:

- `packages/web/src/socket/hooks/useGcalSync.ts`
- `packages/web/src/auth/hooks/oauth/useConnectGoogle.ts`
- `packages/web/src/ducks/events/slices/sync.slice.ts`

`IMPORT_GCAL_END` handling is operation-aware:

- `operation: "REPAIR"`
- always stops repair spinner/state
- `ERRORED`:
- stores `importError`
- shows one repair-failure toast (de-duped by id)
- `COMPLETED`:
- stores import counts in `importResults`
- triggers an events refetch
- `IGNORED`: no refetch
- `operation: "INCREMENTAL"`
- does **not** alter repair spinner/state
- `ERRORED`:
- stores `importError`
- does not show repair-failure toast
- `COMPLETED`: stores counts (if provided) and refetches

Examples:

```json
{ "operation": "REPAIR", "status": "COMPLETED", "eventsCount": 42, "calendarsCount": 3 }
```

```json
{ "operation": "INCREMENTAL", "status": "ERRORED", "message": "Incremental Google Calendar sync failed for user: 123" }
```

### Repair Failure Messaging

Source files:

- `packages/backend/src/common/services/gcal/gcal.utils.ts`
- `packages/backend/src/common/errors/integration/gcal/gcal.errors.ts`
- `packages/backend/src/user/services/user.service.ts`

Repair failures now normalize to two user-facing message classes:

- quota/rate-limit errors from Google (`403`/`429` with quota-style reasons or messages):
- `"Google Calendar repair hit a Google API limit. Please wait a few minutes and try again."`
- all other repair failures:
- `"Google Calendar repair failed. Please try again."`

### Manual Import Trigger Contract

Source files:
Expand Down
Loading