@dxos/functions 0.8.4-main.84f28bd → 0.8.4-main.a4bbb77
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/lib/browser/bundler/index.mjs +56 -38
- package/dist/lib/browser/bundler/index.mjs.map +3 -3
- package/dist/lib/browser/chunk-C2Z7LCJ2.mjs +649 -0
- package/dist/lib/browser/chunk-C2Z7LCJ2.mjs.map +7 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs.map +7 -0
- package/dist/lib/browser/edge/index.mjs +22 -8
- package/dist/lib/browser/edge/index.mjs.map +3 -3
- package/dist/lib/browser/index.mjs +1007 -133
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +91 -41
- package/dist/lib/browser/testing/index.mjs.map +4 -4
- package/dist/lib/node-esm/bundler/index.mjs +55 -38
- package/dist/lib/node-esm/bundler/index.mjs.map +3 -3
- package/dist/lib/node-esm/chunk-AH3AZM2U.mjs +651 -0
- package/dist/lib/node-esm/chunk-AH3AZM2U.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
- package/dist/lib/node-esm/edge/index.mjs +21 -8
- package/dist/lib/node-esm/edge/index.mjs.map +3 -3
- package/dist/lib/node-esm/index.mjs +1007 -133
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +91 -41
- package/dist/lib/node-esm/testing/index.mjs.map +4 -4
- package/dist/types/src/bundler/bundler.d.ts +11 -12
- package/dist/types/src/bundler/bundler.d.ts.map +1 -1
- package/dist/types/src/edge/functions.d.ts +4 -3
- package/dist/types/src/edge/functions.d.ts.map +1 -1
- package/dist/types/src/errors.d.ts +137 -0
- package/dist/types/src/errors.d.ts.map +1 -0
- package/dist/types/src/examples/fib.d.ts +7 -0
- package/dist/types/src/examples/fib.d.ts.map +1 -0
- package/dist/types/src/examples/index.d.ts +4 -0
- package/dist/types/src/examples/index.d.ts.map +1 -0
- package/dist/types/src/examples/reply.d.ts +3 -0
- package/dist/types/src/examples/reply.d.ts.map +1 -0
- package/dist/types/src/examples/sleep.d.ts +5 -0
- package/dist/types/src/examples/sleep.d.ts.map +1 -0
- package/dist/types/src/executor/executor.d.ts +7 -1
- package/dist/types/src/executor/executor.d.ts.map +1 -1
- package/dist/types/src/handler.d.ts +57 -12
- package/dist/types/src/handler.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +3 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/schema.d.ts +5 -0
- package/dist/types/src/schema.d.ts.map +1 -1
- package/dist/types/src/services/credentials.d.ts +17 -3
- package/dist/types/src/services/credentials.d.ts.map +1 -1
- package/dist/types/src/services/database.d.ts +54 -6
- package/dist/types/src/services/database.d.ts.map +1 -1
- package/dist/types/src/services/event-logger.d.ts +65 -30
- package/dist/types/src/services/event-logger.d.ts.map +1 -1
- package/dist/types/src/services/function-invocation-service.d.ts +26 -0
- package/dist/types/src/services/function-invocation-service.d.ts.map +1 -0
- package/dist/types/src/services/function-invocation-service.test.d.ts +2 -0
- package/dist/types/src/services/function-invocation-service.test.d.ts.map +1 -0
- package/dist/types/src/services/index.d.ts +5 -5
- package/dist/types/src/services/index.d.ts.map +1 -1
- package/dist/types/src/services/local-function-execution.d.ts +32 -0
- package/dist/types/src/services/local-function-execution.d.ts.map +1 -0
- package/dist/types/src/services/queues.d.ts +31 -4
- package/dist/types/src/services/queues.d.ts.map +1 -1
- package/dist/types/src/services/remote-function-execution-service.d.ts +20 -0
- package/dist/types/src/services/remote-function-execution-service.d.ts.map +1 -0
- package/dist/types/src/services/service-container.d.ts +28 -18
- package/dist/types/src/services/service-container.d.ts.map +1 -1
- package/dist/types/src/services/service-registry.d.ts +29 -0
- package/dist/types/src/services/service-registry.d.ts.map +1 -0
- package/dist/types/src/services/service-registry.test.d.ts +2 -0
- package/dist/types/src/services/service-registry.test.d.ts.map +1 -0
- package/dist/types/src/services/tracing.d.ts +46 -4
- package/dist/types/src/services/tracing.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +1 -0
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/layer.d.ts +17 -0
- package/dist/types/src/testing/layer.d.ts.map +1 -0
- package/dist/types/src/testing/logger.d.ts +3 -3
- package/dist/types/src/testing/logger.d.ts.map +1 -1
- package/dist/types/src/testing/persist-database.test.d.ts +2 -0
- package/dist/types/src/testing/persist-database.test.d.ts.map +1 -0
- package/dist/types/src/testing/services.d.ts +7 -19
- package/dist/types/src/testing/services.d.ts.map +1 -1
- package/dist/types/src/trace.d.ts +20 -22
- package/dist/types/src/trace.d.ts.map +1 -1
- package/dist/types/src/triggers/index.d.ts +4 -0
- package/dist/types/src/triggers/index.d.ts.map +1 -0
- package/dist/types/src/triggers/input-builder.d.ts +3 -0
- package/dist/types/src/triggers/input-builder.d.ts.map +1 -0
- package/dist/types/src/triggers/invocation-tracer.d.ts +35 -0
- package/dist/types/src/triggers/invocation-tracer.d.ts.map +1 -0
- package/dist/types/src/triggers/trigger-dispatcher.d.ts +74 -0
- package/dist/types/src/triggers/trigger-dispatcher.d.ts.map +1 -0
- package/dist/types/src/triggers/trigger-dispatcher.test.d.ts +2 -0
- package/dist/types/src/triggers/trigger-dispatcher.test.d.ts.map +1 -0
- package/dist/types/src/triggers/trigger-state-store.d.ts +27 -0
- package/dist/types/src/triggers/trigger-state-store.d.ts.map +1 -0
- package/dist/types/src/types.d.ts +55 -245
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/src/url.d.ts +10 -6
- package/dist/types/src/url.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +40 -33
- package/src/bundler/bundler.test.ts +8 -9
- package/src/bundler/bundler.ts +32 -33
- package/src/edge/functions.ts +9 -6
- package/src/errors.ts +21 -0
- package/src/examples/fib.ts +31 -0
- package/src/examples/index.ts +7 -0
- package/src/examples/reply.ts +19 -0
- package/src/examples/sleep.ts +23 -0
- package/src/executor/executor.ts +12 -9
- package/src/handler.ts +133 -24
- package/src/index.ts +3 -2
- package/src/schema.ts +11 -0
- package/src/services/credentials.ts +88 -4
- package/src/services/database.ts +141 -20
- package/src/services/event-logger.ts +68 -37
- package/src/services/function-invocation-service.test.ts +79 -0
- package/src/services/function-invocation-service.ts +82 -0
- package/src/services/index.ts +5 -5
- package/src/services/local-function-execution.ts +150 -0
- package/src/services/queues.ts +48 -8
- package/src/services/remote-function-execution-service.ts +61 -0
- package/src/services/service-container.ts +45 -58
- package/src/services/service-registry.test.ts +42 -0
- package/src/services/service-registry.ts +59 -0
- package/src/services/tracing.ts +120 -6
- package/src/testing/index.ts +1 -0
- package/src/testing/layer.ts +112 -0
- package/src/testing/logger.ts +4 -4
- package/src/testing/persist-database.test.ts +87 -0
- package/src/testing/services.ts +11 -70
- package/src/trace.ts +17 -19
- package/src/triggers/index.ts +7 -0
- package/src/triggers/input-builder.ts +35 -0
- package/src/triggers/invocation-tracer.ts +99 -0
- package/src/triggers/trigger-dispatcher.test.ts +651 -0
- package/src/triggers/trigger-dispatcher.ts +522 -0
- package/src/triggers/trigger-state-store.ts +60 -0
- package/src/types.ts +39 -36
- package/src/url.ts +13 -10
- package/dist/lib/browser/chunk-54U464M4.mjs +0 -360
- package/dist/lib/browser/chunk-54U464M4.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-XDSX35BS.mjs +0 -362
- package/dist/lib/node-esm/chunk-XDSX35BS.mjs.map +0 -7
- package/dist/types/src/services/ai.d.ts +0 -12
- package/dist/types/src/services/ai.d.ts.map +0 -1
- package/dist/types/src/services/function-call-service.d.ts +0 -16
- package/dist/types/src/services/function-call-service.d.ts.map +0 -1
- package/dist/types/src/services/tool-resolver.d.ts +0 -14
- package/dist/types/src/services/tool-resolver.d.ts.map +0 -1
- package/src/services/ai.ts +0 -32
- package/src/services/function-call-service.ts +0 -64
- package/src/services/tool-resolver.ts +0 -31
|
@@ -1,48 +1,51 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
ComputeEvent,
|
|
3
|
+
ComputeEventLogger,
|
|
4
|
+
ComputeEventPayload,
|
|
3
5
|
ConfiguredCredentialsService,
|
|
6
|
+
ContextQueueService,
|
|
4
7
|
CredentialsService,
|
|
5
8
|
DatabaseService,
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
FUNCTIONS_META_KEY,
|
|
10
|
+
FUNCTIONS_PRESET_META_KEY,
|
|
11
|
+
FunctionError,
|
|
12
|
+
FunctionNotFoundError,
|
|
13
|
+
MESSAGE_PROPERTY_TOOL_CALL_ID,
|
|
8
14
|
QueueService,
|
|
15
|
+
RemoteFunctionExecutionService,
|
|
9
16
|
SERVICE_TAGS,
|
|
10
17
|
ServiceContainer,
|
|
11
|
-
|
|
18
|
+
ServiceNotAvailableError,
|
|
12
19
|
TracingService,
|
|
20
|
+
TriggerStateNotFoundError,
|
|
13
21
|
createDefectLogger,
|
|
14
22
|
createEventLogger,
|
|
15
|
-
|
|
16
|
-
|
|
23
|
+
getInvocationUrl,
|
|
24
|
+
getUserFunctionIdInMetadata,
|
|
25
|
+
logCustomEvent,
|
|
26
|
+
setUserFunctionIdInMetadata,
|
|
27
|
+
withAuthorization
|
|
28
|
+
} from "./chunk-C2Z7LCJ2.mjs";
|
|
29
|
+
import {
|
|
30
|
+
__export
|
|
31
|
+
} from "./chunk-J5LGTIGS.mjs";
|
|
17
32
|
|
|
18
33
|
// src/handler.ts
|
|
19
|
-
import { Schema } from "effect";
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
throw new Error("Input schema must be a valid schema");
|
|
23
|
-
}
|
|
24
|
-
if (typeof params.handler !== "function") {
|
|
25
|
-
throw new Error("Handler must be a function");
|
|
26
|
-
}
|
|
27
|
-
return {
|
|
28
|
-
description: params.description,
|
|
29
|
-
inputSchema: params.inputSchema,
|
|
30
|
-
outputSchema: params.outputSchema ?? Schema.Any,
|
|
31
|
-
handler: params.handler
|
|
32
|
-
};
|
|
33
|
-
};
|
|
34
|
+
import { Effect, Schema as Schema2 } from "effect";
|
|
35
|
+
import { Obj, Type as Type2 } from "@dxos/echo";
|
|
36
|
+
import { assertArgument } from "@dxos/invariant";
|
|
34
37
|
|
|
35
38
|
// src/schema.ts
|
|
36
|
-
import { Schema
|
|
39
|
+
import { Schema } from "effect";
|
|
37
40
|
import { Type } from "@dxos/echo";
|
|
38
41
|
import { JsonSchemaType, LabelAnnotation, Ref } from "@dxos/echo-schema";
|
|
39
42
|
import { DataType } from "@dxos/schema";
|
|
40
|
-
var ScriptType =
|
|
41
|
-
name:
|
|
42
|
-
description:
|
|
43
|
+
var ScriptType = Schema.Struct({
|
|
44
|
+
name: Schema.optional(Schema.String),
|
|
45
|
+
description: Schema.optional(Schema.String),
|
|
43
46
|
// TODO(burdon): Change to hash of deployed content.
|
|
44
47
|
// Whether source has changed since last deploy.
|
|
45
|
-
changed:
|
|
48
|
+
changed: Schema.optional(Schema.Boolean),
|
|
46
49
|
source: Ref(DataType.Text)
|
|
47
50
|
}).pipe(Type.Obj({
|
|
48
51
|
typename: "dxos.org/type/Script",
|
|
@@ -50,18 +53,28 @@ var ScriptType = Schema2.Struct({
|
|
|
50
53
|
}), LabelAnnotation.set([
|
|
51
54
|
"name"
|
|
52
55
|
]));
|
|
53
|
-
var FunctionType =
|
|
56
|
+
var FunctionType = Schema.Struct({
|
|
57
|
+
/**
|
|
58
|
+
* Global registry ID.
|
|
59
|
+
* NOTE: The `key` property refers to the original registry entry.
|
|
60
|
+
*/
|
|
61
|
+
// TODO(burdon): Create Format type for DXN-like ids, such as this and schema type.
|
|
62
|
+
// TODO(dmaretskyi): Consider making it part of ECHO meta.
|
|
63
|
+
// TODO(dmaretskyi): Make required.
|
|
64
|
+
key: Schema.optional(Schema.String).annotations({
|
|
65
|
+
description: "Unique registration key for the blueprint"
|
|
66
|
+
}),
|
|
54
67
|
// TODO(burdon): Rename to id/uri?
|
|
55
|
-
name:
|
|
56
|
-
version:
|
|
57
|
-
description:
|
|
68
|
+
name: Schema.NonEmptyString,
|
|
69
|
+
version: Schema.String,
|
|
70
|
+
description: Schema.optional(Schema.String),
|
|
58
71
|
// Reference to a source script if it exists within ECHO.
|
|
59
72
|
// TODO(burdon): Don't ref ScriptType directly (core).
|
|
60
|
-
source:
|
|
61
|
-
inputSchema:
|
|
62
|
-
outputSchema:
|
|
73
|
+
source: Schema.optional(Ref(ScriptType)),
|
|
74
|
+
inputSchema: Schema.optional(JsonSchemaType),
|
|
75
|
+
outputSchema: Schema.optional(JsonSchemaType),
|
|
63
76
|
// Local binding to a function name.
|
|
64
|
-
binding:
|
|
77
|
+
binding: Schema.optional(Schema.String)
|
|
65
78
|
}).pipe(Type.Obj({
|
|
66
79
|
typename: "dxos.org/type/Function",
|
|
67
80
|
version: "0.1.0"
|
|
@@ -69,25 +82,116 @@ var FunctionType = Schema2.Struct({
|
|
|
69
82
|
"name"
|
|
70
83
|
]));
|
|
71
84
|
|
|
85
|
+
// src/handler.ts
|
|
86
|
+
var typeId = Symbol.for("@dxos/functions/FunctionDefinition");
|
|
87
|
+
var defineFunction = ({ key, name, description, inputSchema, outputSchema = Schema2.Any, handler }) => {
|
|
88
|
+
if (!Schema2.isSchema(inputSchema)) {
|
|
89
|
+
throw new Error("Input schema must be a valid schema");
|
|
90
|
+
}
|
|
91
|
+
if (typeof handler !== "function") {
|
|
92
|
+
throw new Error("Handler must be a function");
|
|
93
|
+
}
|
|
94
|
+
const limit = Error.stackTraceLimit;
|
|
95
|
+
Error.stackTraceLimit = 2;
|
|
96
|
+
const traceError = new Error();
|
|
97
|
+
Error.stackTraceLimit = limit;
|
|
98
|
+
let cache = false;
|
|
99
|
+
const captureStackTrace = () => {
|
|
100
|
+
if (cache !== false) {
|
|
101
|
+
return cache;
|
|
102
|
+
}
|
|
103
|
+
if (traceError.stack !== void 0) {
|
|
104
|
+
const stack = traceError.stack.split("\n");
|
|
105
|
+
if (stack[2] !== void 0) {
|
|
106
|
+
cache = stack[2].trim();
|
|
107
|
+
return cache;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
const handlerWithSpan = (...args) => {
|
|
112
|
+
const result = handler(...args);
|
|
113
|
+
if (Effect.isEffect(result)) {
|
|
114
|
+
return Effect.withSpan(result, `${key ?? name}`, {
|
|
115
|
+
captureStackTrace
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return result;
|
|
119
|
+
};
|
|
120
|
+
return {
|
|
121
|
+
[typeId]: true,
|
|
122
|
+
key,
|
|
123
|
+
name,
|
|
124
|
+
description,
|
|
125
|
+
inputSchema,
|
|
126
|
+
outputSchema,
|
|
127
|
+
handler: handlerWithSpan
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
var FunctionDefinition = {
|
|
131
|
+
make: defineFunction,
|
|
132
|
+
isFunction: (value) => {
|
|
133
|
+
return typeof value === "object" && value !== null && Symbol.for("@dxos/functions/FunctionDefinition") in value;
|
|
134
|
+
},
|
|
135
|
+
serialize: (functionDef) => {
|
|
136
|
+
assertArgument(FunctionDefinition.isFunction(functionDef), "functionDef");
|
|
137
|
+
return serializeFunction(functionDef);
|
|
138
|
+
},
|
|
139
|
+
deserialize: (functionObj) => {
|
|
140
|
+
assertArgument(Obj.instanceOf(FunctionType, functionObj), "functionObj");
|
|
141
|
+
return deserializeFunction(functionObj);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
var serializeFunction = (functionDef) => {
|
|
145
|
+
const fn = Obj.make(FunctionType, {
|
|
146
|
+
key: functionDef.key,
|
|
147
|
+
name: functionDef.name,
|
|
148
|
+
version: "0.1.0",
|
|
149
|
+
description: functionDef.description,
|
|
150
|
+
inputSchema: Type2.toJsonSchema(functionDef.inputSchema),
|
|
151
|
+
outputSchema: !functionDef.outputSchema ? void 0 : Type2.toJsonSchema(functionDef.outputSchema)
|
|
152
|
+
});
|
|
153
|
+
if (functionDef.meta?.deployedFunctionId) {
|
|
154
|
+
setUserFunctionIdInMetadata(Obj.getMeta(fn), functionDef.meta.deployedFunctionId);
|
|
155
|
+
}
|
|
156
|
+
return fn;
|
|
157
|
+
};
|
|
158
|
+
var deserializeFunction = (functionObj) => {
|
|
159
|
+
return {
|
|
160
|
+
[typeId]: true,
|
|
161
|
+
// TODO(dmaretskyi): Fix key.
|
|
162
|
+
key: functionObj.key ?? functionObj.name,
|
|
163
|
+
name: functionObj.name,
|
|
164
|
+
description: functionObj.description,
|
|
165
|
+
inputSchema: !functionObj.inputSchema ? Schema2.Unknown : Type2.toEffectSchema(functionObj.inputSchema),
|
|
166
|
+
outputSchema: !functionObj.outputSchema ? void 0 : Type2.toEffectSchema(functionObj.outputSchema),
|
|
167
|
+
// TODO(dmaretskyi): This should throw error.
|
|
168
|
+
handler: () => {
|
|
169
|
+
},
|
|
170
|
+
meta: {
|
|
171
|
+
deployedFunctionId: getUserFunctionIdInMetadata(Obj.getMeta(functionObj))
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
|
|
72
176
|
// src/trace.ts
|
|
73
177
|
import { Schema as Schema4 } from "effect";
|
|
74
|
-
import { Type as
|
|
178
|
+
import { Type as Type4 } from "@dxos/echo";
|
|
75
179
|
import { Queue } from "@dxos/echo-db";
|
|
76
180
|
import { ObjectId } from "@dxos/echo-schema";
|
|
77
181
|
import { log } from "@dxos/log";
|
|
78
182
|
|
|
79
183
|
// src/types.ts
|
|
80
184
|
import { Schema as Schema3, SchemaAST } from "effect";
|
|
81
|
-
import {
|
|
185
|
+
import { Obj as Obj2, QueryAST, Type as Type3 } from "@dxos/echo";
|
|
186
|
+
import { Expando, OptionsAnnotationId, RawObject, Ref as Ref2 } from "@dxos/echo-schema";
|
|
82
187
|
import { DXN } from "@dxos/keys";
|
|
83
|
-
var
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}({});
|
|
188
|
+
var TriggerKinds = [
|
|
189
|
+
"timer",
|
|
190
|
+
"webhook",
|
|
191
|
+
"subscription",
|
|
192
|
+
"email",
|
|
193
|
+
"queue"
|
|
194
|
+
];
|
|
91
195
|
var kindLiteralAnnotations = {
|
|
92
196
|
title: "Kind"
|
|
93
197
|
};
|
|
@@ -105,6 +209,7 @@ var EmailTriggerSchema = Schema3.Struct({
|
|
|
105
209
|
}).pipe(Schema3.mutable);
|
|
106
210
|
var QueueTriggerSchema = Schema3.Struct({
|
|
107
211
|
kind: Schema3.Literal("queue").annotations(kindLiteralAnnotations),
|
|
212
|
+
// TODO(dmaretskyi): Change to a reference.
|
|
108
213
|
queue: DXN.Schema
|
|
109
214
|
}).pipe(Schema3.mutable);
|
|
110
215
|
var WebhookTriggerSchema = Schema3.Struct({
|
|
@@ -120,21 +225,11 @@ var WebhookTriggerSchema = Schema3.Struct({
|
|
|
120
225
|
title: "Port"
|
|
121
226
|
}))
|
|
122
227
|
}).pipe(Schema3.mutable);
|
|
123
|
-
var QuerySchema = Schema3.Struct({
|
|
124
|
-
type: Schema3.optional(Schema3.String.annotations({
|
|
125
|
-
title: "Type"
|
|
126
|
-
})),
|
|
127
|
-
props: Schema3.optional(Schema3.Record({
|
|
128
|
-
key: Schema3.String,
|
|
129
|
-
value: Schema3.Any
|
|
130
|
-
}))
|
|
131
|
-
}).annotations({
|
|
132
|
-
title: "Query"
|
|
133
|
-
});
|
|
134
228
|
var SubscriptionTriggerSchema = Schema3.Struct({
|
|
135
229
|
kind: Schema3.Literal("subscription").annotations(kindLiteralAnnotations),
|
|
136
|
-
|
|
137
|
-
|
|
230
|
+
query: QueryAST.Query.annotations({
|
|
231
|
+
title: "Query"
|
|
232
|
+
}),
|
|
138
233
|
options: Schema3.optional(Schema3.Struct({
|
|
139
234
|
// Watch changes to object (not just creation).
|
|
140
235
|
deep: Schema3.optional(Schema3.Boolean.annotations({
|
|
@@ -172,14 +267,25 @@ var QueueTriggerOutput = Schema3.mutable(Schema3.Struct({
|
|
|
172
267
|
item: Schema3.Any,
|
|
173
268
|
cursor: Schema3.String
|
|
174
269
|
}));
|
|
175
|
-
var SubscriptionTriggerOutput = Schema3.
|
|
270
|
+
var SubscriptionTriggerOutput = Schema3.Struct({
|
|
271
|
+
/**
|
|
272
|
+
* Type of the mutation.
|
|
273
|
+
*/
|
|
274
|
+
// TODO(dmaretskyi): Specify enum.
|
|
176
275
|
type: Schema3.String,
|
|
177
|
-
|
|
178
|
-
|
|
276
|
+
/**
|
|
277
|
+
* Reference to the object that was changed or created.
|
|
278
|
+
*/
|
|
279
|
+
subject: Type3.Ref(Obj2.Any),
|
|
280
|
+
/**
|
|
281
|
+
* @deprecated
|
|
282
|
+
*/
|
|
283
|
+
changedObjectId: Schema3.optional(Schema3.String)
|
|
284
|
+
}).pipe(Schema3.mutable);
|
|
179
285
|
var TimerTriggerOutput = Schema3.mutable(Schema3.Struct({
|
|
180
286
|
tick: Schema3.Number
|
|
181
287
|
}));
|
|
182
|
-
var
|
|
288
|
+
var FunctionTrigger_ = Schema3.Struct({
|
|
183
289
|
/**
|
|
184
290
|
* Function or workflow to invoke.
|
|
185
291
|
*/
|
|
@@ -214,12 +320,11 @@ var FunctionTriggerSchema = Schema3.Struct({
|
|
|
214
320
|
key: Schema3.String,
|
|
215
321
|
value: Schema3.Any
|
|
216
322
|
})))
|
|
217
|
-
})
|
|
218
|
-
var FunctionTrigger = class extends TypedObject({
|
|
323
|
+
}).pipe(Type3.Obj({
|
|
219
324
|
typename: "dxos.org/type/FunctionTrigger",
|
|
220
325
|
version: "0.2.0"
|
|
221
|
-
})
|
|
222
|
-
|
|
326
|
+
}));
|
|
327
|
+
var FunctionTrigger = FunctionTrigger_;
|
|
223
328
|
var FunctionManifestSchema = Schema3.Struct({
|
|
224
329
|
functions: Schema3.optional(Schema3.mutable(Schema3.Array(RawObject(FunctionType)))),
|
|
225
330
|
triggers: Schema3.optional(Schema3.mutable(Schema3.Array(RawObject(FunctionTrigger))))
|
|
@@ -231,19 +336,19 @@ var FUNCTION_TYPES = [
|
|
|
231
336
|
|
|
232
337
|
// src/trace.ts
|
|
233
338
|
var __dxlog_file = "/__w/dxos/dxos/packages/core/functions/src/trace.ts";
|
|
234
|
-
var InvocationOutcome = /* @__PURE__ */ function(InvocationOutcome2) {
|
|
339
|
+
var InvocationOutcome = /* @__PURE__ */ (function(InvocationOutcome2) {
|
|
235
340
|
InvocationOutcome2["SUCCESS"] = "success";
|
|
236
341
|
InvocationOutcome2["FAILURE"] = "failure";
|
|
237
342
|
InvocationOutcome2["PENDING"] = "pending";
|
|
238
343
|
return InvocationOutcome2;
|
|
239
|
-
}({});
|
|
240
|
-
var InvocationTraceEventType = /* @__PURE__ */ function(InvocationTraceEventType2) {
|
|
344
|
+
})({});
|
|
345
|
+
var InvocationTraceEventType = /* @__PURE__ */ (function(InvocationTraceEventType2) {
|
|
241
346
|
InvocationTraceEventType2["START"] = "start";
|
|
242
347
|
InvocationTraceEventType2["END"] = "end";
|
|
243
348
|
return InvocationTraceEventType2;
|
|
244
|
-
}({});
|
|
349
|
+
})({});
|
|
245
350
|
var TraceEventException = Schema4.Struct({
|
|
246
|
-
|
|
351
|
+
timestamp: Schema4.Number,
|
|
247
352
|
message: Schema4.String,
|
|
248
353
|
name: Schema4.String,
|
|
249
354
|
stack: Schema4.optional(Schema4.String)
|
|
@@ -261,7 +366,7 @@ var InvocationTraceStartEvent = Schema4.Struct({
|
|
|
261
366
|
/**
|
|
262
367
|
* Event generation time.
|
|
263
368
|
*/
|
|
264
|
-
|
|
369
|
+
timestamp: Schema4.Number,
|
|
265
370
|
/**
|
|
266
371
|
* Data passed to function / workflow as an argument.
|
|
267
372
|
*/
|
|
@@ -270,16 +375,16 @@ var InvocationTraceStartEvent = Schema4.Struct({
|
|
|
270
375
|
/**
|
|
271
376
|
* Queue for function/workflow invocation events.
|
|
272
377
|
*/
|
|
273
|
-
invocationTraceQueue:
|
|
378
|
+
invocationTraceQueue: Schema4.optional(Type4.Ref(Queue)),
|
|
274
379
|
/**
|
|
275
380
|
* DXN of the invoked function/workflow.
|
|
276
381
|
*/
|
|
277
|
-
invocationTarget:
|
|
382
|
+
invocationTarget: Schema4.optional(Type4.Ref(Type4.Expando)),
|
|
278
383
|
/**
|
|
279
384
|
* Present for automatic invocations.
|
|
280
385
|
*/
|
|
281
|
-
trigger: Schema4.optional(
|
|
282
|
-
}).pipe(
|
|
386
|
+
trigger: Schema4.optional(Type4.Ref(FunctionTrigger))
|
|
387
|
+
}).pipe(Type4.Obj({
|
|
283
388
|
typename: "dxos.org/type/InvocationTraceStart",
|
|
284
389
|
version: "0.1.0"
|
|
285
390
|
}));
|
|
@@ -297,15 +402,15 @@ var InvocationTraceEndEvent = Schema4.Struct({
|
|
|
297
402
|
* Event generation time.
|
|
298
403
|
*/
|
|
299
404
|
// TODO(burdon): Remove ms suffix.
|
|
300
|
-
|
|
405
|
+
timestamp: Schema4.Number,
|
|
301
406
|
outcome: Schema4.Enums(InvocationOutcome),
|
|
302
407
|
exception: Schema4.optional(TraceEventException)
|
|
303
|
-
}).pipe(
|
|
408
|
+
}).pipe(Type4.Obj({
|
|
304
409
|
typename: "dxos.org/type/InvocationTraceEnd",
|
|
305
410
|
version: "0.1.0"
|
|
306
411
|
}));
|
|
307
412
|
var TraceEventLog = Schema4.Struct({
|
|
308
|
-
|
|
413
|
+
timestamp: Schema4.Number,
|
|
309
414
|
level: Schema4.String,
|
|
310
415
|
message: Schema4.String,
|
|
311
416
|
context: Schema4.optional(Schema4.Object)
|
|
@@ -315,13 +420,11 @@ var TraceEvent = Schema4.Struct({
|
|
|
315
420
|
// TODO(burdon): Need enum/numeric result (not string).
|
|
316
421
|
outcome: Schema4.String,
|
|
317
422
|
truncated: Schema4.Boolean,
|
|
318
|
-
/**
|
|
319
|
-
|
|
320
|
-
*/
|
|
321
|
-
ingestionTimestampMs: Schema4.Number,
|
|
423
|
+
/** Time when the event was persisted. */
|
|
424
|
+
ingestionTimestamp: Schema4.Number,
|
|
322
425
|
logs: Schema4.Array(TraceEventLog),
|
|
323
426
|
exceptions: Schema4.Array(TraceEventException)
|
|
324
|
-
}).pipe(
|
|
427
|
+
}).pipe(Type4.Obj({
|
|
325
428
|
typename: "dxos.org/type/TraceEvent",
|
|
326
429
|
version: "0.1.0"
|
|
327
430
|
}));
|
|
@@ -354,7 +457,7 @@ var createInvocationSpans = (items) => {
|
|
|
354
457
|
invocationId
|
|
355
458
|
}, {
|
|
356
459
|
F: __dxlog_file,
|
|
357
|
-
L:
|
|
460
|
+
L: 158,
|
|
358
461
|
S: void 0,
|
|
359
462
|
C: (f, a) => f(...a)
|
|
360
463
|
});
|
|
@@ -363,8 +466,8 @@ var createInvocationSpans = (items) => {
|
|
|
363
466
|
const isInProgress = end === void 0;
|
|
364
467
|
result.push({
|
|
365
468
|
id: invocationId,
|
|
366
|
-
|
|
367
|
-
|
|
469
|
+
timestamp: start.timestamp,
|
|
470
|
+
duration: isInProgress ? now - start.timestamp : end.timestamp - start.timestamp,
|
|
368
471
|
outcome: end?.outcome ?? "pending",
|
|
369
472
|
exception: end?.exception,
|
|
370
473
|
input: start.input,
|
|
@@ -376,117 +479,888 @@ var createInvocationSpans = (items) => {
|
|
|
376
479
|
return result;
|
|
377
480
|
};
|
|
378
481
|
|
|
379
|
-
// src/
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
482
|
+
// src/triggers/invocation-tracer.ts
|
|
483
|
+
import { Context as Context3, Effect as Effect4, Layer as Layer3 } from "effect";
|
|
484
|
+
import { Obj as Obj3, Ref as Ref3 } from "@dxos/echo";
|
|
485
|
+
import { DXN as DXN2, ObjectId as ObjectId2 } from "@dxos/keys";
|
|
486
|
+
|
|
487
|
+
// src/services/function-invocation-service.ts
|
|
488
|
+
import { Context as Context2, Effect as Effect3, Layer as Layer2 } from "effect";
|
|
489
|
+
import { AiService as AiService2 } from "@dxos/ai";
|
|
490
|
+
|
|
491
|
+
// src/services/local-function-execution.ts
|
|
492
|
+
import { Context, Effect as Effect2, Layer, Schema as Schema5 } from "effect";
|
|
493
|
+
import { AiService } from "@dxos/ai";
|
|
494
|
+
import { todo } from "@dxos/debug";
|
|
495
|
+
import { log as log2 } from "@dxos/log";
|
|
496
|
+
function _define_property(obj, key, value) {
|
|
497
|
+
if (key in obj) {
|
|
498
|
+
Object.defineProperty(obj, key, {
|
|
499
|
+
value,
|
|
500
|
+
enumerable: true,
|
|
501
|
+
configurable: true,
|
|
502
|
+
writable: true
|
|
503
|
+
});
|
|
504
|
+
} else {
|
|
505
|
+
obj[key] = value;
|
|
506
|
+
}
|
|
507
|
+
return obj;
|
|
508
|
+
}
|
|
509
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/core/functions/src/services/local-function-execution.ts";
|
|
510
|
+
var _Context_Tag;
|
|
511
|
+
var LocalFunctionExecutionService = class extends (_Context_Tag = Context.Tag("@dxos/functions/LocalFunctionExecutionService")()) {
|
|
384
512
|
};
|
|
385
|
-
|
|
386
|
-
|
|
513
|
+
_define_property(LocalFunctionExecutionService, "layerLive", Layer.effect(LocalFunctionExecutionService, Effect2.gen(function* () {
|
|
514
|
+
const resolver = yield* FunctionImplementationResolver;
|
|
515
|
+
const ai = yield* AiService.AiService;
|
|
516
|
+
const credentials = yield* CredentialsService;
|
|
517
|
+
const database = yield* DatabaseService;
|
|
518
|
+
const queues = yield* QueueService;
|
|
519
|
+
const functionCallService = yield* RemoteFunctionExecutionService;
|
|
520
|
+
return {
|
|
521
|
+
// TODO(dmaretskyi): Better error types.
|
|
522
|
+
invokeFunction: (functionDef, input) => Effect2.gen(function* () {
|
|
523
|
+
const resolved = yield* resolver.resolveFunctionImplementation(functionDef).pipe(Effect2.orDie);
|
|
524
|
+
const output = yield* invokeFunction(resolved, input);
|
|
525
|
+
return output;
|
|
526
|
+
}).pipe(Effect2.provideService(AiService.AiService, ai), Effect2.provideService(CredentialsService, credentials), Effect2.provideService(DatabaseService, database), Effect2.provideService(QueueService, queues), Effect2.provideService(RemoteFunctionExecutionService, functionCallService))
|
|
527
|
+
};
|
|
528
|
+
})));
|
|
529
|
+
_define_property(LocalFunctionExecutionService, "invokeFunction", Effect2.serviceFunctionEffect(LocalFunctionExecutionService, (_) => _.invokeFunction));
|
|
530
|
+
var invokeFunction = (functionDef, input) => Effect2.gen(function* () {
|
|
531
|
+
try {
|
|
532
|
+
const assertInput = functionDef.inputSchema.pipe(Schema5.asserts);
|
|
533
|
+
assertInput(input);
|
|
534
|
+
} catch (e) {
|
|
535
|
+
throw new FunctionError({
|
|
536
|
+
message: "Invalid function input",
|
|
537
|
+
context: {
|
|
538
|
+
name: functionDef.name
|
|
539
|
+
},
|
|
540
|
+
cause: e
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
const context = {
|
|
544
|
+
space: void 0,
|
|
545
|
+
getService: () => todo(),
|
|
546
|
+
getSpace: async (_spaceId) => {
|
|
547
|
+
throw new Error("Not available. Use the database service instead.");
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
log2.info("Invoking function", {
|
|
551
|
+
name: functionDef.name,
|
|
552
|
+
input
|
|
553
|
+
}, {
|
|
554
|
+
F: __dxlog_file2,
|
|
555
|
+
L: 95,
|
|
556
|
+
S: this,
|
|
557
|
+
C: (f, a) => f(...a)
|
|
558
|
+
});
|
|
559
|
+
const data = yield* Effect2.gen(function* () {
|
|
560
|
+
const result = functionDef.handler({
|
|
561
|
+
context,
|
|
562
|
+
data: input
|
|
563
|
+
});
|
|
564
|
+
if (Effect2.isEffect(result)) {
|
|
565
|
+
return yield* result.pipe(Effect2.orDie);
|
|
566
|
+
} else if (typeof result === "object" && result !== null && "then" in result && typeof result.then === "function") {
|
|
567
|
+
return yield* Effect2.promise(() => result);
|
|
568
|
+
} else {
|
|
569
|
+
return result;
|
|
570
|
+
}
|
|
571
|
+
}).pipe(Effect2.orDie, Effect2.catchAllDefect((defect) => Effect2.die(new FunctionError({
|
|
572
|
+
context: {
|
|
573
|
+
name: functionDef.name
|
|
574
|
+
},
|
|
575
|
+
cause: defect
|
|
576
|
+
}))));
|
|
577
|
+
log2.info("Function completed", {
|
|
578
|
+
name: functionDef.name,
|
|
579
|
+
input,
|
|
580
|
+
data
|
|
581
|
+
}, {
|
|
582
|
+
F: __dxlog_file2,
|
|
583
|
+
L: 119,
|
|
584
|
+
S: this,
|
|
585
|
+
C: (f, a) => f(...a)
|
|
586
|
+
});
|
|
587
|
+
try {
|
|
588
|
+
const assertOutput = functionDef.outputSchema?.pipe(Schema5.asserts);
|
|
589
|
+
assertOutput(data);
|
|
590
|
+
} catch (e) {
|
|
591
|
+
throw new FunctionError({
|
|
592
|
+
message: "Invalid function output",
|
|
593
|
+
context: {
|
|
594
|
+
name: functionDef.name
|
|
595
|
+
},
|
|
596
|
+
cause: e
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
return data;
|
|
600
|
+
}).pipe(Effect2.withSpan("invokeFunction", {
|
|
601
|
+
attributes: {
|
|
602
|
+
name: functionDef.name
|
|
603
|
+
}
|
|
604
|
+
}));
|
|
605
|
+
var _Context_Tag1;
|
|
606
|
+
var FunctionImplementationResolver = class extends (_Context_Tag1 = Context.Tag("@dxos/functions/FunctionImplementationResolver")()) {
|
|
387
607
|
};
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
if (
|
|
392
|
-
|
|
608
|
+
_define_property(FunctionImplementationResolver, "layerTest", ({ functions }) => Layer.succeed(FunctionImplementationResolver, {
|
|
609
|
+
resolveFunctionImplementation: (functionDef) => {
|
|
610
|
+
const resolved = functions.find((f) => f.key === functionDef.key);
|
|
611
|
+
if (!resolved) {
|
|
612
|
+
return Effect2.fail(new FunctionNotFoundError(functionDef.name));
|
|
393
613
|
}
|
|
614
|
+
return Effect2.succeed(resolved);
|
|
615
|
+
}
|
|
616
|
+
}));
|
|
617
|
+
|
|
618
|
+
// src/services/function-invocation-service.ts
|
|
619
|
+
function _define_property2(obj, key, value) {
|
|
620
|
+
if (key in obj) {
|
|
621
|
+
Object.defineProperty(obj, key, {
|
|
622
|
+
value,
|
|
623
|
+
enumerable: true,
|
|
624
|
+
configurable: true,
|
|
625
|
+
writable: true
|
|
626
|
+
});
|
|
394
627
|
} else {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
628
|
+
obj[key] = value;
|
|
629
|
+
}
|
|
630
|
+
return obj;
|
|
631
|
+
}
|
|
632
|
+
var _Context_Tag2;
|
|
633
|
+
var FunctionInvocationService = class extends (_Context_Tag2 = Context2.Tag("@dxos/functions/FunctionInvocationService")()) {
|
|
634
|
+
};
|
|
635
|
+
_define_property2(FunctionInvocationService, "invokeFunction", Effect3.serviceFunctionEffect(FunctionInvocationService, (_) => _.invokeFunction));
|
|
636
|
+
_define_property2(FunctionInvocationService, "layer", Layer2.effect(FunctionInvocationService, Effect3.gen(function* () {
|
|
637
|
+
const localExecutioner = yield* LocalFunctionExecutionService;
|
|
638
|
+
const remoteExecutioner = yield* RemoteFunctionExecutionService;
|
|
639
|
+
return {
|
|
640
|
+
invokeFunction: (functionDef, input) => Effect3.gen(function* () {
|
|
641
|
+
if (functionDef.meta?.deployedFunctionId) {
|
|
642
|
+
return yield* remoteExecutioner.callFunction(functionDef.meta.deployedFunctionId, input);
|
|
643
|
+
}
|
|
644
|
+
return yield* localExecutioner.invokeFunction(functionDef, input);
|
|
645
|
+
})
|
|
646
|
+
};
|
|
647
|
+
})));
|
|
648
|
+
_define_property2(FunctionInvocationService, "layerTest", ({ functions = [] } = {}) => FunctionInvocationService.layer.pipe(Layer2.provide(LocalFunctionExecutionService.layerLive), Layer2.provide(FunctionImplementationResolver.layerTest({
|
|
649
|
+
functions
|
|
650
|
+
})), Layer2.provide(RemoteFunctionExecutionService.layerMock)));
|
|
651
|
+
_define_property2(FunctionInvocationService, "layerTestMocked", ({ functions }) => FunctionInvocationService.layerTest({
|
|
652
|
+
functions
|
|
653
|
+
}).pipe(Layer2.provide(AiService2.notAvailable), Layer2.provide(CredentialsService.configuredLayer([])), Layer2.provide(DatabaseService.notAvailable), Layer2.provide(QueueService.notAvailable)));
|
|
654
|
+
|
|
655
|
+
// src/triggers/invocation-tracer.ts
|
|
656
|
+
function _define_property3(obj, key, value) {
|
|
657
|
+
if (key in obj) {
|
|
658
|
+
Object.defineProperty(obj, key, {
|
|
659
|
+
value,
|
|
660
|
+
enumerable: true,
|
|
661
|
+
configurable: true,
|
|
662
|
+
writable: true
|
|
398
663
|
});
|
|
664
|
+
} else {
|
|
665
|
+
obj[key] = value;
|
|
666
|
+
}
|
|
667
|
+
return obj;
|
|
668
|
+
}
|
|
669
|
+
var _Context_Tag3;
|
|
670
|
+
var InvocationTracer = class extends (_Context_Tag3 = Context3.Tag("@dxos/functions/InvocationTracer")()) {
|
|
671
|
+
};
|
|
672
|
+
_define_property3(InvocationTracer, "layerLive", (opts) => Layer3.effect(InvocationTracer, Effect4.gen(function* () {
|
|
673
|
+
return {
|
|
674
|
+
traceInvocationStart: Effect4.fn("traceInvocationStart")(function* ({ payload, target }) {
|
|
675
|
+
const invocationId = ObjectId2.random();
|
|
676
|
+
const invocationTraceQueue = yield* QueueService.createQueue({
|
|
677
|
+
subspaceTag: "trace"
|
|
678
|
+
});
|
|
679
|
+
const now = Date.now();
|
|
680
|
+
const traceEvent = Obj3.make(InvocationTraceStartEvent, {
|
|
681
|
+
type: InvocationTraceEventType.START,
|
|
682
|
+
invocationId,
|
|
683
|
+
timestamp: now,
|
|
684
|
+
// TODO(dmaretskyi): Not json-stringifying this makes ECHO fail when one ECHO object becomes embedded in another ECHO object.
|
|
685
|
+
input: JSON.parse(JSON.stringify(payload.data ?? {})),
|
|
686
|
+
invocationTraceQueue: Ref3.fromDXN(invocationTraceQueue.dxn),
|
|
687
|
+
invocationTarget: target ? Ref3.fromDXN(target) : void 0,
|
|
688
|
+
trigger: payload.trigger ? Ref3.fromDXN(DXN2.fromLocalObjectId(payload.trigger.id)) : void 0
|
|
689
|
+
});
|
|
690
|
+
yield* QueueService.append(opts.invocationTraceQueue, [
|
|
691
|
+
traceEvent
|
|
692
|
+
]);
|
|
693
|
+
return {
|
|
694
|
+
invocationId,
|
|
695
|
+
invocationTraceQueue
|
|
696
|
+
};
|
|
697
|
+
}),
|
|
698
|
+
traceInvocationEnd: Effect4.fn("traceInvocationEnd")(function* ({ trace, exception }) {
|
|
699
|
+
const now = Date.now();
|
|
700
|
+
const traceEvent = Obj3.make(InvocationTraceEndEvent, {
|
|
701
|
+
type: InvocationTraceEventType.END,
|
|
702
|
+
invocationId: trace.invocationId,
|
|
703
|
+
timestamp: now,
|
|
704
|
+
outcome: exception ? InvocationOutcome.FAILURE : InvocationOutcome.SUCCESS,
|
|
705
|
+
exception: exception ? {
|
|
706
|
+
name: exception.constructor.name,
|
|
707
|
+
timestamp: now,
|
|
708
|
+
message: exception?.message ?? "Unknown error",
|
|
709
|
+
stack: exception?.stack
|
|
710
|
+
} : void 0
|
|
711
|
+
});
|
|
712
|
+
yield* QueueService.append(opts.invocationTraceQueue, [
|
|
713
|
+
traceEvent
|
|
714
|
+
]);
|
|
715
|
+
})
|
|
716
|
+
};
|
|
717
|
+
})));
|
|
718
|
+
_define_property3(InvocationTracer, "layerTest", Layer3.unwrapEffect(Effect4.gen(function* () {
|
|
719
|
+
const queue = yield* QueueService.createQueue({
|
|
720
|
+
subspaceTag: "trace"
|
|
721
|
+
});
|
|
722
|
+
return InvocationTracer.layerLive({
|
|
723
|
+
invocationTraceQueue: queue
|
|
724
|
+
});
|
|
725
|
+
})));
|
|
726
|
+
|
|
727
|
+
// src/triggers/trigger-dispatcher.ts
|
|
728
|
+
import { Cause, Context as Context5, Cron, Duration, Effect as Effect6, Either, Exit, Fiber, Layer as Layer5, Option as Option2, Record, Schedule } from "effect";
|
|
729
|
+
import { DXN as DXN3, Filter, Obj as Obj4, Query } from "@dxos/echo";
|
|
730
|
+
import { causeToError } from "@dxos/effect";
|
|
731
|
+
import { invariant } from "@dxos/invariant";
|
|
732
|
+
import { log as log3 } from "@dxos/log";
|
|
733
|
+
import { KEY_QUEUE_POSITION } from "@dxos/protocols";
|
|
734
|
+
|
|
735
|
+
// src/triggers/input-builder.ts
|
|
736
|
+
var createInvocationPayload = (trigger, event) => {
|
|
737
|
+
if (!trigger.input) {
|
|
738
|
+
return event;
|
|
739
|
+
}
|
|
740
|
+
const payload = {};
|
|
741
|
+
for (const [key, value] of Object.entries(trigger.input)) {
|
|
742
|
+
if (typeof value !== "string" || !(value.startsWith("{{") && value.endsWith("}}"))) {
|
|
743
|
+
payload[key] = value;
|
|
744
|
+
continue;
|
|
745
|
+
}
|
|
746
|
+
const propertyPath = value.slice(2, -2);
|
|
747
|
+
let valueSubstitution = propertyPath.startsWith("trigger.") ? trigger : propertyPath.startsWith("event.") ? event : void 0;
|
|
748
|
+
for (const pathSegment of propertyPath.split(".").slice(1)) {
|
|
749
|
+
if (valueSubstitution && typeof valueSubstitution === "object") {
|
|
750
|
+
valueSubstitution = valueSubstitution[pathSegment];
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
payload[key] = valueSubstitution;
|
|
399
754
|
}
|
|
755
|
+
return payload;
|
|
400
756
|
};
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
757
|
+
|
|
758
|
+
// src/triggers/trigger-state-store.ts
|
|
759
|
+
import { KeyValueStore } from "@effect/platform";
|
|
760
|
+
import { Context as Context4 } from "effect";
|
|
761
|
+
import { Schema as Schema6 } from "effect";
|
|
762
|
+
import { Effect as Effect5, Layer as Layer4 } from "effect";
|
|
763
|
+
import { Option } from "effect";
|
|
764
|
+
import { ObjectId as ObjectId3 } from "@dxos/keys";
|
|
765
|
+
function _define_property4(obj, key, value) {
|
|
766
|
+
if (key in obj) {
|
|
767
|
+
Object.defineProperty(obj, key, {
|
|
768
|
+
value,
|
|
769
|
+
enumerable: true,
|
|
770
|
+
configurable: true,
|
|
771
|
+
writable: true
|
|
772
|
+
});
|
|
773
|
+
} else {
|
|
774
|
+
obj[key] = value;
|
|
775
|
+
}
|
|
776
|
+
return obj;
|
|
777
|
+
}
|
|
778
|
+
var TriggerState = Schema6.Struct({
|
|
779
|
+
version: Schema6.Literal("1"),
|
|
780
|
+
triggerId: Schema6.String,
|
|
781
|
+
state: Schema6.optional(Schema6.Union(Schema6.TaggedStruct("subscription", {
|
|
782
|
+
processedVersions: Schema6.Record({
|
|
783
|
+
key: ObjectId3,
|
|
784
|
+
value: Schema6.String
|
|
785
|
+
})
|
|
786
|
+
})))
|
|
787
|
+
});
|
|
788
|
+
var _Context_Tag4;
|
|
789
|
+
var TriggerStateStore = class extends (_Context_Tag4 = Context4.Tag("@dxos/functions/TriggerStateStore")()) {
|
|
410
790
|
};
|
|
791
|
+
_define_property4(TriggerStateStore, "getState", Effect5.serviceFunctionEffect(TriggerStateStore, (_) => _.getState));
|
|
792
|
+
_define_property4(TriggerStateStore, "saveState", Effect5.serviceFunctionEffect(TriggerStateStore, (_) => _.saveState));
|
|
793
|
+
_define_property4(TriggerStateStore, "layerKv", Layer4.effect(TriggerStateStore, Effect5.gen(function* () {
|
|
794
|
+
const kv = yield* KeyValueStore.KeyValueStore;
|
|
795
|
+
const schemaStore = kv.forSchema(Schema6.parseJson(TriggerState));
|
|
796
|
+
const store = {
|
|
797
|
+
getState: Effect5.fn("TriggerStateStore.getState")(function* (triggerId) {
|
|
798
|
+
const valueOption = yield* schemaStore.get(triggerId).pipe(Effect5.orDie);
|
|
799
|
+
if (Option.isNone(valueOption)) {
|
|
800
|
+
return yield* Effect5.fail(new TriggerStateNotFoundError());
|
|
801
|
+
}
|
|
802
|
+
return valueOption.value;
|
|
803
|
+
}),
|
|
804
|
+
saveState: Effect5.fn("TriggerStateStore.saveState")(function* (state) {
|
|
805
|
+
yield* schemaStore.set(state.triggerId, state).pipe(Effect5.orDie);
|
|
806
|
+
})
|
|
807
|
+
};
|
|
808
|
+
return store;
|
|
809
|
+
})));
|
|
810
|
+
_define_property4(TriggerStateStore, "layerMemory", TriggerStateStore.layerKv.pipe(Layer4.provide(KeyValueStore.layerMemory)));
|
|
811
|
+
|
|
812
|
+
// src/triggers/trigger-dispatcher.ts
|
|
813
|
+
function _define_property5(obj, key, value) {
|
|
814
|
+
if (key in obj) {
|
|
815
|
+
Object.defineProperty(obj, key, {
|
|
816
|
+
value,
|
|
817
|
+
enumerable: true,
|
|
818
|
+
configurable: true,
|
|
819
|
+
writable: true
|
|
820
|
+
});
|
|
821
|
+
} else {
|
|
822
|
+
obj[key] = value;
|
|
823
|
+
}
|
|
824
|
+
return obj;
|
|
825
|
+
}
|
|
826
|
+
var __dxlog_file3 = "/__w/dxos/dxos/packages/core/functions/src/triggers/trigger-dispatcher.ts";
|
|
827
|
+
var _Context_Tag5;
|
|
828
|
+
var TriggerDispatcher = class extends (_Context_Tag5 = Context5.Tag("@dxos/functions/TriggerDispatcher")()) {
|
|
829
|
+
};
|
|
830
|
+
_define_property5(TriggerDispatcher, "layer", (options) => Layer5.effect(TriggerDispatcher, Effect6.gen(function* () {
|
|
831
|
+
return new TriggerDispatcherImpl(options);
|
|
832
|
+
})));
|
|
833
|
+
var TriggerDispatcherImpl = class {
|
|
834
|
+
get running() {
|
|
835
|
+
return this._running;
|
|
836
|
+
}
|
|
837
|
+
constructor(options) {
|
|
838
|
+
_define_property5(this, "livePollInterval", void 0);
|
|
839
|
+
_define_property5(this, "timeControl", void 0);
|
|
840
|
+
_define_property5(this, "_running", false);
|
|
841
|
+
_define_property5(this, "_internalTime", void 0);
|
|
842
|
+
_define_property5(this, "_timerFiber", void 0);
|
|
843
|
+
_define_property5(this, "_scheduledTriggers", /* @__PURE__ */ new Map());
|
|
844
|
+
_define_property5(this, "start", () => Effect6.gen(this, function* () {
|
|
845
|
+
if (this._running) {
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
this._running = true;
|
|
849
|
+
if (this.timeControl === "natural") {
|
|
850
|
+
this._timerFiber = yield* this._startNaturalTimeProcessing().pipe(Effect6.tapErrorCause((cause) => {
|
|
851
|
+
const error = causeToError(cause);
|
|
852
|
+
log3.error("trigger dispatcher error", {
|
|
853
|
+
error
|
|
854
|
+
}, {
|
|
855
|
+
F: __dxlog_file3,
|
|
856
|
+
L: 176,
|
|
857
|
+
S: this,
|
|
858
|
+
C: (f, a) => f(...a)
|
|
859
|
+
});
|
|
860
|
+
this._running = false;
|
|
861
|
+
return Effect6.void;
|
|
862
|
+
}), Effect6.forkDaemon);
|
|
863
|
+
} else {
|
|
864
|
+
return yield* Effect6.dieMessage("TriggerDispatcher started in manual time control mode");
|
|
865
|
+
}
|
|
866
|
+
log3.info("TriggerDispatcher started", {
|
|
867
|
+
timeControl: this.timeControl
|
|
868
|
+
}, {
|
|
869
|
+
F: __dxlog_file3,
|
|
870
|
+
L: 186,
|
|
871
|
+
S: this,
|
|
872
|
+
C: (f, a) => f(...a)
|
|
873
|
+
});
|
|
874
|
+
}));
|
|
875
|
+
_define_property5(this, "stop", () => Effect6.gen(this, function* () {
|
|
876
|
+
if (!this._running) {
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
this._running = false;
|
|
880
|
+
if (this._timerFiber) {
|
|
881
|
+
yield* Fiber.interrupt(this._timerFiber);
|
|
882
|
+
this._timerFiber = void 0;
|
|
883
|
+
}
|
|
884
|
+
this._scheduledTriggers.clear();
|
|
885
|
+
log3.info("TriggerDispatcher stopped", void 0, {
|
|
886
|
+
F: __dxlog_file3,
|
|
887
|
+
L: 206,
|
|
888
|
+
S: this,
|
|
889
|
+
C: (f, a) => f(...a)
|
|
890
|
+
});
|
|
891
|
+
}));
|
|
892
|
+
_define_property5(this, "invokeTrigger", (options2) => Effect6.gen(this, function* () {
|
|
893
|
+
const { trigger, event } = options2;
|
|
894
|
+
log3.info("running trigger", {
|
|
895
|
+
triggerId: trigger.id,
|
|
896
|
+
spec: trigger.spec,
|
|
897
|
+
event
|
|
898
|
+
}, {
|
|
899
|
+
F: __dxlog_file3,
|
|
900
|
+
L: 214,
|
|
901
|
+
S: this,
|
|
902
|
+
C: (f, a) => f(...a)
|
|
903
|
+
});
|
|
904
|
+
const tracer = yield* InvocationTracer;
|
|
905
|
+
const trace = yield* tracer.traceInvocationStart({
|
|
906
|
+
target: trigger.function?.dxn,
|
|
907
|
+
payload: {
|
|
908
|
+
trigger: {
|
|
909
|
+
id: trigger.id,
|
|
910
|
+
// TODO(dmaretskyi): Is `spec` always there>
|
|
911
|
+
kind: trigger.spec.kind
|
|
912
|
+
},
|
|
913
|
+
data: event
|
|
914
|
+
}
|
|
915
|
+
});
|
|
916
|
+
const result = yield* Effect6.gen(this, function* () {
|
|
917
|
+
if (!trigger.enabled) {
|
|
918
|
+
return yield* Effect6.dieMessage("Attempting to invoke disabled trigger");
|
|
919
|
+
}
|
|
920
|
+
if (!trigger.function) {
|
|
921
|
+
return yield* Effect6.dieMessage("Trigger has no function reference");
|
|
922
|
+
}
|
|
923
|
+
const serialiedFunction = yield* DatabaseService.load(trigger.function).pipe(Effect6.orDie);
|
|
924
|
+
invariant(Obj4.instanceOf(FunctionType, serialiedFunction), void 0, {
|
|
925
|
+
F: __dxlog_file3,
|
|
926
|
+
L: 241,
|
|
927
|
+
S: this,
|
|
928
|
+
A: [
|
|
929
|
+
"Obj.instanceOf(FunctionType, serialiedFunction)",
|
|
930
|
+
""
|
|
931
|
+
]
|
|
932
|
+
});
|
|
933
|
+
const functionDef = deserializeFunction(serialiedFunction);
|
|
934
|
+
const inputData = this._prepareInputData(trigger, event);
|
|
935
|
+
return yield* FunctionInvocationService.invokeFunction(functionDef, inputData).pipe(Effect6.provide(ComputeEventLogger.layerFromTracing.pipe(Layer5.provideMerge(TracingService.layerQueue(trace.invocationTraceQueue)))));
|
|
936
|
+
}).pipe(Effect6.exit);
|
|
937
|
+
const triggerExecutionResult = {
|
|
938
|
+
triggerId: trigger.id,
|
|
939
|
+
result
|
|
940
|
+
};
|
|
941
|
+
if (Exit.isSuccess(result)) {
|
|
942
|
+
log3.info("trigger execution success", {
|
|
943
|
+
triggerId: trigger.id
|
|
944
|
+
}, {
|
|
945
|
+
F: __dxlog_file3,
|
|
946
|
+
L: 262,
|
|
947
|
+
S: this,
|
|
948
|
+
C: (f, a) => f(...a)
|
|
949
|
+
});
|
|
950
|
+
} else {
|
|
951
|
+
log3.error("trigger execution failure", {
|
|
952
|
+
error: causeToError(result.cause)
|
|
953
|
+
}, {
|
|
954
|
+
F: __dxlog_file3,
|
|
955
|
+
L: 266,
|
|
956
|
+
S: this,
|
|
957
|
+
C: (f, a) => f(...a)
|
|
958
|
+
});
|
|
959
|
+
}
|
|
960
|
+
yield* tracer.traceInvocationEnd({
|
|
961
|
+
trace,
|
|
962
|
+
// TODO(dmaretskyi): Might miss errors.
|
|
963
|
+
exception: Exit.isFailure(result) ? Cause.prettyErrors(result.cause)[0] : void 0
|
|
964
|
+
});
|
|
965
|
+
return triggerExecutionResult;
|
|
966
|
+
}));
|
|
967
|
+
_define_property5(this, "invokeScheduledTriggers", ({ kinds = [
|
|
968
|
+
"timer",
|
|
969
|
+
"queue",
|
|
970
|
+
"subscription"
|
|
971
|
+
] } = {}) => Effect6.gen(this, function* () {
|
|
972
|
+
const invocations = [];
|
|
973
|
+
for (const kind of kinds) {
|
|
974
|
+
switch (kind) {
|
|
975
|
+
case "timer":
|
|
976
|
+
{
|
|
977
|
+
yield* this.refreshTriggers();
|
|
978
|
+
const now = this.getCurrentTime();
|
|
979
|
+
const triggersToInvoke = [];
|
|
980
|
+
for (const [triggerId, scheduledTrigger] of this._scheduledTriggers.entries()) {
|
|
981
|
+
if (scheduledTrigger.nextExecution <= now) {
|
|
982
|
+
triggersToInvoke.push(scheduledTrigger.trigger);
|
|
983
|
+
scheduledTrigger.nextExecution = Cron.next(scheduledTrigger.cron, now);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
invocations.push(...yield* Effect6.forEach(triggersToInvoke, (trigger) => this.invokeTrigger({
|
|
987
|
+
trigger,
|
|
988
|
+
event: {
|
|
989
|
+
tick: now.getTime()
|
|
990
|
+
}
|
|
991
|
+
}), {
|
|
992
|
+
concurrency: 1
|
|
993
|
+
}));
|
|
994
|
+
}
|
|
995
|
+
break;
|
|
996
|
+
case "queue": {
|
|
997
|
+
const triggers = yield* this._fetchTriggers();
|
|
998
|
+
for (const trigger of triggers) {
|
|
999
|
+
const spec = trigger.spec;
|
|
1000
|
+
if (spec?.kind !== "queue") {
|
|
1001
|
+
continue;
|
|
1002
|
+
}
|
|
1003
|
+
const cursor = Obj4.getKeys(trigger, KEY_QUEUE_CURSOR).at(0)?.id;
|
|
1004
|
+
const queue = yield* QueueService.getQueue(DXN3.parse(spec.queue));
|
|
1005
|
+
const objects = yield* Effect6.promise(() => queue.queryObjects());
|
|
1006
|
+
for (const object of objects) {
|
|
1007
|
+
const objectPos = Obj4.getKeys(object, KEY_QUEUE_POSITION).at(0)?.id;
|
|
1008
|
+
if (!objectPos || cursor && parseInt(cursor) >= parseInt(objectPos)) {
|
|
1009
|
+
continue;
|
|
1010
|
+
}
|
|
1011
|
+
invocations.push(yield* this.invokeTrigger({
|
|
1012
|
+
trigger,
|
|
1013
|
+
event: {
|
|
1014
|
+
queue: spec.queue,
|
|
1015
|
+
item: object,
|
|
1016
|
+
cursor: objectPos
|
|
1017
|
+
}
|
|
1018
|
+
}));
|
|
1019
|
+
Obj4.deleteKeys(trigger, KEY_QUEUE_CURSOR);
|
|
1020
|
+
Obj4.getMeta(trigger).keys.push({
|
|
1021
|
+
source: KEY_QUEUE_CURSOR,
|
|
1022
|
+
id: objectPos
|
|
1023
|
+
});
|
|
1024
|
+
yield* DatabaseService.flush();
|
|
1025
|
+
break;
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
break;
|
|
1029
|
+
}
|
|
1030
|
+
case "subscription": {
|
|
1031
|
+
const triggers = yield* this._fetchTriggers();
|
|
1032
|
+
for (const trigger of triggers) {
|
|
1033
|
+
const spec = Obj4.getSnapshot(trigger).spec;
|
|
1034
|
+
if (spec?.kind !== "subscription") {
|
|
1035
|
+
continue;
|
|
1036
|
+
}
|
|
1037
|
+
const { objects } = yield* DatabaseService.runQuery(Query.fromAst(spec.query));
|
|
1038
|
+
const state = yield* TriggerStateStore.getState(trigger.id).pipe(Effect6.catchTag("TRIGGER_STATE_NOT_FOUND", () => Effect6.succeed({
|
|
1039
|
+
version: "1",
|
|
1040
|
+
triggerId: trigger.id,
|
|
1041
|
+
state: {
|
|
1042
|
+
_tag: "subscription",
|
|
1043
|
+
processedVersions: {}
|
|
1044
|
+
}
|
|
1045
|
+
})));
|
|
1046
|
+
invariant(state.state?._tag === "subscription", void 0, {
|
|
1047
|
+
F: __dxlog_file3,
|
|
1048
|
+
L: 379,
|
|
1049
|
+
S: this,
|
|
1050
|
+
A: [
|
|
1051
|
+
"state.state?._tag === 'subscription'",
|
|
1052
|
+
""
|
|
1053
|
+
]
|
|
1054
|
+
});
|
|
1055
|
+
let updated = false;
|
|
1056
|
+
for (const object of objects) {
|
|
1057
|
+
const existingVersion = Record.get(state.state.processedVersions, object.id).pipe(Option2.map(Obj4.decodeVersion));
|
|
1058
|
+
const currentVersion = Obj4.version(object);
|
|
1059
|
+
const run = Option2.isNone(existingVersion) || Obj4.compareVersions(currentVersion, existingVersion.value) === "different";
|
|
1060
|
+
if (!run) {
|
|
1061
|
+
continue;
|
|
1062
|
+
}
|
|
1063
|
+
const { db } = yield* DatabaseService;
|
|
1064
|
+
invocations.push(yield* this.invokeTrigger({
|
|
1065
|
+
trigger,
|
|
1066
|
+
event: {
|
|
1067
|
+
// TODO(dmaretskyi): Change type not supported.
|
|
1068
|
+
type: "unknown",
|
|
1069
|
+
subject: db.ref(Obj4.getDXN(object)),
|
|
1070
|
+
changedObjectId: object.id
|
|
1071
|
+
}
|
|
1072
|
+
}));
|
|
1073
|
+
state.state.processedVersions[object.id] = Obj4.encodeVersion(currentVersion);
|
|
1074
|
+
updated = true;
|
|
1075
|
+
}
|
|
1076
|
+
if (updated) {
|
|
1077
|
+
yield* TriggerStateStore.saveState(state);
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
break;
|
|
1081
|
+
}
|
|
1082
|
+
default: {
|
|
1083
|
+
return yield* Effect6.dieMessage(`Unknown trigger kind: ${kind}`);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
return invocations;
|
|
1088
|
+
}));
|
|
1089
|
+
_define_property5(this, "advanceTime", (duration) => Effect6.gen(this, function* () {
|
|
1090
|
+
if (this.timeControl !== "manual") {
|
|
1091
|
+
return yield* Effect6.dieMessage("advanceTime can only be used in manual time control mode");
|
|
1092
|
+
}
|
|
1093
|
+
const millis = Duration.toMillis(duration);
|
|
1094
|
+
this._internalTime = new Date(this._internalTime.getTime() + millis);
|
|
1095
|
+
log3("Advanced internal time", {
|
|
1096
|
+
newTime: this._internalTime,
|
|
1097
|
+
advancedBy: Duration.format(duration)
|
|
1098
|
+
}, {
|
|
1099
|
+
F: __dxlog_file3,
|
|
1100
|
+
L: 436,
|
|
1101
|
+
S: this,
|
|
1102
|
+
C: (f, a) => f(...a)
|
|
1103
|
+
});
|
|
1104
|
+
}).pipe(Effect6.orDie));
|
|
1105
|
+
_define_property5(this, "getCurrentTime", () => {
|
|
1106
|
+
if (this.timeControl === "natural") {
|
|
1107
|
+
return /* @__PURE__ */ new Date();
|
|
1108
|
+
} else {
|
|
1109
|
+
return new Date(this._internalTime);
|
|
1110
|
+
}
|
|
1111
|
+
});
|
|
1112
|
+
_define_property5(this, "refreshTriggers", () => Effect6.gen(this, function* () {
|
|
1113
|
+
const triggers = yield* this._fetchTriggers();
|
|
1114
|
+
const currentTriggerIds = new Set(triggers.map((t) => t.id));
|
|
1115
|
+
for (const triggerId of this._scheduledTriggers.keys()) {
|
|
1116
|
+
if (!currentTriggerIds.has(triggerId)) {
|
|
1117
|
+
this._scheduledTriggers.delete(triggerId);
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
for (const trigger of triggers) {
|
|
1121
|
+
if (trigger.spec?.kind === "timer" && trigger.enabled) {
|
|
1122
|
+
const timerSpec = trigger.spec;
|
|
1123
|
+
const cronEither = Cron.parse(timerSpec.cron);
|
|
1124
|
+
if (Either.isRight(cronEither)) {
|
|
1125
|
+
const cron = cronEither.right;
|
|
1126
|
+
const existing = this._scheduledTriggers.get(trigger.id);
|
|
1127
|
+
const now = this.getCurrentTime();
|
|
1128
|
+
const nextExecution = existing?.nextExecution ?? Cron.next(cron, now);
|
|
1129
|
+
log3("Updated scheduled trigger", {
|
|
1130
|
+
triggerId: trigger.id,
|
|
1131
|
+
cron: timerSpec.cron,
|
|
1132
|
+
nextExecution,
|
|
1133
|
+
now
|
|
1134
|
+
}, {
|
|
1135
|
+
F: __dxlog_file3,
|
|
1136
|
+
L: 476,
|
|
1137
|
+
S: this,
|
|
1138
|
+
C: (f, a) => f(...a)
|
|
1139
|
+
});
|
|
1140
|
+
this._scheduledTriggers.set(trigger.id, {
|
|
1141
|
+
trigger,
|
|
1142
|
+
cron,
|
|
1143
|
+
nextExecution
|
|
1144
|
+
});
|
|
1145
|
+
} else {
|
|
1146
|
+
log3.error("Invalid cron expression", {
|
|
1147
|
+
triggerId: trigger.id,
|
|
1148
|
+
cron: timerSpec.cron,
|
|
1149
|
+
error: cronEither.left.message
|
|
1150
|
+
}, {
|
|
1151
|
+
F: __dxlog_file3,
|
|
1152
|
+
L: 488,
|
|
1153
|
+
S: this,
|
|
1154
|
+
C: (f, a) => f(...a)
|
|
1155
|
+
});
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
log3("Updated scheduled triggers", {
|
|
1160
|
+
count: this._scheduledTriggers.size
|
|
1161
|
+
}, {
|
|
1162
|
+
F: __dxlog_file3,
|
|
1163
|
+
L: 497,
|
|
1164
|
+
S: this,
|
|
1165
|
+
C: (f, a) => f(...a)
|
|
1166
|
+
});
|
|
1167
|
+
}).pipe(Effect6.withSpan("TriggerDispatcher.refreshTriggers")));
|
|
1168
|
+
_define_property5(this, "_fetchTriggers", () => Effect6.gen(this, function* () {
|
|
1169
|
+
const { objects } = yield* DatabaseService.runQuery(Filter.type(FunctionTrigger));
|
|
1170
|
+
return objects;
|
|
1171
|
+
}).pipe(Effect6.withSpan("TriggerDispatcher.fetchTriggers")));
|
|
1172
|
+
_define_property5(this, "_startNaturalTimeProcessing", () => Effect6.gen(this, function* () {
|
|
1173
|
+
yield* this.invokeScheduledTriggers();
|
|
1174
|
+
}).pipe(Effect6.repeat(Schedule.fixed(this.livePollInterval)), Effect6.asVoid));
|
|
1175
|
+
_define_property5(this, "_prepareInputData", (trigger, event) => {
|
|
1176
|
+
return createInvocationPayload(trigger, event);
|
|
1177
|
+
});
|
|
1178
|
+
this.timeControl = options.timeControl;
|
|
1179
|
+
this.livePollInterval = options.livePollInterval ?? Duration.seconds(1);
|
|
1180
|
+
this._internalTime = options.startingTime ?? /* @__PURE__ */ new Date();
|
|
1181
|
+
}
|
|
1182
|
+
};
|
|
1183
|
+
var KEY_QUEUE_CURSOR = "dxos.org/key/local-trigger-dispatcher/queue-cursor";
|
|
411
1184
|
|
|
412
1185
|
// src/executor/executor.ts
|
|
413
|
-
import { Effect, Schema as
|
|
1186
|
+
import { Effect as Effect7, Schema as Schema7 } from "effect";
|
|
414
1187
|
import { runAndForwardErrors } from "@dxos/effect";
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
1188
|
+
function _define_property6(obj, key, value) {
|
|
1189
|
+
if (key in obj) {
|
|
1190
|
+
Object.defineProperty(obj, key, {
|
|
1191
|
+
value,
|
|
1192
|
+
enumerable: true,
|
|
1193
|
+
configurable: true,
|
|
1194
|
+
writable: true
|
|
1195
|
+
});
|
|
1196
|
+
} else {
|
|
1197
|
+
obj[key] = value;
|
|
418
1198
|
}
|
|
1199
|
+
return obj;
|
|
1200
|
+
}
|
|
1201
|
+
var FunctionExecutor = class {
|
|
1202
|
+
/**
|
|
1203
|
+
* Invoke function.
|
|
1204
|
+
*/
|
|
419
1205
|
// TODO(dmaretskyi): Invocation context: queue, space, etc...
|
|
420
|
-
async invoke(
|
|
421
|
-
const assertInput =
|
|
1206
|
+
async invoke(functionDef, input) {
|
|
1207
|
+
const assertInput = functionDef.inputSchema.pipe(Schema7.asserts);
|
|
422
1208
|
assertInput(input);
|
|
423
1209
|
const context = {
|
|
1210
|
+
space: void 0,
|
|
424
1211
|
getService: this._services.getService.bind(this._services),
|
|
425
1212
|
getSpace: async (_spaceId) => {
|
|
426
1213
|
throw new Error("Not available. Use the database service instead.");
|
|
427
|
-
},
|
|
428
|
-
space: void 0,
|
|
429
|
-
get ai() {
|
|
430
|
-
throw new Error("Not available. Use the ai service instead.");
|
|
431
1214
|
}
|
|
432
1215
|
};
|
|
433
|
-
const result =
|
|
1216
|
+
const result = functionDef.handler({
|
|
434
1217
|
context,
|
|
435
1218
|
data: input
|
|
436
1219
|
});
|
|
437
1220
|
let data;
|
|
438
|
-
if (
|
|
439
|
-
data = await result.pipe(
|
|
1221
|
+
if (Effect7.isEffect(result)) {
|
|
1222
|
+
data = await result.pipe(Effect7.provide(this._services.createLayer()), runAndForwardErrors);
|
|
440
1223
|
} else {
|
|
441
1224
|
data = await result;
|
|
442
1225
|
}
|
|
443
|
-
const assertOutput =
|
|
1226
|
+
const assertOutput = functionDef.outputSchema?.pipe(Schema7.asserts);
|
|
444
1227
|
assertOutput(data);
|
|
445
1228
|
return data;
|
|
446
1229
|
}
|
|
1230
|
+
constructor(_services) {
|
|
1231
|
+
_define_property6(this, "_services", void 0);
|
|
1232
|
+
this._services = _services;
|
|
1233
|
+
}
|
|
447
1234
|
};
|
|
1235
|
+
|
|
1236
|
+
// src/examples/index.ts
|
|
1237
|
+
var examples_exports = {};
|
|
1238
|
+
__export(examples_exports, {
|
|
1239
|
+
fib: () => fib_default,
|
|
1240
|
+
reply: () => reply_default,
|
|
1241
|
+
sleep: () => sleep_default
|
|
1242
|
+
});
|
|
1243
|
+
|
|
1244
|
+
// src/examples/fib.ts
|
|
1245
|
+
import { Effect as Effect8, Schema as Schema8 } from "effect";
|
|
1246
|
+
var fib_default = defineFunction({
|
|
1247
|
+
key: "example.org/function/fib",
|
|
1248
|
+
name: "Fibonacci",
|
|
1249
|
+
description: "Function that calculates a Fibonacci number",
|
|
1250
|
+
inputSchema: Schema8.Struct({
|
|
1251
|
+
iterations: Schema8.optional(Schema8.Number).annotations({
|
|
1252
|
+
description: "Number of iterations",
|
|
1253
|
+
default: 1e5
|
|
1254
|
+
})
|
|
1255
|
+
}),
|
|
1256
|
+
outputSchema: Schema8.Struct({
|
|
1257
|
+
result: Schema8.String
|
|
1258
|
+
}),
|
|
1259
|
+
handler: Effect8.fn(function* ({ data: { iterations = 1e5 } }) {
|
|
1260
|
+
let a = 0n;
|
|
1261
|
+
let b = 1n;
|
|
1262
|
+
for (let i = 0; i < iterations; i++) {
|
|
1263
|
+
a += b;
|
|
1264
|
+
b = a - b;
|
|
1265
|
+
}
|
|
1266
|
+
return {
|
|
1267
|
+
result: a.toString()
|
|
1268
|
+
};
|
|
1269
|
+
})
|
|
1270
|
+
});
|
|
1271
|
+
|
|
1272
|
+
// src/examples/reply.ts
|
|
1273
|
+
import { Console, Effect as Effect9, Schema as Schema9 } from "effect";
|
|
1274
|
+
var reply_default = defineFunction({
|
|
1275
|
+
key: "example.org/function/reply",
|
|
1276
|
+
name: "Reply",
|
|
1277
|
+
description: "Function that echoes the input",
|
|
1278
|
+
inputSchema: Schema9.Any,
|
|
1279
|
+
outputSchema: Schema9.Any,
|
|
1280
|
+
handler: Effect9.fn(function* ({ data }) {
|
|
1281
|
+
yield* Console.log("reply", {
|
|
1282
|
+
data
|
|
1283
|
+
});
|
|
1284
|
+
return data;
|
|
1285
|
+
})
|
|
1286
|
+
});
|
|
1287
|
+
|
|
1288
|
+
// src/examples/sleep.ts
|
|
1289
|
+
import { Effect as Effect10, Schema as Schema10 } from "effect";
|
|
1290
|
+
var sleep_default = defineFunction({
|
|
1291
|
+
key: "example.org/function/sleep",
|
|
1292
|
+
name: "Sleep",
|
|
1293
|
+
description: "Function that sleeps for a given amount of time",
|
|
1294
|
+
inputSchema: Schema10.Struct({
|
|
1295
|
+
duration: Schema10.optional(Schema10.Number).annotations({
|
|
1296
|
+
description: "Milliseconds to sleep",
|
|
1297
|
+
default: 1e5
|
|
1298
|
+
})
|
|
1299
|
+
}),
|
|
1300
|
+
outputSchema: Schema10.Void,
|
|
1301
|
+
handler: Effect10.fn(function* ({ data: { duration = 1e5 } }) {
|
|
1302
|
+
yield* Effect10.sleep(duration);
|
|
1303
|
+
})
|
|
1304
|
+
});
|
|
448
1305
|
export {
|
|
449
|
-
|
|
1306
|
+
ComputeEvent,
|
|
1307
|
+
ComputeEventLogger,
|
|
1308
|
+
ComputeEventPayload,
|
|
450
1309
|
ConfiguredCredentialsService,
|
|
1310
|
+
ContextQueueService,
|
|
451
1311
|
CredentialsService,
|
|
452
1312
|
DatabaseService,
|
|
453
1313
|
EmailTriggerOutput,
|
|
454
|
-
|
|
1314
|
+
FUNCTIONS_META_KEY,
|
|
455
1315
|
FUNCTIONS_PRESET_META_KEY,
|
|
456
1316
|
FUNCTION_TYPES,
|
|
457
|
-
|
|
1317
|
+
FunctionDefinition,
|
|
1318
|
+
FunctionError,
|
|
458
1319
|
FunctionExecutor,
|
|
1320
|
+
FunctionImplementationResolver,
|
|
1321
|
+
FunctionInvocationService,
|
|
459
1322
|
FunctionManifestSchema,
|
|
1323
|
+
FunctionNotFoundError,
|
|
460
1324
|
FunctionTrigger,
|
|
461
|
-
FunctionTriggerSchema,
|
|
462
1325
|
FunctionType,
|
|
463
1326
|
InvocationOutcome,
|
|
464
1327
|
InvocationTraceEndEvent,
|
|
465
1328
|
InvocationTraceEventType,
|
|
466
1329
|
InvocationTraceStartEvent,
|
|
1330
|
+
InvocationTracer,
|
|
1331
|
+
LocalFunctionExecutionService,
|
|
1332
|
+
MESSAGE_PROPERTY_TOOL_CALL_ID,
|
|
467
1333
|
QueueService,
|
|
468
1334
|
QueueTriggerOutput,
|
|
1335
|
+
RemoteFunctionExecutionService,
|
|
469
1336
|
SERVICE_TAGS,
|
|
470
1337
|
ScriptType,
|
|
471
1338
|
ServiceContainer,
|
|
1339
|
+
ServiceNotAvailableError,
|
|
472
1340
|
SubscriptionTriggerOutput,
|
|
473
1341
|
TimerTriggerOutput,
|
|
474
|
-
ToolResolverService,
|
|
475
1342
|
TraceEvent,
|
|
476
1343
|
TraceEventException,
|
|
477
1344
|
TraceEventLog,
|
|
478
1345
|
TracingService,
|
|
479
|
-
|
|
1346
|
+
TriggerDispatcher,
|
|
1347
|
+
TriggerKinds,
|
|
480
1348
|
TriggerSchema,
|
|
1349
|
+
TriggerState,
|
|
1350
|
+
TriggerStateNotFoundError,
|
|
1351
|
+
TriggerStateStore,
|
|
481
1352
|
WebhookTriggerOutput,
|
|
482
1353
|
createDefectLogger,
|
|
483
1354
|
createEventLogger,
|
|
484
1355
|
createInvocationSpans,
|
|
485
1356
|
defineFunction,
|
|
1357
|
+
deserializeFunction,
|
|
1358
|
+
examples_exports as exampleFunctions,
|
|
486
1359
|
getInvocationUrl,
|
|
487
|
-
|
|
1360
|
+
getUserFunctionIdInMetadata,
|
|
488
1361
|
logCustomEvent,
|
|
489
|
-
|
|
490
|
-
|
|
1362
|
+
serializeFunction,
|
|
1363
|
+
setUserFunctionIdInMetadata,
|
|
1364
|
+
withAuthorization
|
|
491
1365
|
};
|
|
492
1366
|
//# sourceMappingURL=index.mjs.map
|