@dxos/functions 0.5.3-main.79e0565 → 0.5.3-main.7cd4303
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/index.mjs +238 -285
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +240 -285
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/{function → registry}/function-registry.d.ts +4 -4
- package/dist/types/src/registry/function-registry.d.ts.map +1 -0
- package/dist/types/src/registry/function-registry.test.d.ts.map +1 -0
- package/dist/types/src/registry/index.d.ts.map +1 -0
- package/dist/types/src/runtime/dev-server.d.ts +1 -1
- package/dist/types/src/runtime/dev-server.d.ts.map +1 -1
- package/dist/types/src/runtime/scheduler.d.ts +1 -2
- package/dist/types/src/runtime/scheduler.d.ts.map +1 -1
- package/dist/types/src/trigger/trigger-registry.d.ts.map +1 -1
- package/dist/types/src/trigger/type/subscription-trigger.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +19 -33
- package/dist/types/src/types.d.ts.map +1 -1
- package/package.json +16 -15
- package/schema/functions.json +9 -18
- package/src/index.ts +1 -1
- package/src/{function → registry}/function-registry.test.ts +10 -10
- package/src/registry/function-registry.ts +84 -0
- package/src/runtime/dev-server.test.ts +2 -2
- package/src/runtime/dev-server.ts +5 -4
- package/src/runtime/scheduler.test.ts +1 -1
- package/src/runtime/scheduler.ts +8 -16
- package/src/testing/functions-integration.test.ts +1 -1
- package/src/testing/setup.ts +1 -1
- package/src/trigger/trigger-registry.test.ts +34 -60
- package/src/trigger/trigger-registry.ts +6 -19
- package/src/trigger/type/subscription-trigger.ts +10 -17
- package/src/types.ts +10 -12
- package/dist/types/src/function/function-registry.d.ts.map +0 -1
- package/dist/types/src/function/function-registry.test.d.ts.map +0 -1
- package/dist/types/src/function/index.d.ts.map +0 -1
- package/dist/types/src/util.d.ts +0 -15
- package/dist/types/src/util.d.ts.map +0 -1
- package/dist/types/src/util.test.d.ts +0 -2
- package/dist/types/src/util.test.d.ts.map +0 -1
- package/src/function/function-registry.ts +0 -90
- package/src/util.test.ts +0 -43
- package/src/util.ts +0 -48
- /package/dist/types/src/{function → registry}/function-registry.test.d.ts +0 -0
- /package/dist/types/src/{function → registry}/index.d.ts +0 -0
- /package/src/{function → registry}/index.ts +0 -0
|
@@ -62,7 +62,9 @@ export declare class FunctionDef extends FunctionDef_base {
|
|
|
62
62
|
}
|
|
63
63
|
declare const FunctionTrigger_base: import("@dxos/echo-schema").EchoSchemaClass<{
|
|
64
64
|
function: string;
|
|
65
|
-
meta?:
|
|
65
|
+
meta?: {
|
|
66
|
+
readonly [x: string]: any;
|
|
67
|
+
} | undefined;
|
|
66
68
|
spec: {
|
|
67
69
|
readonly filter: readonly {
|
|
68
70
|
readonly type: string;
|
|
@@ -98,34 +100,26 @@ export declare class FunctionTrigger extends FunctionTrigger_base {
|
|
|
98
100
|
* Function manifest file.
|
|
99
101
|
*/
|
|
100
102
|
export declare const FunctionManifestSchema: S.struct<{
|
|
101
|
-
functions: S.PropertySignature<"?:",
|
|
103
|
+
functions: S.PropertySignature<"?:", Omit<{
|
|
102
104
|
handler: string;
|
|
103
105
|
uri: string;
|
|
104
106
|
description?: string | undefined;
|
|
105
107
|
route: string;
|
|
106
108
|
} & {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
readonly id: string;
|
|
110
|
-
readonly source: string;
|
|
111
|
-
}[];
|
|
112
|
-
} | undefined;
|
|
113
|
-
})[] | undefined, never, "?:", ({
|
|
109
|
+
id: string;
|
|
110
|
+
}, "id">[] | undefined, never, "?:", Omit<{
|
|
114
111
|
handler: string;
|
|
115
112
|
uri: string;
|
|
116
113
|
description?: string | undefined;
|
|
117
114
|
route: string;
|
|
118
115
|
} & {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
readonly source: string;
|
|
123
|
-
}[];
|
|
124
|
-
} | undefined;
|
|
125
|
-
})[] | undefined, never>;
|
|
126
|
-
triggers: S.PropertySignature<"?:", ({
|
|
116
|
+
id: string;
|
|
117
|
+
}, "id">[] | undefined, never>;
|
|
118
|
+
triggers: S.PropertySignature<"?:", Omit<{
|
|
127
119
|
function: string;
|
|
128
|
-
meta?:
|
|
120
|
+
meta?: {
|
|
121
|
+
readonly [x: string]: any;
|
|
122
|
+
} | undefined;
|
|
129
123
|
spec: {
|
|
130
124
|
readonly filter: readonly {
|
|
131
125
|
readonly type: string;
|
|
@@ -153,15 +147,12 @@ export declare const FunctionManifestSchema: S.struct<{
|
|
|
153
147
|
} | undefined;
|
|
154
148
|
};
|
|
155
149
|
} & {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
readonly id: string;
|
|
159
|
-
readonly source: string;
|
|
160
|
-
}[];
|
|
161
|
-
} | undefined;
|
|
162
|
-
})[] | undefined, never, "?:", ({
|
|
150
|
+
id: string;
|
|
151
|
+
}, "id">[] | undefined, never, "?:", Omit<{
|
|
163
152
|
function: string;
|
|
164
|
-
meta?:
|
|
153
|
+
meta?: {
|
|
154
|
+
readonly [x: string]: any;
|
|
155
|
+
} | undefined;
|
|
165
156
|
spec: {
|
|
166
157
|
readonly filter: readonly {
|
|
167
158
|
readonly type: string;
|
|
@@ -189,13 +180,8 @@ export declare const FunctionManifestSchema: S.struct<{
|
|
|
189
180
|
} | undefined;
|
|
190
181
|
};
|
|
191
182
|
} & {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
readonly id: string;
|
|
195
|
-
readonly source: string;
|
|
196
|
-
}[];
|
|
197
|
-
} | undefined;
|
|
198
|
-
})[] | undefined, never>;
|
|
183
|
+
id: string;
|
|
184
|
+
}, "id">[] | undefined, never>;
|
|
199
185
|
}>;
|
|
200
186
|
export type FunctionManifest = S.Schema.Type<typeof FunctionManifestSchema>;
|
|
201
187
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAIA,OAAO,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAIA,OAAO,EAAO,CAAC,EAAe,MAAM,mBAAmB,CAAC;AAKxD;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,CAAC;AAErF,QAAA,MAAM,yBAAyB;;;;;;;;;;;;;;;;;EAiB7B,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAElF,QAAA,MAAM,kBAAkB;;;EAGtB,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,QAAA,MAAM,oBAAoB;;;;GAOzB,CAAC;AACF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE,QAAA,MAAM,sBAAsB;;;;;;;;EAI1B,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAQ5E,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,cAAc,GAAG,gBAAgB,GAAG,mBAAmB,CAAC;;;;;;;;;AAEjG;;GAEG;AACH,qBAAa,WAAY,SAAQ,gBAS/B;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEL,qBAAa,eAAgB,SAAQ,oBAQnC;CAAG;AAEL;;GAEG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/functions",
|
|
3
|
-
"version": "0.5.3-main.
|
|
3
|
+
"version": "0.5.3-main.7cd4303",
|
|
4
4
|
"description": "Functions SDK and runtime.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -26,28 +26,29 @@
|
|
|
26
26
|
"express": "^4.19.2",
|
|
27
27
|
"get-port-please": "^3.1.1",
|
|
28
28
|
"ws": "^8.14.2",
|
|
29
|
-
"@braneframe/types": "0.5.3-main.
|
|
30
|
-
"@dxos/async": "0.5.3-main.
|
|
31
|
-
"@dxos/
|
|
32
|
-
"@dxos/
|
|
33
|
-
"@dxos/
|
|
34
|
-
"@dxos/
|
|
35
|
-
"@dxos/
|
|
36
|
-
"@dxos/keys": "0.5.3-main.
|
|
37
|
-
"@dxos/node-std": "0.5.3-main.
|
|
38
|
-
"@dxos/
|
|
39
|
-
"@dxos/protocols": "0.5.3-main.
|
|
40
|
-
"@dxos/
|
|
29
|
+
"@braneframe/types": "0.5.3-main.7cd4303",
|
|
30
|
+
"@dxos/async": "0.5.3-main.7cd4303",
|
|
31
|
+
"@dxos/context": "0.5.3-main.7cd4303",
|
|
32
|
+
"@dxos/echo-db": "0.5.3-main.7cd4303",
|
|
33
|
+
"@dxos/client": "0.5.3-main.7cd4303",
|
|
34
|
+
"@dxos/echo-schema": "0.5.3-main.7cd4303",
|
|
35
|
+
"@dxos/invariant": "0.5.3-main.7cd4303",
|
|
36
|
+
"@dxos/keys": "0.5.3-main.7cd4303",
|
|
37
|
+
"@dxos/node-std": "0.5.3-main.7cd4303",
|
|
38
|
+
"@dxos/log": "0.5.3-main.7cd4303",
|
|
39
|
+
"@dxos/protocols": "0.5.3-main.7cd4303",
|
|
40
|
+
"@dxos/util": "0.5.3-main.7cd4303"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/express": "^4.17.17",
|
|
44
44
|
"@types/ws": "^7.4.0",
|
|
45
|
-
"@dxos/agent": "0.5.3-main.
|
|
45
|
+
"@dxos/agent": "0.5.3-main.7cd4303"
|
|
46
46
|
},
|
|
47
47
|
"publishConfig": {
|
|
48
48
|
"access": "public"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
|
-
"gen-schema": "ts-node ./tools/schema.ts"
|
|
51
|
+
"gen-schema": "ts-node ./tools/schema.ts",
|
|
52
|
+
"prebuild": "pnpm gen-schema"
|
|
52
53
|
}
|
|
53
54
|
}
|
package/schema/functions.json
CHANGED
|
@@ -48,11 +48,17 @@
|
|
|
48
48
|
"properties": {
|
|
49
49
|
"function": {
|
|
50
50
|
"type": "string",
|
|
51
|
-
"description": "Function URI.",
|
|
51
|
+
"description": "Function ID/URI.",
|
|
52
52
|
"title": "string"
|
|
53
53
|
},
|
|
54
54
|
"meta": {
|
|
55
|
-
"
|
|
55
|
+
"type": "object",
|
|
56
|
+
"required": [],
|
|
57
|
+
"properties": {},
|
|
58
|
+
"additionalProperties": {
|
|
59
|
+
"$id": "/schemas/any",
|
|
60
|
+
"title": "any"
|
|
61
|
+
}
|
|
56
62
|
},
|
|
57
63
|
"spec": {
|
|
58
64
|
"anyOf": [
|
|
@@ -187,20 +193,5 @@
|
|
|
187
193
|
}
|
|
188
194
|
}
|
|
189
195
|
},
|
|
190
|
-
"additionalProperties": false
|
|
191
|
-
"$defs": {
|
|
192
|
-
"object": {
|
|
193
|
-
"$id": "/schemas/object",
|
|
194
|
-
"oneOf": [
|
|
195
|
-
{
|
|
196
|
-
"type": "object"
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
"type": "array"
|
|
200
|
-
}
|
|
201
|
-
],
|
|
202
|
-
"description": "an object in the TypeScript meaning, i.e. the `object` type",
|
|
203
|
-
"title": "object"
|
|
204
|
-
}
|
|
205
|
-
}
|
|
196
|
+
"additionalProperties": false
|
|
206
197
|
}
|
package/src/index.ts
CHANGED
|
@@ -44,7 +44,7 @@ describe('function registry', () => {
|
|
|
44
44
|
const client = (await createInitializedClients(testBuilder))[0];
|
|
45
45
|
const registry = createRegistry(client);
|
|
46
46
|
const space = await client.spaces.create();
|
|
47
|
-
await registry.register(space, testManifest
|
|
47
|
+
await registry.register(space, testManifest);
|
|
48
48
|
const { objects: definitions } = await space.db.query(Filter.schema(FunctionDef)).run();
|
|
49
49
|
expect(definitions.length).to.eq(1);
|
|
50
50
|
expect(definitions[0].uri).to.eq(testManifest.functions?.[0]?.uri);
|
|
@@ -54,8 +54,8 @@ describe('function registry', () => {
|
|
|
54
54
|
const client = (await createInitializedClients(testBuilder))[0];
|
|
55
55
|
const registry = createRegistry(client);
|
|
56
56
|
const space = await client.spaces.create();
|
|
57
|
-
const existing = space.db.add(create(FunctionDef, testManifest.functions![0]));
|
|
58
|
-
await registry.register(space, testManifest
|
|
57
|
+
const existing = space.db.add(create(FunctionDef, { ...testManifest.functions![0] }));
|
|
58
|
+
await registry.register(space, testManifest);
|
|
59
59
|
const { objects: definitions } = await space.db.query(Filter.schema(FunctionDef)).run();
|
|
60
60
|
expect(definitions.length).to.eq(1);
|
|
61
61
|
expect(definitions[0].uri).to.eq(existing.uri);
|
|
@@ -67,12 +67,12 @@ describe('function registry', () => {
|
|
|
67
67
|
const client = (await createInitializedClients(testBuilder))[0];
|
|
68
68
|
const registry = createRegistry(client);
|
|
69
69
|
const space = await client.spaces.create();
|
|
70
|
-
const definitions = range(3, () => create(FunctionDef, testManifest.functions![0]));
|
|
70
|
+
const definitions = range(3, () => create(FunctionDef, { ...testManifest.functions![0] }));
|
|
71
71
|
definitions.forEach((def) => space.db.add(def));
|
|
72
72
|
|
|
73
73
|
const functionRegistered = new Trigger<FunctionDef[]>();
|
|
74
|
-
registry.
|
|
75
|
-
functionRegistered.wake(fn.
|
|
74
|
+
registry.onFunctionsRegistered.on((fn) => {
|
|
75
|
+
functionRegistered.wake(fn.newFunctions);
|
|
76
76
|
});
|
|
77
77
|
void registry.open(ctx);
|
|
78
78
|
const functions = await functionRegistered.wait();
|
|
@@ -86,12 +86,12 @@ describe('function registry', () => {
|
|
|
86
86
|
const space = await client.spaces.create();
|
|
87
87
|
|
|
88
88
|
const functionRegistered = new Trigger<FunctionDef>();
|
|
89
|
-
registry.
|
|
90
|
-
expect(fn.
|
|
91
|
-
functionRegistered.wake(fn.
|
|
89
|
+
registry.onFunctionsRegistered.on((fn) => {
|
|
90
|
+
expect(fn.newFunctions.length).to.eq(1);
|
|
91
|
+
functionRegistered.wake(fn.newFunctions[0]);
|
|
92
92
|
});
|
|
93
93
|
await registry.open(ctx);
|
|
94
|
-
await registry.register(space, testManifest
|
|
94
|
+
await registry.register(space, testManifest);
|
|
95
95
|
const registered = await functionRegistered.wait();
|
|
96
96
|
expect(registered.uri).to.eq(testManifest.functions![0].uri);
|
|
97
97
|
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Event } from '@dxos/async';
|
|
6
|
+
import { type Client } from '@dxos/client';
|
|
7
|
+
import { create, Filter, type Space } from '@dxos/client/echo';
|
|
8
|
+
import { type Context, Resource } from '@dxos/context';
|
|
9
|
+
import { PublicKey } from '@dxos/keys';
|
|
10
|
+
import { ComplexMap } from '@dxos/util';
|
|
11
|
+
|
|
12
|
+
import { FunctionDef, type FunctionManifest } from '../types';
|
|
13
|
+
|
|
14
|
+
export type FunctionsRegisteredEvent = {
|
|
15
|
+
space: Space;
|
|
16
|
+
newFunctions: FunctionDef[];
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export class FunctionRegistry extends Resource {
|
|
20
|
+
private readonly _functionBySpaceKey = new ComplexMap<PublicKey, FunctionDef[]>(PublicKey.hash);
|
|
21
|
+
|
|
22
|
+
public readonly onFunctionsRegistered = new Event<FunctionsRegisteredEvent>();
|
|
23
|
+
|
|
24
|
+
constructor(private readonly _client: Client) {
|
|
25
|
+
super();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public getFunctions(space: Space): FunctionDef[] {
|
|
29
|
+
return this._functionBySpaceKey.get(space.key) ?? [];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The method loads function definitions from the manifest into the space.
|
|
34
|
+
* We first load all the definitions from the space to deduplicate by functionId.
|
|
35
|
+
*/
|
|
36
|
+
// TODO(burdon): This should not be space specific (they are static for the agent).
|
|
37
|
+
public async register(space: Space, manifest: FunctionManifest): Promise<void> {
|
|
38
|
+
if (!manifest.functions?.length) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (!space.db.graph.runtimeSchemaRegistry.isSchemaRegistered(FunctionDef)) {
|
|
42
|
+
space.db.graph.runtimeSchemaRegistry.registerSchema(FunctionDef);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const { objects: existingDefinitions } = await space.db.query(Filter.schema(FunctionDef)).run();
|
|
46
|
+
const newDefinitions = getNewDefinitions(manifest.functions, existingDefinitions);
|
|
47
|
+
const reactiveObjects = newDefinitions.map((template) => create(FunctionDef, { ...template }));
|
|
48
|
+
reactiveObjects.forEach((obj) => space.db.add(obj));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
protected override async _open(): Promise<void> {
|
|
52
|
+
const spaceListSubscription = this._client.spaces.subscribe(async (spaces) => {
|
|
53
|
+
for (const space of spaces) {
|
|
54
|
+
if (this._functionBySpaceKey.has(space.key)) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const registered: FunctionDef[] = [];
|
|
58
|
+
this._functionBySpaceKey.set(space.key, registered);
|
|
59
|
+
await space.waitUntilReady();
|
|
60
|
+
if (this._ctx.disposed) {
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const functionsSubscription = space.db.query(Filter.schema(FunctionDef)).subscribe((definitions) => {
|
|
65
|
+
const newFunctions = getNewDefinitions(definitions.objects, registered);
|
|
66
|
+
if (newFunctions.length > 0) {
|
|
67
|
+
registered.push(...newFunctions);
|
|
68
|
+
this.onFunctionsRegistered.emit({ space, newFunctions });
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
this._ctx.onDispose(functionsSubscription);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
this._ctx.onDispose(() => spaceListSubscription.unsubscribe());
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
protected override async _close(_: Context): Promise<void> {
|
|
78
|
+
this._functionBySpaceKey.clear();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const getNewDefinitions = <T extends { uri: string }>(candidateList: T[], existing: FunctionDef[]): T[] => {
|
|
83
|
+
return candidateList.filter((candidate) => existing.find((def) => def.uri === candidate.uri) == null);
|
|
84
|
+
};
|
|
@@ -11,7 +11,7 @@ import { TestBuilder } from '@dxos/client/testing';
|
|
|
11
11
|
import { describe, test } from '@dxos/test';
|
|
12
12
|
|
|
13
13
|
import { DevServer } from './dev-server';
|
|
14
|
-
import { FunctionRegistry } from '../
|
|
14
|
+
import { FunctionRegistry } from '../registry';
|
|
15
15
|
import { createFunctionRuntime } from '../testing';
|
|
16
16
|
import { type FunctionManifest } from '../types';
|
|
17
17
|
|
|
@@ -44,7 +44,7 @@ describe('dev server', () => {
|
|
|
44
44
|
baseDir: path.join(__dirname, '../testing'),
|
|
45
45
|
});
|
|
46
46
|
const space = await client.spaces.create();
|
|
47
|
-
await registry.register(space, manifest
|
|
47
|
+
await registry.register(space, manifest);
|
|
48
48
|
await server.start();
|
|
49
49
|
|
|
50
50
|
// TODO(burdon): Doesn't shut down cleanly.
|
|
@@ -13,8 +13,8 @@ import { Context } from '@dxos/context';
|
|
|
13
13
|
import { invariant } from '@dxos/invariant';
|
|
14
14
|
import { log } from '@dxos/log';
|
|
15
15
|
|
|
16
|
-
import { type FunctionRegistry } from '../function';
|
|
17
16
|
import { type FunctionContext, type FunctionEvent, type FunctionHandler, type FunctionResponse } from '../handler';
|
|
17
|
+
import { type FunctionRegistry } from '../registry';
|
|
18
18
|
import { type FunctionDef } from '../types';
|
|
19
19
|
|
|
20
20
|
export type DevServerOptions = {
|
|
@@ -41,15 +41,16 @@ export class DevServer {
|
|
|
41
41
|
|
|
42
42
|
public readonly update = new Event<number>();
|
|
43
43
|
|
|
44
|
+
// prettier-ignore
|
|
44
45
|
constructor(
|
|
45
46
|
private readonly _client: Client,
|
|
46
47
|
private readonly _functionsRegistry: FunctionRegistry,
|
|
47
48
|
private readonly _options: DevServerOptions,
|
|
48
49
|
) {
|
|
49
|
-
this._functionsRegistry.
|
|
50
|
-
|
|
50
|
+
this._functionsRegistry.onFunctionsRegistered.on(async ({ newFunctions }) => {
|
|
51
|
+
newFunctions.forEach((def) => this._load(def));
|
|
51
52
|
await this._safeUpdateRegistration();
|
|
52
|
-
log('new functions loaded', {
|
|
53
|
+
log('new functions loaded', { newFunctions });
|
|
53
54
|
});
|
|
54
55
|
}
|
|
55
56
|
|
|
@@ -12,7 +12,7 @@ import { create } from '@dxos/echo-schema';
|
|
|
12
12
|
import { describe, test } from '@dxos/test';
|
|
13
13
|
|
|
14
14
|
import { Scheduler, type SchedulerOptions } from './scheduler';
|
|
15
|
-
import { FunctionRegistry } from '../
|
|
15
|
+
import { FunctionRegistry } from '../registry';
|
|
16
16
|
import { createInitializedClients, TestType, triggerWebhook } from '../testing';
|
|
17
17
|
import { TriggerRegistry } from '../trigger';
|
|
18
18
|
import { type FunctionManifest } from '../types';
|
package/src/runtime/scheduler.ts
CHANGED
|
@@ -4,13 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
|
|
7
|
-
import { Mutex } from '@dxos/async';
|
|
8
7
|
import { type Space } from '@dxos/client/echo';
|
|
9
8
|
import { Context } from '@dxos/context';
|
|
10
9
|
import { log } from '@dxos/log';
|
|
11
10
|
|
|
12
|
-
import { type FunctionRegistry } from '../function';
|
|
13
11
|
import { type FunctionEventMeta } from '../handler';
|
|
12
|
+
import { type FunctionRegistry } from '../registry';
|
|
14
13
|
import { type TriggerRegistry } from '../trigger';
|
|
15
14
|
import { type FunctionDef, type FunctionManifest, type FunctionTrigger } from '../types';
|
|
16
15
|
|
|
@@ -27,15 +26,13 @@ export type SchedulerOptions = {
|
|
|
27
26
|
export class Scheduler {
|
|
28
27
|
private _ctx = createContext();
|
|
29
28
|
|
|
30
|
-
private readonly _callMutex = new Mutex();
|
|
31
|
-
|
|
32
29
|
constructor(
|
|
33
30
|
public readonly functions: FunctionRegistry,
|
|
34
31
|
public readonly triggers: TriggerRegistry,
|
|
35
32
|
private readonly _options: SchedulerOptions = {},
|
|
36
33
|
) {
|
|
37
|
-
this.functions.
|
|
38
|
-
await this._safeActivateTriggers(space, this.triggers.getInactiveTriggers(space),
|
|
34
|
+
this.functions.onFunctionsRegistered.on(async ({ space, newFunctions }) => {
|
|
35
|
+
await this._safeActivateTriggers(space, this.triggers.getInactiveTriggers(space), newFunctions);
|
|
39
36
|
});
|
|
40
37
|
this.triggers.registered.on(async ({ space, triggers }) => {
|
|
41
38
|
await this._safeActivateTriggers(space, triggers, this.functions.getFunctions(space));
|
|
@@ -55,9 +52,8 @@ export class Scheduler {
|
|
|
55
52
|
await this.triggers.close();
|
|
56
53
|
}
|
|
57
54
|
|
|
58
|
-
// TODO(burdon): Remove and update registries directly.
|
|
59
55
|
public async register(space: Space, manifest: FunctionManifest) {
|
|
60
|
-
await this.functions.register(space, manifest
|
|
56
|
+
await this.functions.register(space, manifest);
|
|
61
57
|
await this.triggers.register(space, manifest);
|
|
62
58
|
}
|
|
63
59
|
|
|
@@ -80,20 +76,16 @@ export class Scheduler {
|
|
|
80
76
|
}
|
|
81
77
|
|
|
82
78
|
await this.triggers.activate({ space }, fnTrigger, async (args) => {
|
|
83
|
-
return this.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
data: { ...args, spaceKey: space.key },
|
|
87
|
-
});
|
|
79
|
+
return this._execFunction(definition, {
|
|
80
|
+
meta: fnTrigger.meta,
|
|
81
|
+
data: { ...args, spaceKey: space.key },
|
|
88
82
|
});
|
|
89
83
|
});
|
|
90
|
-
|
|
91
84
|
log('activated trigger', { space: space.key, trigger: fnTrigger });
|
|
92
85
|
}
|
|
93
86
|
|
|
94
87
|
private async _execFunction<TData, TMeta>(
|
|
95
88
|
def: FunctionDef,
|
|
96
|
-
trigger: FunctionTrigger,
|
|
97
89
|
{ data, meta }: { data: TData; meta?: TMeta },
|
|
98
90
|
): Promise<number> {
|
|
99
91
|
let status = 0;
|
|
@@ -105,7 +97,7 @@ export class Scheduler {
|
|
|
105
97
|
if (endpoint) {
|
|
106
98
|
// TODO(burdon): Move out of scheduler (generalize as callback).
|
|
107
99
|
const url = path.join(endpoint, def.route);
|
|
108
|
-
log.info('exec', { function: def.uri, url
|
|
100
|
+
log.info('exec', { function: def.uri, url });
|
|
109
101
|
const response = await fetch(url, {
|
|
110
102
|
method: 'POST',
|
|
111
103
|
headers: {
|
|
@@ -13,7 +13,7 @@ import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
|
13
13
|
import { describe, test } from '@dxos/test';
|
|
14
14
|
|
|
15
15
|
import { setTestCallHandler } from './test/handler';
|
|
16
|
-
import { FunctionRegistry } from '../
|
|
16
|
+
import { FunctionRegistry } from '../registry';
|
|
17
17
|
import { DevServer, Scheduler } from '../runtime';
|
|
18
18
|
import { createFunctionRuntime, createInitializedClients, TestType } from '../testing';
|
|
19
19
|
import { TriggerRegistry } from '../trigger';
|
package/src/testing/setup.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { range } from '@dxos/util';
|
|
|
10
10
|
import { TestType } from './types';
|
|
11
11
|
import { FunctionDef, FunctionTrigger } from '../types';
|
|
12
12
|
|
|
13
|
-
// TODO(burdon): Create
|
|
13
|
+
// TODO(burdon): Create TestBuilder.
|
|
14
14
|
|
|
15
15
|
export const createInitializedClients = async (testBuilder: TestBuilder, count: number = 1, config?: Config) => {
|
|
16
16
|
const clients = range(count).map(() => new Client({ config, services: testBuilder.createLocalClientServices() }));
|