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