Skip to content

sufyman/directus-timeouts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

directus-timeouts

Opinionated timeout tiers, retry, and exponential-backoff helpers for Directus clients. Tune by tier instead of hand-coding timeouts on every call. Works with the Directus SDK, plain fetch, or axios.

npm install directus-timeouts

Why

The Directus SDK doesn't ship timeout or retry primitives. Every consumer reinvents:

  • "What timeout do I use for this kind of query?"
  • "Should I retry on 502? On ECONNRESET?"
  • "How do I add backoff without pulling in a 200KB dep?"

This package gives you four tuned tiers (fast / standard / heavy / critical), a retryable-error matcher that matches what Directus actually returns under load, and a tieredFetch wrapper you can drop straight into createDirectus(...).with(rest({ fetch: tieredFetch("standard") })).

Tiers (defaults, ms)

Tier Timeout Use for
fast 8,000 Single-record fetches, simple filters
standard 15,000 Most reads
heavy 25,000 Complex filters, deep relations, exports
critical 45,000 File uploads, batch writes, "must succeed"

Usage with the Directus SDK

import { createDirectus, rest, readItems } from "@directus/sdk";
import { tieredFetch, withRetry } from "directus-timeouts";

const directus = createDirectus(process.env.DIRECTUS_URL!).with(
  rest({ fetch: tieredFetch("standard") }),
);

// Add retry + backoff to any call:
const posts = await withRetry(() => directus.request(readItems("posts")));

Usage with plain fetch

import { tieredFetch } from "directus-timeouts";

const f = tieredFetch("heavy");
const res = await f("https://cms.example.com/items/big-export");

Usage with axios

import axios from "axios";
import { createAxiosConfig } from "directus-timeouts";

await axios.get("/items/posts", createAxiosConfig("fast"));

API

getTimeout(tier?: TimeoutTier, overrides?): number
backoffDelay(attempt: number, options?: RetryOptions): number
isRetryableError(error: unknown): boolean
withRetry<T>(fn: () => Promise<T>, options?: RetryOptions & { onRetry? }): Promise<T>
tieredFetch(tier?: TimeoutTier, options?: { overrides?; baseFetch? }): typeof fetch
createAxiosConfig(tier?, headers?): { timeout, headers }

DEFAULT_TIMEOUTS // { fast, standard, heavy, critical }
DEFAULT_RETRY    // { maxAttempts, baseDelayMs, exponentialBackoff, jitter }

Retry decisions

isRetryableError returns true for:

  • AbortError
  • ECONNABORTED, ECONNRESET, ETIMEDOUT
  • Errors whose message contains timeout / network / fetch failed
  • HTTP 429 (rate limit)
  • HTTP 5xx

Everything else (including 4xx) is non-retryable and propagated immediately.

Backoff with jitter

Delay = baseDelayMs * 2^(attempt-1) ± up to 20% jitter, so a thundering herd doesn't synchronize.

License

MIT

About

Opinionated timeout tiers, retry, and exponential backoff helpers for Directus. Drop into the SDK or any fetch/axios client to stop random 30s hangs.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors