@gaganref/confect-server 10.3.1-fork.38 → 10.3.1-fork.39
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/ConvexFunctionDefinitions.d.ts.map +1 -1
- package/dist/ConvexFunctionDefinitions.js +2 -2
- package/dist/ConvexFunctionDefinitions.js.map +1 -1
- package/dist/GroupRegistry.d.ts +1 -0
- package/dist/GroupRegistry.d.ts.map +1 -1
- package/dist/GroupRegistry.js +10 -3
- package/dist/GroupRegistry.js.map +1 -1
- package/dist/QueryStreamReadBudget.js +1 -1
- package/dist/RegisteredConvexFunction.d.ts +7 -4
- package/dist/RegisteredConvexFunction.d.ts.map +1 -1
- package/dist/RegisteredConvexFunction.js +27 -14
- package/dist/RegisteredConvexFunction.js.map +1 -1
- package/dist/RegisteredFunction.d.ts +9 -2
- package/dist/RegisteredFunction.d.ts.map +1 -1
- package/dist/RegisteredFunction.js +37 -13
- package/dist/RegisteredFunction.js.map +1 -1
- package/dist/RegisteredNodeFunction.d.ts +1 -1
- package/dist/RegisteredNodeFunction.d.ts.map +1 -1
- package/dist/RegisteredNodeFunction.js +7 -5
- package/dist/RegisteredNodeFunction.js.map +1 -1
- package/dist/index.js +9 -9
- package/dist/internal/observability.d.ts +5 -0
- package/dist/internal/observability.d.ts.map +1 -0
- package/dist/internal/observability.js +21 -0
- package/dist/internal/observability.js.map +1 -0
- package/package.json +2 -2
- package/src/ConvexFunctionDefinitions.ts +2 -1
- package/src/GroupRegistry.ts +7 -3
- package/src/RegisteredConvexFunction.ts +16 -0
- package/src/RegisteredFunction.ts +70 -7
- package/src/RegisteredNodeFunction.ts +7 -1
- package/src/internal/observability.ts +27 -0
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
type DefaultFunctionArgs,
|
|
13
13
|
type FunctionVisibility,
|
|
14
|
+
type FunctionMetadata,
|
|
14
15
|
type GenericActionCtx,
|
|
15
16
|
type GenericDataModel,
|
|
16
17
|
type StorageReader as ConvexStorageReader,
|
|
@@ -21,8 +22,10 @@ import {
|
|
|
21
22
|
import type { Value } from "convex/values";
|
|
22
23
|
import { ConvexError } from "convex/values";
|
|
23
24
|
import { pipe } from "effect/Function";
|
|
25
|
+
import * as Clock from "effect/Clock";
|
|
24
26
|
import * as Cause from "effect/Cause";
|
|
25
27
|
import * as Console from "effect/Console";
|
|
28
|
+
import * as Context from "effect/Context";
|
|
26
29
|
import * as Effect from "effect/Effect";
|
|
27
30
|
import * as Exit from "effect/Exit";
|
|
28
31
|
import * as Result from "effect/Result";
|
|
@@ -45,9 +48,16 @@ import * as Storage from "./Storage.js";
|
|
|
45
48
|
import * as StorageActionWriter from "./StorageActionWriter.js";
|
|
46
49
|
import type * as StorageReader from "./StorageReader.js";
|
|
47
50
|
import * as StorageWriter from "./StorageWriter.js";
|
|
51
|
+
import * as Tracer from "effect/Tracer";
|
|
52
|
+
import * as ObservabilityRuntime from "./internal/observability.js";
|
|
48
53
|
import * as VectorSearch from "./VectorSearch.js";
|
|
49
54
|
import type * as Handler from "./Handler.js";
|
|
50
55
|
|
|
56
|
+
export const Observability = Context.Reference<Layer.Layer<never> | undefined>(
|
|
57
|
+
"@confect/server/Observability",
|
|
58
|
+
{ defaultValue: () => undefined },
|
|
59
|
+
);
|
|
60
|
+
|
|
51
61
|
export type Any =
|
|
52
62
|
| RegisteredQuery<FunctionVisibility, DefaultFunctionArgs, any>
|
|
53
63
|
| RegisteredMutation<FunctionVisibility, DefaultFunctionArgs, any>
|
|
@@ -215,21 +225,58 @@ export const runHandlerPromise =
|
|
|
215
225
|
errorSchema: Schema.Codec<any, any> | undefined,
|
|
216
226
|
runOptions?: {
|
|
217
227
|
readonly scheduler?: EffectScheduler.Scheduler | undefined;
|
|
228
|
+
readonly clock?: Clock.Clock | undefined;
|
|
229
|
+
readonly invocation?: Effect.Effect<FunctionMetadata> | undefined;
|
|
230
|
+
readonly observability?: Layer.Layer<never> | undefined;
|
|
218
231
|
},
|
|
219
232
|
) =>
|
|
220
233
|
<A, E>(effect: Effect.Effect<A, E>): Promise<A> => {
|
|
234
|
+
const { observability, invocation, clock } = runOptions ?? {};
|
|
235
|
+
let encodedError: Exit.Exit<any, any> | undefined;
|
|
236
|
+
const observed = Effect.tapCause(effect, (cause) =>
|
|
237
|
+
Effect.gen(function* () {
|
|
238
|
+
const reason =
|
|
239
|
+
cause.reasons.find(Cause.isDieReason) ??
|
|
240
|
+
cause.reasons.find(Cause.isFailReason);
|
|
241
|
+
if (reason?._tag === "Fail" && errorSchema !== undefined) {
|
|
242
|
+
encodedError = yield* Effect.exit(
|
|
243
|
+
Schema.encodeEffect(errorSchema)(reason.error),
|
|
244
|
+
);
|
|
245
|
+
if (Exit.isFailure(encodedError))
|
|
246
|
+
return yield* Effect.orDie(encodedError);
|
|
247
|
+
}
|
|
248
|
+
}),
|
|
249
|
+
);
|
|
221
250
|
const withConvexError: Effect.Effect<Result.Result<A, ConvexError<any>>> =
|
|
222
251
|
Effect.gen(function* () {
|
|
223
|
-
const exit = yield* Effect.exit(
|
|
252
|
+
const exit = yield* Effect.exit(
|
|
253
|
+
observability === undefined || invocation === undefined
|
|
254
|
+
? effect
|
|
255
|
+
: Effect.flatMap(invocation, ({ name, type, componentPath }) =>
|
|
256
|
+
Effect.useSpan(
|
|
257
|
+
name,
|
|
258
|
+
{
|
|
259
|
+
root: true,
|
|
260
|
+
attributes: { kind: type, componentPath },
|
|
261
|
+
},
|
|
262
|
+
(span) =>
|
|
263
|
+
Effect.provideService(observed, Tracer.ParentSpan, span),
|
|
264
|
+
),
|
|
265
|
+
),
|
|
266
|
+
);
|
|
224
267
|
if (Exit.isSuccess(exit)) {
|
|
225
268
|
return Result.succeed(exit.value);
|
|
226
269
|
}
|
|
227
270
|
|
|
228
|
-
const
|
|
271
|
+
const cause =
|
|
272
|
+
encodedError !== undefined && Exit.isFailure(encodedError)
|
|
273
|
+
? encodedError.cause
|
|
274
|
+
: exit.cause;
|
|
229
275
|
const reason =
|
|
230
276
|
cause.reasons.find(Cause.isDieReason) ??
|
|
231
277
|
cause.reasons.find(Cause.isFailReason);
|
|
232
278
|
if (
|
|
279
|
+
encodedError === undefined &&
|
|
233
280
|
reason?._tag === "Die" &&
|
|
234
281
|
cause.reasons.length === 1 &&
|
|
235
282
|
reason.defect instanceof ConvexError
|
|
@@ -244,9 +291,11 @@ export const runHandlerPromise =
|
|
|
244
291
|
}
|
|
245
292
|
return yield* Effect.die(reason.error);
|
|
246
293
|
}
|
|
247
|
-
const encoded =
|
|
248
|
-
|
|
249
|
-
|
|
294
|
+
const encoded =
|
|
295
|
+
encodedError ??
|
|
296
|
+
(yield* Effect.exit(
|
|
297
|
+
Schema.encodeEffect(errorSchema)(reason.error),
|
|
298
|
+
));
|
|
250
299
|
if (Exit.isSuccess(encoded)) {
|
|
251
300
|
return Result.fail(new ConvexError(encoded.value));
|
|
252
301
|
}
|
|
@@ -258,8 +307,15 @@ export const runHandlerPromise =
|
|
|
258
307
|
});
|
|
259
308
|
return Effect.runPromise(
|
|
260
309
|
withConvexError.pipe(
|
|
261
|
-
Effect.provide(
|
|
310
|
+
Effect.provide(
|
|
311
|
+
observability === undefined
|
|
312
|
+
? ConvexLogger.layer
|
|
313
|
+
: ObservabilityRuntime.memoized(observability),
|
|
314
|
+
),
|
|
262
315
|
Effect.provideService(Console.Console, globalThis.console),
|
|
316
|
+
clock === undefined
|
|
317
|
+
? (self) => self
|
|
318
|
+
: Effect.provideService(Clock.Clock, clock),
|
|
263
319
|
),
|
|
264
320
|
runOptions,
|
|
265
321
|
).then(
|
|
@@ -290,6 +346,7 @@ export const actionFunctionBase = <
|
|
|
290
346
|
resolvedMiddlewares = [],
|
|
291
347
|
createLayer,
|
|
292
348
|
scope = IdScope.app,
|
|
349
|
+
observability,
|
|
293
350
|
}: {
|
|
294
351
|
name: string;
|
|
295
352
|
functionVisibility: FunctionVisibility;
|
|
@@ -302,6 +359,7 @@ export const actionFunctionBase = <
|
|
|
302
359
|
ctx: GenericActionCtx<DataModel.ToConvex<DataModel.FromSchema<Schema>>>,
|
|
303
360
|
) => Layer.Layer<R>;
|
|
304
361
|
scope?: IdScope.IdScope;
|
|
362
|
+
observability?: Layer.Layer<never> | undefined;
|
|
305
363
|
}) => ({
|
|
306
364
|
args: compileArgsSchema(args, scope),
|
|
307
365
|
returns: compileReturnsSchema(returns, scope),
|
|
@@ -338,7 +396,12 @@ export const actionFunctionBase = <
|
|
|
338
396
|
Schema.encodeEffect(returns),
|
|
339
397
|
Effect.catchTag("SchemaError", Effect.die),
|
|
340
398
|
);
|
|
341
|
-
}).pipe(
|
|
399
|
+
}).pipe(
|
|
400
|
+
runHandlerPromise(combineErrorSchemas(error, resolvedMiddlewares), {
|
|
401
|
+
invocation: Effect.promise(() => ctx.meta.getFunctionMetadata()),
|
|
402
|
+
observability,
|
|
403
|
+
}),
|
|
404
|
+
),
|
|
342
405
|
});
|
|
343
406
|
|
|
344
407
|
export type ActionServices<
|
|
@@ -23,7 +23,7 @@ export const buildForGroup = <Group extends GroupSpec.AnyWithProps>(
|
|
|
23
23
|
databaseSchema: DatabaseSchema.AnyWithProps,
|
|
24
24
|
groupLayer: Layer.Layer<GroupImpl.GroupImpl<"Finalized">>,
|
|
25
25
|
): RegisteredFunctions.RegisteredFunctionsForGroupSpec<Group> => {
|
|
26
|
-
const { functionRegistryItems, middlewareRegistryItems } =
|
|
26
|
+
const { functionRegistryItems, middlewareRegistryItems, observability } =
|
|
27
27
|
GroupRegistry.make(groupLayer);
|
|
28
28
|
return mapLeaves<FunctionRegistryItem.AnyWithProps, RegisteredFunction.Any>(
|
|
29
29
|
functionRegistryItems as {
|
|
@@ -38,6 +38,7 @@ export const buildForGroup = <Group extends GroupSpec.AnyWithProps>(
|
|
|
38
38
|
databaseSchema,
|
|
39
39
|
confect,
|
|
40
40
|
ResolvedMiddleware.resolve(confect, middlewareRegistryItems),
|
|
41
|
+
observability,
|
|
41
42
|
),
|
|
42
43
|
),
|
|
43
44
|
Match.exhaustive,
|
|
@@ -49,6 +50,7 @@ export const make = (
|
|
|
49
50
|
databaseSchema: DatabaseSchema.AnyWithProps,
|
|
50
51
|
item: FunctionRegistryItem.ConfectFunctionRegistryItem,
|
|
51
52
|
resolvedMiddlewares: ReadonlyArray<ResolvedMiddleware.ResolvedMiddleware> = [],
|
|
53
|
+
observability?: Layer.Layer<never>,
|
|
52
54
|
): RegisteredFunction.Any => {
|
|
53
55
|
const genericFunction = Match.value(item.functionVisibility).pipe(
|
|
54
56
|
Match.when("public", () => actionGeneric),
|
|
@@ -59,6 +61,7 @@ export const make = (
|
|
|
59
61
|
return genericFunction(
|
|
60
62
|
nodeActionFunction(databaseSchema, {
|
|
61
63
|
name: item.name,
|
|
64
|
+
observability,
|
|
62
65
|
functionVisibility: item.functionVisibility,
|
|
63
66
|
args: item.args,
|
|
64
67
|
returns: item.returns,
|
|
@@ -86,6 +89,7 @@ const nodeActionFunction = <
|
|
|
86
89
|
error,
|
|
87
90
|
handler,
|
|
88
91
|
resolvedMiddlewares,
|
|
92
|
+
observability,
|
|
89
93
|
}: {
|
|
90
94
|
name: string;
|
|
91
95
|
functionVisibility: FunctionVisibility;
|
|
@@ -101,6 +105,7 @@ const nodeActionFunction = <
|
|
|
101
105
|
| NodeServices.NodeServices
|
|
102
106
|
>;
|
|
103
107
|
resolvedMiddlewares: ReadonlyArray<ResolvedMiddleware.ResolvedMiddleware>;
|
|
108
|
+
observability?: Layer.Layer<never> | undefined;
|
|
104
109
|
},
|
|
105
110
|
) =>
|
|
106
111
|
RegisteredFunction.actionFunctionBase({
|
|
@@ -112,6 +117,7 @@ const nodeActionFunction = <
|
|
|
112
117
|
error,
|
|
113
118
|
handler,
|
|
114
119
|
resolvedMiddlewares,
|
|
120
|
+
observability,
|
|
115
121
|
createLayer: (ctx) =>
|
|
116
122
|
Layer.mergeAll(
|
|
117
123
|
RegisteredFunction.actionLayer(databaseSchema, ctx),
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as Duration from "effect/Duration";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Exit from "effect/Exit";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import * as Scope from "effect/Scope";
|
|
6
|
+
import * as ConvexConfigProvider from "../ConvexConfigProvider.js";
|
|
7
|
+
|
|
8
|
+
const memoMap = Layer.makeMemoMapUnsafe();
|
|
9
|
+
export const scope = Scope.makeUnsafe();
|
|
10
|
+
const layers = new WeakMap<Layer.Layer<never>, Layer.Layer<never>>();
|
|
11
|
+
|
|
12
|
+
export const memoized = (layer: Layer.Layer<never>): Layer.Layer<never> => {
|
|
13
|
+
const cached = layers.get(layer);
|
|
14
|
+
if (cached !== undefined) return cached;
|
|
15
|
+
const built = Layer.buildWithMemoMap(layer, memoMap, scope).pipe(
|
|
16
|
+
Effect.provide(ConvexConfigProvider.layer),
|
|
17
|
+
// A failed first build is retried on the next invocation instead of failing every later one.
|
|
18
|
+
Effect.cachedWithTTL((exit) =>
|
|
19
|
+
Exit.isSuccess(exit) ? Duration.infinity : Duration.zero,
|
|
20
|
+
),
|
|
21
|
+
Effect.runSync,
|
|
22
|
+
Effect.uninterruptible,
|
|
23
|
+
Layer.effectContext,
|
|
24
|
+
);
|
|
25
|
+
layers.set(layer, built);
|
|
26
|
+
return built;
|
|
27
|
+
};
|