Skip to content

Give the Supabase and object-storage clients a request timeout #215

Description

@HMarzban

Problem

Neither client sets a timeout.

The object-storage client is built with credentials, bucket and endpoint only (apps/hocuspocus.server/src/lib/storage/storage.s3.ts:8-13). The Supabase clients set auth options only (apps/hocuspocus.server/src/lib/supabase.ts:13 and apps/hocuspocus.server/src/lib/supabase.ts:23-25). Neither file contains the string timeout.

A black-holed endpoint therefore holds the caller until the socket closes.

Token verification runs through the anon client (apps/hocuspocus.server/src/lib/auth.ts:86). A cache sits in front of it, const TOKEN_CACHE_TTL_MS = 60_000 (apps/hocuspocus.server/src/lib/auth.ts:52). So only a cache miss reaches Supabase. A miss can happen on the REST middleware path (apps/hocuspocus.server/src/api/middleware/auth.ts:29) and on the collaboration handshake (apps/hocuspocus.server/src/hocuspocus.server.ts:458). A stalled Supabase then stalls people signing in and reconnecting.

Two paths already bound themselves. The health probe sets .abortSignal(AbortSignal.timeout(2000)) (apps/hocuspocus.server/src/api/services/health.service.ts:73). The raw PostgREST helper supabaseRest sets signal: init?.signal ?? AbortSignal.timeout(SUPABASE_FETCH_TIMEOUT_MS) (apps/hocuspocus.server/src/api/utils/supabase.ts:21). That constant is const SUPABASE_FETCH_TIMEOUT_MS = 10_000 (apps/hocuspocus.server/src/api/utils/supabase.ts:8). Every other call made through the two clients carries no deadline.

What to do

Give both clients a default per-request deadline.

For Supabase, pass a global.fetch that attaches an AbortSignal.timeout. For object storage, wrap each call so it fails at a fixed deadline instead of at socket close.

Pick a bound that matches the one already in the tree. supabaseRest uses 10 s.

Acceptance

  • A call routed to a black-holed endpoint fails within the deadline, not at socket close.
  • The timeout failure is logged, and names which client timed out.
  • The health probe keeps its own 2 s bound.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions