2.8 KiB
2.8 KiB
Caching, Retries, and Failure Semantics
GET lifecycle
- Build full URL from
baseUrl,path, and query params. - Check cache by full URL.
- Fetch with auth headers and timeout on cache miss.
- Retry network errors, timeout errors,
429, and5xx. - Parse JSON.
- Throw
SocialhoseErrorfor unsupported non-OK responses. - Store successful parsed response in cache.
POST lifecycle
- Build URL.
- Fetch JSON body with auth headers and timeout.
- Retry network errors, timeout errors,
429, and5xx. - Parse JSON.
- Return
{ status, data }. - Never cache.
Retry policy
Defaults:
retries: 3,
retryDelayMs: (attempt) => 400 * 2 ** attempt + Math.random() * 200,
timeoutMs: 8_000,
Retries apply to transient conditions only:
- network failures
- SDK timeout/abort failures
429 Too Many Requests5xxserver errors
Retries do not apply to normal client errors such as 400, 401, 403, and 404.
Cache contract
interface Cache {
get(key: string): Promise<unknown | undefined>;
set(key: string, value: unknown, ttlMs: number): Promise<void>;
delete(key: string): Promise<void>;
}
The cache key is the full request URL. ttlMs is in milliseconds and comes from cacheTtlMs or per-request revalidateSeconds.
Redis-style cache example
import { SocialhoseClient, type Cache } from '@socialhose/api';
class RedisJsonCache implements Cache {
constructor(private redis: {
get(k: string): Promise<string | null>;
set(k: string, v: string, mode: 'PX', ttl: number): Promise<unknown>;
del(k: string): Promise<unknown>;
}) {}
async get(key: string) {
const value = await this.redis.get(key);
return value == null ? undefined : JSON.parse(value);
}
async set(key: string, value: unknown, ttlMs: number) {
if (ttlMs <= 0) return;
await this.redis.set(key, JSON.stringify(value), 'PX', ttlMs);
}
async delete(key: string) {
await this.redis.del(key);
}
}
const socialhose = new SocialhoseClient({
apiKey: process.env.SOCIALHOSE_API_KEY!,
cache: new RedisJsonCache(redis),
});
Method failure semantics
Campaign, analytics, mention, and list methods:
- Throw
SocialhoseErrorafter retry exhaustion or unsupported non-OK responses. - Return normalized arrays when the API wraps arrays in properties such as
series,platforms, orkeywords.
inviteMailingListMember():
201 + status: invited->outcome: 'invited'.409->outcome: 'already'.- Unexpected success/conflict shapes ->
outcome: 'error'. - Other non-OK statuses throw.
Entity methods:
getEntityBrief()throws if the mention search fails.getEntityStats()requires the initial brief but treats later subrequests as best-effort.getEntityBriefs()skips failed terms and returns successful entries.