experimental-a2 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/ai-server.js +1 -1
- package/dist/client.js +1 -1
- package/dist/http.js +1 -1
- package/dist/{internal-D6wNxTck.js → internal-gCd5qMry.js} +9 -1
- package/dist/{log-polling-6COoN60V.js → log-polling-DZ1MiKLg.js} +3 -2
- package/dist/log-postgres.js +1 -1
- package/dist/log-redis-core-CyJ5L8yR.js +836 -0
- package/dist/log-redis-http.d.ts +21 -0
- package/dist/log-redis-http.js +62 -0
- package/dist/log-redis.d.ts +10 -4
- package/dist/log-redis.js +165 -828
- package/dist/log-sqlite.js +1 -1
- package/dist/recovery-vercel.js +1 -1
- package/dist/{server-DJgD2YWP.js → server-BcLa4RFL.js} +1 -1
- package/dist/server.js +1 -1
- package/docs/01-quickstart.mdx +1 -2
- package/docs/concepts/01-contracts.mdx +3 -4
- package/docs/concepts/03-durability.mdx +6 -9
- package/docs/guides/01-timers.mdx +4 -9
- package/docs/guides/05-production.mdx +14 -2
- package/docs/index.mdx +7 -35
- package/docs/reference/01-api.mdx +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { c as IdSource, i as Clock, t as A2Log } from "./log-ldf5g8Cx.js";
|
|
2
|
+
//#region src/log-redis-http.d.ts
|
|
3
|
+
type RedisHttpLogOptions = {
|
|
4
|
+
/** REST endpoint, e.g. `process.env.UPSTASH_REDIS_REST_URL`. */
|
|
5
|
+
url: string;
|
|
6
|
+
/** Bearer token, e.g. `process.env.UPSTASH_REDIS_REST_TOKEN`. */
|
|
7
|
+
token: string;
|
|
8
|
+
/** Key prefix — isolates multiple apps on one Redis. Default `'a2'`. */
|
|
9
|
+
keyPrefix?: string;
|
|
10
|
+
/** Injectable clock — every stored timestamp comes from here. */
|
|
11
|
+
clock?: Clock;
|
|
12
|
+
/** Injectable id source for generated event ids. */
|
|
13
|
+
ids?: IdSource;
|
|
14
|
+
};
|
|
15
|
+
type RedisHttpLog = A2Log & {
|
|
16
|
+
/** Nothing to disconnect; present so callers can treat logs uniformly. */
|
|
17
|
+
close(): Promise<void>;
|
|
18
|
+
};
|
|
19
|
+
declare function redisHttp(options: RedisHttpLogOptions): RedisHttpLog;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { RedisHttpLog, RedisHttpLogOptions, redisHttp };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { t as A2Error } from "./errors-BJRMd-h6.js";
|
|
2
|
+
import { n as SYSTEM_CLOCK, t as RANDOM_IDS } from "./log-yJbXUf72.js";
|
|
3
|
+
import { n as pollingStream } from "./log-polling-DZ1MiKLg.js";
|
|
4
|
+
import { t as createRedisLogCore } from "./log-redis-core-CyJ5L8yR.js";
|
|
5
|
+
//#region src/log-redis-http.ts
|
|
6
|
+
/**
|
|
7
|
+
* experimental-a2/log-redis-http — the same Redis Streams log over a
|
|
8
|
+
* provider REST API (Upstash-shaped: POST one command as a JSON array,
|
|
9
|
+
* receive `{ result }` or `{ error }`). The storage semantics live in
|
|
10
|
+
* log-redis-core.ts, shared with experimental-a2/log-redis.
|
|
11
|
+
*
|
|
12
|
+
* Fully connectionless: every command is one `fetch`, so it works
|
|
13
|
+
* where a Redis-protocol connection cannot exist or cannot be spared.
|
|
14
|
+
* Without a connection there is no push and no pub/sub, so `stream()`
|
|
15
|
+
* is the shared activity-adaptive poll loop (25ms while events flow,
|
|
16
|
+
* backing off to a 250ms idle ceiling). No peer dependencies.
|
|
17
|
+
*/
|
|
18
|
+
function redisHttp(options) {
|
|
19
|
+
if (!options.url || !options.token) throw new TypeError("redisHttp() needs a url and a token");
|
|
20
|
+
const { url, token } = options;
|
|
21
|
+
const call = async (command, ...args) => {
|
|
22
|
+
let response;
|
|
23
|
+
try {
|
|
24
|
+
response = await fetch(url, {
|
|
25
|
+
method: "POST",
|
|
26
|
+
headers: {
|
|
27
|
+
authorization: `Bearer ${token}`,
|
|
28
|
+
"content-type": "application/json"
|
|
29
|
+
},
|
|
30
|
+
body: JSON.stringify([command, ...args.map(String)])
|
|
31
|
+
});
|
|
32
|
+
} catch (err) {
|
|
33
|
+
throw new A2Error("LOG_UNAVAILABLE", "redis rest request failed", { cause: err });
|
|
34
|
+
}
|
|
35
|
+
const body = await response.json().catch(() => null);
|
|
36
|
+
if (body === null || !response.ok || body.error !== void 0) throw new A2Error("LOG_UNAVAILABLE", `redis rest command failed: ${body?.error ?? `status ${response.status}`}`);
|
|
37
|
+
return body.result;
|
|
38
|
+
};
|
|
39
|
+
const core = createRedisLogCore({
|
|
40
|
+
call,
|
|
41
|
+
clock: options.clock ?? SYSTEM_CLOCK,
|
|
42
|
+
ids: options.ids ?? RANDOM_IDS,
|
|
43
|
+
keyPrefix: options.keyPrefix ?? "a2"
|
|
44
|
+
});
|
|
45
|
+
return {
|
|
46
|
+
append: core.append,
|
|
47
|
+
read: core.read,
|
|
48
|
+
claimAvailable: core.claimAvailable,
|
|
49
|
+
renewClaims: core.renewClaims,
|
|
50
|
+
completeAttempt: core.completeAttempt,
|
|
51
|
+
failAttempt: core.failAttempt,
|
|
52
|
+
readState: core.readState,
|
|
53
|
+
putSnapshot: core.putSnapshot,
|
|
54
|
+
inspect: core.inspect,
|
|
55
|
+
stream(sessionId, opts) {
|
|
56
|
+
return pollingStream((afterIndex) => core.readRange(sessionId, afterIndex), opts?.startAt !== void 0 ? { startAt: opts.startAt } : {});
|
|
57
|
+
},
|
|
58
|
+
async close() {}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
export { redisHttp };
|
package/dist/log-redis.d.ts
CHANGED
|
@@ -2,18 +2,24 @@ import { c as IdSource, i as Clock, t as A2Log } from "./log-ldf5g8Cx.js";
|
|
|
2
2
|
//#region src/log-redis.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* The minimal client this backend needs — `ioredis` matches it
|
|
5
|
-
* structurally. `call` issues any command; `duplicate` opens the
|
|
6
|
-
*
|
|
5
|
+
* structurally. `call` issues any command; `duplicate` opens the one
|
|
6
|
+
* shared subscriber connection; `on` delivers its pub/sub messages.
|
|
7
|
+
*
|
|
8
|
+
* The client must restore its subscriptions after a reconnect
|
|
9
|
+
* (`ioredis` does). One that doesn't stays correct — the safety
|
|
10
|
+
* re-read delivers everything — but every live feed silently degrades
|
|
11
|
+
* to safety-read latency from that point on.
|
|
7
12
|
*/
|
|
8
13
|
type RedisConnection = {
|
|
9
14
|
call(command: string, ...args: Array<string | number>): Promise<unknown>;
|
|
10
15
|
duplicate(): RedisConnection;
|
|
16
|
+
on(event: "message", listener: (channel: string, message: string) => void): unknown;
|
|
11
17
|
disconnect(): void;
|
|
12
18
|
};
|
|
13
19
|
type RedisLogOptions = {
|
|
14
20
|
/** Creates an `ioredis` client lazily (optional peer dep `ioredis`). */
|
|
15
21
|
url?: string | undefined;
|
|
16
|
-
/** Bring your own client — anything `call`/`duplicate`/`disconnect`. */
|
|
22
|
+
/** Bring your own client — anything `call`/`duplicate`/`on`/`disconnect`. */
|
|
17
23
|
client?: RedisConnection;
|
|
18
24
|
/** Key prefix — isolates multiple apps on one Redis. Default `'a2'`. */
|
|
19
25
|
keyPrefix?: string;
|
|
@@ -23,7 +29,7 @@ type RedisLogOptions = {
|
|
|
23
29
|
ids?: IdSource;
|
|
24
30
|
};
|
|
25
31
|
type RedisLog = A2Log & {
|
|
26
|
-
/** Disconnect the client and
|
|
32
|
+
/** Disconnect the command client and the shared subscriber. */
|
|
27
33
|
close(): Promise<void>;
|
|
28
34
|
};
|
|
29
35
|
declare function redis(options?: RedisLogOptions): RedisLog;
|