@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.
Files changed (63) hide show
  1. package/dist/Actor.d.ts +2 -3
  2. package/dist/Actor.d.ts.map +1 -1
  3. package/dist/Actor.js +2 -2
  4. package/dist/Actor.js.map +1 -1
  5. package/dist/Client.d.ts.map +1 -1
  6. package/dist/Client.js +6 -4
  7. package/dist/Client.js.map +1 -1
  8. package/dist/Registry.d.ts +69 -7
  9. package/dist/Registry.d.ts.map +1 -1
  10. package/dist/Registry.js +93 -40
  11. package/dist/Registry.js.map +1 -1
  12. package/dist/RivetError.d.ts +18 -3
  13. package/dist/RivetError.d.ts.map +1 -1
  14. package/dist/RivetError.js +31 -0
  15. package/dist/RivetError.js.map +1 -1
  16. package/dist/RivetLogger.d.ts +41 -0
  17. package/dist/RivetLogger.d.ts.map +1 -0
  18. package/dist/RivetLogger.js +41 -0
  19. package/dist/RivetLogger.js.map +1 -0
  20. package/dist/State.d.ts +92 -56
  21. package/dist/State.d.ts.map +1 -1
  22. package/dist/State.js +51 -57
  23. package/dist/State.js.map +1 -1
  24. package/dist/internal/ActorInstanceManager.d.ts.map +1 -1
  25. package/dist/internal/ActorInstanceManager.js +4 -4
  26. package/dist/internal/ActorInstanceManager.js.map +1 -1
  27. package/dist/internal/ActorStateAdapter.d.ts +1 -1
  28. package/dist/internal/ActorStateAdapter.d.ts.map +1 -1
  29. package/dist/internal/ActorStateAdapter.js +2 -7
  30. package/dist/internal/ActorStateAdapter.js.map +1 -1
  31. package/dist/internal/StateOptions.d.ts +1 -0
  32. package/dist/internal/StateOptions.d.ts.map +1 -1
  33. package/dist/internal/logging.d.ts +6 -7
  34. package/dist/internal/logging.d.ts.map +1 -1
  35. package/dist/internal/logging.js +78 -102
  36. package/dist/internal/logging.js.map +1 -1
  37. package/dist/mod.d.ts +1 -1
  38. package/dist/mod.d.ts.map +1 -1
  39. package/dist/mod.js +1 -1
  40. package/dist/mod.js.map +1 -1
  41. package/package.json +3 -3
  42. package/src/Actor.test-d.ts +32 -0
  43. package/src/Actor.ts +29 -4
  44. package/src/Client.test.ts +21 -18
  45. package/src/Client.ts +6 -4
  46. package/src/Registry.test.ts +7 -11
  47. package/src/Registry.ts +116 -50
  48. package/src/RivetError.test.ts +11 -0
  49. package/src/RivetError.ts +37 -0
  50. package/src/RivetLogger.ts +60 -0
  51. package/src/State.test.ts +163 -4
  52. package/src/State.ts +293 -97
  53. package/src/internal/ActorInstanceManager.ts +4 -10
  54. package/src/internal/ActorStateAdapter.ts +5 -11
  55. package/src/internal/StateOptions.ts +4 -0
  56. package/src/internal/logging.test.ts +65 -88
  57. package/src/internal/logging.ts +103 -143
  58. package/src/mod.ts +1 -1
  59. package/dist/Logger.d.ts +0 -29
  60. package/dist/Logger.d.ts.map +0 -1
  61. package/dist/Logger.js +0 -31
  62. package/dist/Logger.js.map +0 -1
  63. package/src/Logger.ts +0 -43
@@ -1,12 +1,8 @@
1
1
  import { assert, describe, it } from "@effect/vitest";
2
- import { Client, Logger, RivetError } from "@rivetkit/effect";
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
- ): PinoLogger {
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 PinoLogger;
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(() => configureDefaultLogger("silent")),
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(Logger.layerPino(baseLogger)));
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(() => configureDefaultLogger("silent")),
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(Logger.layerPino(baseLogger)),
76
+ Layer.provideMerge(
77
+ RivetLogger.layerFromPino(baseLogger),
78
+ ),
77
79
  ),
78
80
  ),
79
81
  );
80
82
 
81
- assert.deepStrictEqual(entries[0], {
82
- level: "info",
83
- fields: { clientId: "test-client" },
84
- msg: "client effect log",
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 { configureBaseLogger } from "rivetkit/log";
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 Logger from "./Logger.ts";
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
- configureBaseLogger(baseLogger);
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(Logger.layerPino(baseLogger)),
151
+ Layer.provideMerge(RivetLogger.layerFromPino(baseLogger)),
150
152
  ),
151
153
  ),
152
154
  );
@@ -1,12 +1,8 @@
1
1
  import { assert, describe, it } from "@effect/vitest";
2
- import { Action, Actor, Logger, Registry } from "@rivetkit/effect";
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(): PinoLogger {
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 PinoLogger;
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(Logger.layerPino(baseLogger)),
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 { configureBaseLogger, type Logger as PinoLogger } from "rivetkit/log";
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 Logger from "./Logger.ts";
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: PinoLogger;
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
- const make = (options: Options, baseLogger: PinoLogger): Registry => {
39
- return Registry.of({
40
- [TypeId]: TypeId,
41
- options,
42
- baseLogger,
43
- rivetkitActors: new Map(),
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
- make(options, baseLogger),
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
- configureBaseLogger(registry.baseLogger);
62
- return Rivetkit.setup({
63
- use: Object.fromEntries(registry.rivetkitActors),
64
- ...registry.options,
65
- logging: { baseLogger: registry.baseLogger },
66
- ...(options?.serverless === undefined
67
- ? {}
68
- : { serverless: options.serverless }),
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
- * Runs an actor registration layer against the configured engine.
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(Logger.layerPino(baseLogger)),
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
- HttpServerResponse.HttpServerResponse,
149
- HttpServerError.HttpServerError,
150
- HttpServerRequest.HttpServerRequest
151
- > => {
152
- const rivetkitRegistry = setupRivetkitRegistry(registry, {
153
- serverless: options,
154
- });
155
- return HttpEffect.fromWebHandler((request) =>
156
- rivetkitRegistry.handler(request),
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(Logger.layer)),
245
+ registryLayer.pipe(Layer.provideMerge(RivetLogger.defaultLayer)),
183
246
  );
184
- // @effect-diagnostics-next-line returnEffectInGen:off
185
- return makeHttpEffect(Context.get(context, Registry), options).pipe(
186
- Effect.provide(context),
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(Logger.layer),
289
+ Layer.provideMerge(RivetLogger.defaultLayer),
225
290
  );
226
291
 
227
292
  return HttpEffect.toWebHandlerLayerWith(registryLayerWithLogging, {
228
293
  toHandler: (context) =>
229
- Effect.succeed(
294
+ Effect.map(
230
295
  makeHttpEffect(
231
296
  Context.get(context, Registry),
232
297
  serverlessOptions,
233
- ).pipe(Effect.provide(context)),
298
+ ),
299
+ (httpEffect) => httpEffect.pipe(Effect.provide(context)),
234
300
  ),
235
301
  middleware,
236
302
  memoMap,
@@ -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
+ );