docs: expand JavaScript SDK documentation
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
# Caching, Retries, and Failure Semantics
|
||||
|
||||
## GET lifecycle
|
||||
|
||||
1. Build full URL from `baseUrl`, `path`, and query params.
|
||||
2. Check cache by full URL.
|
||||
3. Fetch with auth headers and timeout on cache miss.
|
||||
4. Retry network errors, timeout errors, `429`, and `5xx`.
|
||||
5. Parse JSON.
|
||||
6. Throw `SocialhoseError` for unsupported non-OK responses.
|
||||
7. Store successful parsed response in cache.
|
||||
|
||||
## POST lifecycle
|
||||
|
||||
1. Build URL.
|
||||
2. Fetch JSON body with auth headers and timeout.
|
||||
3. Retry network errors, timeout errors, `429`, and `5xx`.
|
||||
4. Parse JSON.
|
||||
5. Return `{ status, data }`.
|
||||
6. Never cache.
|
||||
|
||||
## Retry policy
|
||||
|
||||
Defaults:
|
||||
|
||||
```ts
|
||||
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 Requests`
|
||||
- `5xx` server errors
|
||||
|
||||
Retries do not apply to normal client errors such as `400`, `401`, `403`, and `404`.
|
||||
|
||||
## Cache contract
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
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 `SocialhoseError` after retry exhaustion or unsupported non-OK responses.
|
||||
- Return normalized arrays when the API wraps arrays in properties such as `series`, `platforms`, or `keywords`.
|
||||
|
||||
`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.
|
||||
Reference in New Issue
Block a user