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