@rivetkit/effect 2.3.2 → 2.3.3-rc.2
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/dist/Actor.d.ts +2 -3
- package/dist/Actor.d.ts.map +1 -1
- package/dist/Actor.js +2 -2
- package/dist/Actor.js.map +1 -1
- package/dist/Client.d.ts.map +1 -1
- package/dist/Client.js +6 -4
- package/dist/Client.js.map +1 -1
- package/dist/Registry.d.ts +69 -7
- package/dist/Registry.d.ts.map +1 -1
- package/dist/Registry.js +93 -40
- package/dist/Registry.js.map +1 -1
- package/dist/RivetError.d.ts +18 -3
- package/dist/RivetError.d.ts.map +1 -1
- package/dist/RivetError.js +31 -0
- package/dist/RivetError.js.map +1 -1
- package/dist/RivetLogger.d.ts +41 -0
- package/dist/RivetLogger.d.ts.map +1 -0
- package/dist/RivetLogger.js +41 -0
- package/dist/RivetLogger.js.map +1 -0
- package/dist/State.d.ts +92 -56
- package/dist/State.d.ts.map +1 -1
- package/dist/State.js +51 -57
- package/dist/State.js.map +1 -1
- package/dist/internal/ActorInstanceManager.d.ts.map +1 -1
- package/dist/internal/ActorInstanceManager.js +4 -4
- package/dist/internal/ActorInstanceManager.js.map +1 -1
- package/dist/internal/ActorStateAdapter.d.ts +1 -1
- package/dist/internal/ActorStateAdapter.d.ts.map +1 -1
- package/dist/internal/ActorStateAdapter.js +2 -7
- package/dist/internal/ActorStateAdapter.js.map +1 -1
- package/dist/internal/StateOptions.d.ts +1 -0
- package/dist/internal/StateOptions.d.ts.map +1 -1
- package/dist/internal/logging.d.ts +6 -7
- package/dist/internal/logging.d.ts.map +1 -1
- package/dist/internal/logging.js +78 -102
- package/dist/internal/logging.js.map +1 -1
- package/dist/mod.d.ts +1 -1
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +1 -1
- package/dist/mod.js.map +1 -1
- package/package.json +3 -3
- package/src/Actor.test-d.ts +32 -0
- package/src/Actor.ts +29 -4
- package/src/Client.test.ts +21 -18
- package/src/Client.ts +6 -4
- package/src/Registry.test.ts +7 -11
- package/src/Registry.ts +116 -50
- package/src/RivetError.test.ts +11 -0
- package/src/RivetError.ts +37 -0
- package/src/RivetLogger.ts +60 -0
- package/src/State.test.ts +163 -4
- package/src/State.ts +293 -97
- package/src/internal/ActorInstanceManager.ts +4 -10
- package/src/internal/ActorStateAdapter.ts +5 -11
- package/src/internal/StateOptions.ts +4 -0
- package/src/internal/logging.test.ts +65 -88
- package/src/internal/logging.ts +103 -143
- package/src/mod.ts +1 -1
- package/dist/Logger.d.ts +0 -29
- package/dist/Logger.d.ts.map +0 -1
- package/dist/Logger.js +0 -31
- package/dist/Logger.js.map +0 -1
- package/src/Logger.ts +0 -43
package/src/Client.test.ts
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import { assert, describe, it } from "@effect/vitest";
|
|
2
|
-
import { Client,
|
|
2
|
+
import { Client, RivetError, RivetLogger } from "@rivetkit/effect";
|
|
3
3
|
import { Effect, Layer, Schema } from "effect";
|
|
4
4
|
import * as RivetkitErrors from "rivetkit/errors";
|
|
5
|
-
import
|
|
6
|
-
configureDefaultLogger,
|
|
7
|
-
getBaseLogger,
|
|
8
|
-
type Logger as PinoLogger,
|
|
9
|
-
} from "rivetkit/log";
|
|
5
|
+
import * as RivetkitLog from "rivetkit/log";
|
|
10
6
|
import * as ActionErrorEnvelope from "./internal/ActionErrorEnvelope";
|
|
11
7
|
|
|
12
8
|
function makeTestLogger(
|
|
@@ -15,7 +11,7 @@ function makeTestLogger(
|
|
|
15
11
|
readonly fields: Record<string, unknown>;
|
|
16
12
|
readonly msg: string | undefined;
|
|
17
13
|
}>,
|
|
18
|
-
):
|
|
14
|
+
): RivetkitLog.Logger {
|
|
19
15
|
const logger: Record<string, unknown> = {
|
|
20
16
|
level: "debug",
|
|
21
17
|
child: () => logger,
|
|
@@ -29,7 +25,7 @@ function makeTestLogger(
|
|
|
29
25
|
};
|
|
30
26
|
}
|
|
31
27
|
|
|
32
|
-
return logger as unknown as
|
|
28
|
+
return logger as unknown as RivetkitLog.Logger;
|
|
33
29
|
}
|
|
34
30
|
|
|
35
31
|
describe("Client", () => {
|
|
@@ -39,13 +35,15 @@ describe("Client", () => {
|
|
|
39
35
|
const baseLogger = makeTestLogger();
|
|
40
36
|
|
|
41
37
|
yield* Effect.addFinalizer(() =>
|
|
42
|
-
Effect.sync(() =>
|
|
38
|
+
Effect.sync(() =>
|
|
39
|
+
RivetkitLog.configureDefaultLogger("silent"),
|
|
40
|
+
),
|
|
43
41
|
);
|
|
44
42
|
yield* Client.make({
|
|
45
43
|
endpoint: "http://127.0.0.1:6420",
|
|
46
|
-
}).pipe(Effect.provide(
|
|
44
|
+
}).pipe(Effect.provide(RivetLogger.layerFromPino(baseLogger)));
|
|
47
45
|
|
|
48
|
-
assert.strictEqual(getBaseLogger(), baseLogger);
|
|
46
|
+
assert.strictEqual(RivetkitLog.getBaseLogger(), baseLogger);
|
|
49
47
|
}),
|
|
50
48
|
),
|
|
51
49
|
);
|
|
@@ -61,7 +59,9 @@ describe("Client", () => {
|
|
|
61
59
|
const baseLogger = makeTestLogger(entries);
|
|
62
60
|
|
|
63
61
|
yield* Effect.addFinalizer(() =>
|
|
64
|
-
Effect.sync(() =>
|
|
62
|
+
Effect.sync(() =>
|
|
63
|
+
RivetkitLog.configureDefaultLogger("silent"),
|
|
64
|
+
),
|
|
65
65
|
);
|
|
66
66
|
yield* Effect.gen(function* () {
|
|
67
67
|
yield* Client.Client;
|
|
@@ -73,16 +73,19 @@ describe("Client", () => {
|
|
|
73
73
|
Client.layer({
|
|
74
74
|
endpoint: "http://127.0.0.1:6420",
|
|
75
75
|
}).pipe(
|
|
76
|
-
Layer.provideMerge(
|
|
76
|
+
Layer.provideMerge(
|
|
77
|
+
RivetLogger.layerFromPino(baseLogger),
|
|
78
|
+
),
|
|
77
79
|
),
|
|
78
80
|
),
|
|
79
81
|
);
|
|
80
82
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
const entry = entries[0];
|
|
84
|
+
assert.ok(entry !== undefined);
|
|
85
|
+
assert.strictEqual(entry.level, "info");
|
|
86
|
+
assert.strictEqual(entry.msg, "client effect log");
|
|
87
|
+
assert.strictEqual(entry.fields.clientId, "test-client");
|
|
88
|
+
assert.strictEqual(typeof entry.fields.fiberId, "string");
|
|
86
89
|
assert.ok(
|
|
87
90
|
entries.some(
|
|
88
91
|
(entry) =>
|
package/src/Client.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Context, Effect, Layer, Record, Result, Schema } from "effect";
|
|
2
2
|
import * as RivetkitClient from "rivetkit/client";
|
|
3
3
|
import * as RivetkitErrors from "rivetkit/errors";
|
|
4
|
-
import
|
|
4
|
+
import * as RivetkitLog from "rivetkit/log";
|
|
5
5
|
import type * as Action from "./Action.ts";
|
|
6
6
|
import type * as Actor from "./Actor.ts";
|
|
7
7
|
import * as ActionErrorEnvelope from "./internal/ActionErrorEnvelope.ts";
|
|
8
8
|
import { getOrCreateBaseLogger } from "./internal/logging.ts";
|
|
9
9
|
import { rpcSystem, type TraceMeta } from "./internal/tracing.ts";
|
|
10
|
-
import * as
|
|
10
|
+
import * as RivetLogger from "./RivetLogger.ts";
|
|
11
11
|
import * as RivetError from "./RivetError.ts";
|
|
12
12
|
|
|
13
13
|
const TypeId = "~@rivetkit/effect/Client";
|
|
@@ -49,7 +49,9 @@ export const make = Effect.fnUntraced(function* (options: Options = {}) {
|
|
|
49
49
|
const baseLogger = yield* getOrCreateBaseLogger;
|
|
50
50
|
const rivetkitClient = yield* Effect.acquireRelease(
|
|
51
51
|
Effect.sync(() => {
|
|
52
|
-
|
|
52
|
+
// Raw RivetKit clients do not accept a logger in their config,
|
|
53
|
+
// so install the Effect-selected logger before construction.
|
|
54
|
+
RivetkitLog.configureBaseLogger(baseLogger);
|
|
53
55
|
return RivetkitClient.createClient(options);
|
|
54
56
|
}),
|
|
55
57
|
(c) => Effect.promise(() => c.dispose()),
|
|
@@ -146,7 +148,7 @@ export const layer = (options: Options = {}): Layer.Layer<Client> =>
|
|
|
146
148
|
Layer.unwrap(
|
|
147
149
|
Effect.map(getOrCreateBaseLogger, (baseLogger) =>
|
|
148
150
|
Layer.effect(Client, make(options)).pipe(
|
|
149
|
-
Layer.provideMerge(
|
|
151
|
+
Layer.provideMerge(RivetLogger.layerFromPino(baseLogger)),
|
|
150
152
|
),
|
|
151
153
|
),
|
|
152
154
|
);
|
package/src/Registry.test.ts
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import { assert, describe, it } from "@effect/vitest";
|
|
2
|
-
import { Action, Actor,
|
|
2
|
+
import { Action, Actor, Registry, RivetLogger } from "@rivetkit/effect";
|
|
3
3
|
import { Effect, Layer } from "effect";
|
|
4
4
|
import { HttpEffect } from "effect/unstable/http";
|
|
5
|
-
import
|
|
6
|
-
configureDefaultLogger,
|
|
7
|
-
getBaseLogger,
|
|
8
|
-
type Logger as PinoLogger,
|
|
9
|
-
} from "rivetkit/log";
|
|
5
|
+
import * as RivetkitLog from "rivetkit/log";
|
|
10
6
|
import { vi } from "vitest";
|
|
11
7
|
|
|
12
8
|
const TestActor = Actor.make("TestActor", {
|
|
@@ -28,7 +24,7 @@ const RegistryLive = ActorsLayer.pipe(
|
|
|
28
24
|
),
|
|
29
25
|
);
|
|
30
26
|
|
|
31
|
-
function makeTestLogger():
|
|
27
|
+
function makeTestLogger(): RivetkitLog.Logger {
|
|
32
28
|
const logger: Record<string, unknown> = {
|
|
33
29
|
level: "debug",
|
|
34
30
|
child: () => logger,
|
|
@@ -37,7 +33,7 @@ function makeTestLogger(): PinoLogger {
|
|
|
37
33
|
logger[level] = (): void => {};
|
|
38
34
|
}
|
|
39
35
|
|
|
40
|
-
return logger as unknown as
|
|
36
|
+
return logger as unknown as RivetkitLog.Logger;
|
|
41
37
|
}
|
|
42
38
|
|
|
43
39
|
describe("Registry.toWebHandler", () => {
|
|
@@ -224,7 +220,7 @@ describe("Registry.toWebHandler", () => {
|
|
|
224
220
|
it("uses a custom logger layer for the underlying RivetKit registry", async () => {
|
|
225
221
|
const baseLogger = makeTestLogger();
|
|
226
222
|
const CustomLoggerRegistryLive = RegistryLive.pipe(
|
|
227
|
-
Layer.provide(
|
|
223
|
+
Layer.provide(RivetLogger.layerFromPino(baseLogger)),
|
|
228
224
|
);
|
|
229
225
|
const { handler, dispose } = Registry.toWebHandler(
|
|
230
226
|
CustomLoggerRegistryLive,
|
|
@@ -236,10 +232,10 @@ describe("Registry.toWebHandler", () => {
|
|
|
236
232
|
);
|
|
237
233
|
|
|
238
234
|
assert.strictEqual(response.status, 200);
|
|
239
|
-
assert.strictEqual(getBaseLogger(), baseLogger);
|
|
235
|
+
assert.strictEqual(RivetkitLog.getBaseLogger(), baseLogger);
|
|
240
236
|
} finally {
|
|
241
237
|
await dispose();
|
|
242
|
-
configureDefaultLogger("silent");
|
|
238
|
+
RivetkitLog.configureDefaultLogger("silent");
|
|
243
239
|
}
|
|
244
240
|
});
|
|
245
241
|
|
package/src/Registry.ts
CHANGED
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
type HttpServerResponse,
|
|
8
8
|
} from "effect/unstable/http";
|
|
9
9
|
import * as Rivetkit from "rivetkit";
|
|
10
|
-
import
|
|
10
|
+
import * as RivetkitLog from "rivetkit/log";
|
|
11
11
|
import * as Client from "./Client.ts";
|
|
12
12
|
import { BaseLogger, getOrCreateBaseLogger } from "./internal/logging.ts";
|
|
13
|
-
import * as
|
|
13
|
+
import * as RivetLogger from "./RivetLogger.ts";
|
|
14
14
|
|
|
15
15
|
const TypeId = "~@rivetkit/effect/Registry";
|
|
16
16
|
type ServerlessOptions = NonNullable<
|
|
@@ -19,7 +19,7 @@ type ServerlessOptions = NonNullable<
|
|
|
19
19
|
|
|
20
20
|
export type Options = Pick<
|
|
21
21
|
Rivetkit.RegistryConfigInput<Rivetkit.RegistryActors>,
|
|
22
|
-
"endpoint" | "token" | "namespace" | "noWelcome"
|
|
22
|
+
"endpoint" | "token" | "namespace" | "noWelcome" | "sqlite"
|
|
23
23
|
>;
|
|
24
24
|
|
|
25
25
|
export interface Registry {
|
|
@@ -27,7 +27,7 @@ export interface Registry {
|
|
|
27
27
|
|
|
28
28
|
readonly options: Options;
|
|
29
29
|
|
|
30
|
-
readonly baseLogger:
|
|
30
|
+
readonly baseLogger: RivetkitLog.Logger;
|
|
31
31
|
|
|
32
32
|
readonly rivetkitActors: Map<string, Rivetkit.AnyActorDefinition>;
|
|
33
33
|
}
|
|
@@ -35,20 +35,49 @@ export interface Registry {
|
|
|
35
35
|
export const Registry: Context.Service<Registry, Registry> =
|
|
36
36
|
Context.Service<Registry>("@rivetkit/effect/Registry");
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Creates the shared registry that actor layers register into.
|
|
40
|
+
*
|
|
41
|
+
* @remarks
|
|
42
|
+
* Actor layers created with {@link Actor.Actor.toLayer|`Actor.toLayer()`}
|
|
43
|
+
* register into this service. Registry entrypoints such as
|
|
44
|
+
* {@link serve|`Registry.serve()`}, {@link toWebHandler|`Registry.toWebHandler()`},
|
|
45
|
+
* and {@link toHttpEffect|`Registry.toHttpEffect()`} later use the collected
|
|
46
|
+
* actors to create the underlying RivetKit runtime.
|
|
47
|
+
*
|
|
48
|
+
* @param options - RivetKit runtime options shared by the registered actors.
|
|
49
|
+
*
|
|
50
|
+
* @returns A layer that provides the {@link Registry|`Registry.Registry`}
|
|
51
|
+
* service.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* import { Registry } from "@rivetkit/effect"
|
|
56
|
+
* import { Layer } from "effect"
|
|
57
|
+
*
|
|
58
|
+
* const ActorsLayer = Layer.mergeAll(ChatRoomLive, ModeratorLive)
|
|
59
|
+
*
|
|
60
|
+
* const MainLayer = Registry.serve(ActorsLayer).pipe(
|
|
61
|
+
* Layer.provide(Registry.layer({ endpoint: "http://127.0.0.1:6420" }))
|
|
62
|
+
* )
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* @see {@link serve|`Registry.serve()`} for starting a long-running actor
|
|
66
|
+
* server.
|
|
67
|
+
* @see {@link toWebHandler|`Registry.toWebHandler()`} for Fetch-compatible
|
|
68
|
+
* serverless handlers.
|
|
69
|
+
* @see {@link toHttpEffect|`Registry.toHttpEffect()`} for Effect HTTP handlers.
|
|
70
|
+
*/
|
|
47
71
|
export const layer = (options: Options = {}): Layer.Layer<Registry> =>
|
|
48
72
|
Layer.effect(
|
|
49
73
|
Registry,
|
|
50
74
|
Effect.map(getOrCreateBaseLogger, (baseLogger) =>
|
|
51
|
-
|
|
75
|
+
Registry.of({
|
|
76
|
+
[TypeId]: TypeId,
|
|
77
|
+
options,
|
|
78
|
+
baseLogger,
|
|
79
|
+
rivetkitActors: new Map(),
|
|
80
|
+
}),
|
|
52
81
|
),
|
|
53
82
|
);
|
|
54
83
|
|
|
@@ -57,24 +86,53 @@ const setupRivetkitRegistry = (
|
|
|
57
86
|
options?: {
|
|
58
87
|
readonly serverless?: ServerlessOptions | undefined;
|
|
59
88
|
},
|
|
60
|
-
) =>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
89
|
+
) =>
|
|
90
|
+
Effect.sync(() =>
|
|
91
|
+
Rivetkit.setup({
|
|
92
|
+
use: Object.fromEntries(registry.rivetkitActors),
|
|
93
|
+
...registry.options,
|
|
94
|
+
logging: { baseLogger: registry.baseLogger },
|
|
95
|
+
...(options?.serverless === undefined
|
|
96
|
+
? {}
|
|
97
|
+
: { serverless: options.serverless }),
|
|
98
|
+
}),
|
|
99
|
+
);
|
|
71
100
|
|
|
72
101
|
/**
|
|
73
|
-
*
|
|
102
|
+
* Serves the actors registered by `actorsLayer`.
|
|
103
|
+
*
|
|
104
|
+
* @remarks
|
|
105
|
+
* Provide this with {@link layer|`Registry.layer()`} at the application root.
|
|
106
|
+
* Building the returned layer evaluates the actor layer, collects its registered
|
|
107
|
+
* actors, and starts the underlying RivetKit runtime using the options from
|
|
108
|
+
* {@link layer|`Registry.layer()`}. Launch the resulting layer with
|
|
109
|
+
* {@link Layer.launch|`Layer.launch()`} to keep the server process alive.
|
|
110
|
+
*
|
|
111
|
+
* @param actorsLayer - A layer containing one or more
|
|
112
|
+
* {@link Actor.Actor.toLayer|`Actor.toLayer()`} registrations.
|
|
113
|
+
*
|
|
114
|
+
* @returns A side-effecting startup layer that requires the
|
|
115
|
+
* {@link Registry|`Registry.Registry`} service and the services required by
|
|
116
|
+
* `actorsLayer`.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* import { Registry } from "@rivetkit/effect"
|
|
121
|
+
* import { Layer } from "effect"
|
|
122
|
+
*
|
|
123
|
+
* const ActorsLayer = Layer.mergeAll(ChatRoomLive, ModeratorLive)
|
|
124
|
+
*
|
|
125
|
+
* const MainLayer = Registry.serve(ActorsLayer).pipe(
|
|
126
|
+
* Layer.provide(Registry.layer({ endpoint: "http://127.0.0.1:6420" }))
|
|
127
|
+
* )
|
|
128
|
+
*
|
|
129
|
+
* Layer.launch(MainLayer).pipe(NodeRuntime.runMain);
|
|
130
|
+
* ```
|
|
131
|
+
*
|
|
132
|
+
* @see {@link toWebHandler|`Registry.toWebHandler()`} for Fetch-compatible
|
|
133
|
+
* serverless handlers.
|
|
134
|
+
* @see {@link toHttpEffect|`Registry.toHttpEffect()`} for Effect HTTP handlers.
|
|
74
135
|
*
|
|
75
|
-
* The actor layer is built in the server layer scope. Registered Rivet Actors
|
|
76
|
-
* are collected from `Registry`, materialized into a single underlying RivetKit
|
|
77
|
-
* registry, and started.
|
|
78
136
|
*/
|
|
79
137
|
export const serve = <E, R>(
|
|
80
138
|
actorsLayer: Layer.Layer<never, E, R>,
|
|
@@ -82,13 +140,14 @@ export const serve = <E, R>(
|
|
|
82
140
|
Layer.effectDiscard(
|
|
83
141
|
Effect.gen(function* () {
|
|
84
142
|
const registry = yield* Registry;
|
|
85
|
-
const baseLogger = registry.baseLogger;
|
|
86
143
|
yield* Layer.build(
|
|
87
144
|
actorsLayer.pipe(
|
|
88
|
-
Layer.provideMerge(
|
|
145
|
+
Layer.provideMerge(
|
|
146
|
+
RivetLogger.layerFromPino(registry.baseLogger),
|
|
147
|
+
),
|
|
89
148
|
),
|
|
90
149
|
);
|
|
91
|
-
const rivetkitRegistry = setupRivetkitRegistry(registry);
|
|
150
|
+
const rivetkitRegistry = yield* setupRivetkitRegistry(registry);
|
|
92
151
|
yield* Effect.sync(() => rivetkitRegistry.start());
|
|
93
152
|
}),
|
|
94
153
|
);
|
|
@@ -107,7 +166,7 @@ export const test: Layer.Layer<Client.Client, never, Registry> = Layer.effect(
|
|
|
107
166
|
Client.Client,
|
|
108
167
|
Effect.gen(function* () {
|
|
109
168
|
const registry = yield* Registry;
|
|
110
|
-
const rivetkitRegistry = setupRivetkitRegistry(registry);
|
|
169
|
+
const rivetkitRegistry = yield* setupRivetkitRegistry(registry);
|
|
111
170
|
rivetkitRegistry.config.test = {
|
|
112
171
|
...rivetkitRegistry.config.test,
|
|
113
172
|
enabled: true,
|
|
@@ -145,17 +204,21 @@ const makeHttpEffect = (
|
|
|
145
204
|
registry: Registry,
|
|
146
205
|
options?: ToHttpEffectOptions,
|
|
147
206
|
): Effect.Effect<
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
207
|
+
Effect.Effect<
|
|
208
|
+
HttpServerResponse.HttpServerResponse,
|
|
209
|
+
HttpServerError.HttpServerError,
|
|
210
|
+
HttpServerRequest.HttpServerRequest
|
|
211
|
+
>
|
|
212
|
+
> =>
|
|
213
|
+
Effect.map(
|
|
214
|
+
setupRivetkitRegistry(registry, {
|
|
215
|
+
serverless: options,
|
|
216
|
+
}),
|
|
217
|
+
(rivetkitRegistry) =>
|
|
218
|
+
HttpEffect.fromWebHandler((request) =>
|
|
219
|
+
rivetkitRegistry.handler(request),
|
|
220
|
+
),
|
|
157
221
|
);
|
|
158
|
-
};
|
|
159
222
|
|
|
160
223
|
export type ToHttpEffectOptions = ServerlessOptions;
|
|
161
224
|
|
|
@@ -179,12 +242,14 @@ export const toHttpEffect = Effect.fnUntraced(function* <E>(
|
|
|
179
242
|
Scope.Scope
|
|
180
243
|
> {
|
|
181
244
|
const context = yield* Layer.build(
|
|
182
|
-
registryLayer.pipe(Layer.provideMerge(
|
|
245
|
+
registryLayer.pipe(Layer.provideMerge(RivetLogger.defaultLayer)),
|
|
183
246
|
);
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
247
|
+
const httpEffect = yield* makeHttpEffect(
|
|
248
|
+
Context.get(context, Registry),
|
|
249
|
+
options,
|
|
187
250
|
);
|
|
251
|
+
// @effect-diagnostics-next-line returnEffectInGen:off
|
|
252
|
+
return httpEffect.pipe(Effect.provide(context));
|
|
188
253
|
});
|
|
189
254
|
|
|
190
255
|
export type ToWebHandlerOptions = ServerlessOptions & {
|
|
@@ -221,16 +286,17 @@ export const toWebHandler = <E>(
|
|
|
221
286
|
}
|
|
222
287
|
|
|
223
288
|
const registryLayerWithLogging = registryLayer.pipe(
|
|
224
|
-
Layer.provideMerge(
|
|
289
|
+
Layer.provideMerge(RivetLogger.defaultLayer),
|
|
225
290
|
);
|
|
226
291
|
|
|
227
292
|
return HttpEffect.toWebHandlerLayerWith(registryLayerWithLogging, {
|
|
228
293
|
toHandler: (context) =>
|
|
229
|
-
Effect.
|
|
294
|
+
Effect.map(
|
|
230
295
|
makeHttpEffect(
|
|
231
296
|
Context.get(context, Registry),
|
|
232
297
|
serverlessOptions,
|
|
233
|
-
)
|
|
298
|
+
),
|
|
299
|
+
(httpEffect) => httpEffect.pipe(Effect.provide(context)),
|
|
234
300
|
),
|
|
235
301
|
middleware,
|
|
236
302
|
memoMap,
|
package/src/RivetError.test.ts
CHANGED
|
@@ -121,6 +121,13 @@ describe("RivetError", () => {
|
|
|
121
121
|
"actor ready timeout",
|
|
122
122
|
),
|
|
123
123
|
);
|
|
124
|
+
const wakeRetriesExceeded = RivetError.fromUnknown(
|
|
125
|
+
new RivetkitErrors.RivetError(
|
|
126
|
+
"guard",
|
|
127
|
+
"actor_wake_retries_exceeded",
|
|
128
|
+
"actor wake retries exceeded",
|
|
129
|
+
),
|
|
130
|
+
);
|
|
124
131
|
const tunnelTimeout = RivetError.fromUnknown(
|
|
125
132
|
new RivetkitErrors.RivetError(
|
|
126
133
|
"guard",
|
|
@@ -137,6 +144,10 @@ describe("RivetError", () => {
|
|
|
137
144
|
readyTimeout.reason,
|
|
138
145
|
RivetError.GuardActorReadyTimeout,
|
|
139
146
|
);
|
|
147
|
+
assert.instanceOf(
|
|
148
|
+
wakeRetriesExceeded.reason,
|
|
149
|
+
RivetError.GuardActorWakeRetriesExceeded,
|
|
150
|
+
);
|
|
140
151
|
assert.instanceOf(
|
|
141
152
|
tunnelTimeout.reason,
|
|
142
153
|
RivetError.GuardTunnelMessageTimeout,
|
package/src/RivetError.ts
CHANGED
|
@@ -426,6 +426,38 @@ export class GuardActorReadyTimeout extends Schema.TaggedErrorClass<GuardActorRe
|
|
|
426
426
|
}
|
|
427
427
|
}
|
|
428
428
|
|
|
429
|
+
export class GuardActorWakeRetriesExceeded extends Schema.TaggedErrorClass<GuardActorWakeRetriesExceeded>(
|
|
430
|
+
`${ReasonTypeId}/GuardActorWakeRetriesExceeded`,
|
|
431
|
+
)("GuardActorWakeRetriesExceeded", {
|
|
432
|
+
cause: Schema.instanceOf(RivetkitErrors.RivetError),
|
|
433
|
+
}) {
|
|
434
|
+
readonly [ReasonTypeId] = ReasonTypeId;
|
|
435
|
+
override get message() {
|
|
436
|
+
return this.cause.message;
|
|
437
|
+
}
|
|
438
|
+
get group() {
|
|
439
|
+
return this.cause.group;
|
|
440
|
+
}
|
|
441
|
+
get code() {
|
|
442
|
+
return this.cause.code;
|
|
443
|
+
}
|
|
444
|
+
get metadata() {
|
|
445
|
+
return this.cause.metadata;
|
|
446
|
+
}
|
|
447
|
+
get actor() {
|
|
448
|
+
return this.cause.actor;
|
|
449
|
+
}
|
|
450
|
+
get statusCode() {
|
|
451
|
+
return this.cause.statusCode;
|
|
452
|
+
}
|
|
453
|
+
get public() {
|
|
454
|
+
return this.cause.public;
|
|
455
|
+
}
|
|
456
|
+
get isRetryable(): boolean {
|
|
457
|
+
return true;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
429
461
|
export class GuardActorRunnerFailed extends Schema.TaggedErrorClass<GuardActorRunnerFailed>(
|
|
430
462
|
`${ReasonTypeId}/GuardActorRunnerFailed`,
|
|
431
463
|
)("GuardActorRunnerFailed", {
|
|
@@ -816,6 +848,7 @@ export type RivetErrorReason =
|
|
|
816
848
|
| InvalidEncoding
|
|
817
849
|
| InvalidRequest
|
|
818
850
|
| GuardActorReadyTimeout
|
|
851
|
+
| GuardActorWakeRetriesExceeded
|
|
819
852
|
| GuardActorRunnerFailed
|
|
820
853
|
| GuardServiceUnavailable
|
|
821
854
|
| GuardActorStoppedWhileWaiting
|
|
@@ -843,6 +876,7 @@ export const RivetErrorReason: Schema.Union<
|
|
|
843
876
|
typeof InvalidEncoding,
|
|
844
877
|
typeof InvalidRequest,
|
|
845
878
|
typeof GuardActorReadyTimeout,
|
|
879
|
+
typeof GuardActorWakeRetriesExceeded,
|
|
846
880
|
typeof GuardActorRunnerFailed,
|
|
847
881
|
typeof GuardServiceUnavailable,
|
|
848
882
|
typeof GuardActorStoppedWhileWaiting,
|
|
@@ -869,6 +903,7 @@ export const RivetErrorReason: Schema.Union<
|
|
|
869
903
|
InvalidEncoding,
|
|
870
904
|
InvalidRequest,
|
|
871
905
|
GuardActorReadyTimeout,
|
|
906
|
+
GuardActorWakeRetriesExceeded,
|
|
872
907
|
GuardActorRunnerFailed,
|
|
873
908
|
GuardServiceUnavailable,
|
|
874
909
|
GuardActorStoppedWhileWaiting,
|
|
@@ -993,6 +1028,8 @@ const reasonByCode: { [key: string]: MakeRivetErrorReason | undefined } = {
|
|
|
993
1028
|
"request.invalid": (error) => new InvalidRequest({ cause: error }),
|
|
994
1029
|
"guard.actor_ready_timeout": (error) =>
|
|
995
1030
|
new GuardActorReadyTimeout({ cause: error }),
|
|
1031
|
+
"guard.actor_wake_retries_exceeded": (error) =>
|
|
1032
|
+
new GuardActorWakeRetriesExceeded({ cause: error }),
|
|
996
1033
|
"guard.actor_runner_failed": (error) =>
|
|
997
1034
|
new GuardActorRunnerFailed({ cause: error }),
|
|
998
1035
|
"guard.service_unavailable": (error) =>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Effect, Logger, Layer } from "effect";
|
|
2
|
+
import * as RivetkitLog from "rivetkit/log";
|
|
3
|
+
import {
|
|
4
|
+
BaseLogger,
|
|
5
|
+
getOrCreateBaseLogger,
|
|
6
|
+
makeLogger,
|
|
7
|
+
} from "./internal/logging.ts";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Builds an Effect logger from a custom Pino-compatible logger.
|
|
11
|
+
*
|
|
12
|
+
* Use this with Effect's `Logger.layer` when you only need to customize Effect
|
|
13
|
+
* log output. Use {@link layerFromPino} when RivetKit's underlying TypeScript SDK
|
|
14
|
+
* logs should use the same logger too.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { Logger } from "effect"
|
|
19
|
+
* import { RivetLogger } from "@rivetkit/effect"
|
|
20
|
+
* import { pino } from "pino"
|
|
21
|
+
*
|
|
22
|
+
* const baseLogger = pino({ transport: { target: "pino-pretty" } })
|
|
23
|
+
* const LoggerLive = Logger.layer([RivetLogger.fromPino(baseLogger)])
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export const fromPino = (
|
|
27
|
+
baseLogger: RivetkitLog.Logger,
|
|
28
|
+
): Logger.Logger<unknown, void> => makeLogger(baseLogger);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Builds a logging layer from a custom Pino-compatible logger.
|
|
32
|
+
*
|
|
33
|
+
* The layer installs the matching Effect logger and configures the underlying
|
|
34
|
+
* RivetKit TypeScript SDK logs to go through the same logger. The Effect tracer
|
|
35
|
+
* logger is installed alongside the Pino adapter so log events remain attached
|
|
36
|
+
* to active traces.
|
|
37
|
+
*/
|
|
38
|
+
export const layerFromPino = (
|
|
39
|
+
baseLogger: RivetkitLog.Logger,
|
|
40
|
+
options?: {
|
|
41
|
+
readonly mergeWithExisting?: boolean | undefined;
|
|
42
|
+
},
|
|
43
|
+
): Layer.Layer<BaseLogger> =>
|
|
44
|
+
Layer.mergeAll(
|
|
45
|
+
Layer.succeed(BaseLogger, baseLogger),
|
|
46
|
+
Logger.layer([Logger.tracerLogger, fromPino(baseLogger)], {
|
|
47
|
+
mergeWithExisting: options?.mergeWithExisting,
|
|
48
|
+
}),
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Default RivetKit Effect logging layer.
|
|
53
|
+
*
|
|
54
|
+
* The layer creates a base logger from RivetKit log configuration and installs
|
|
55
|
+
* the Effect logger adapter. Applications that want custom formatting or
|
|
56
|
+
* transports should provide {@link layerFromPino} instead.
|
|
57
|
+
*/
|
|
58
|
+
export const defaultLayer: Layer.Layer<never> = Layer.unwrap(
|
|
59
|
+
Effect.map(getOrCreateBaseLogger, layerFromPino),
|
|
60
|
+
);
|