@dxos/functions 0.5.3-main.f752aaa → 0.5.3-main.f9b873d
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 +802 -429
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +787 -426
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/handler.d.ts +33 -12
- package/dist/types/src/handler.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/registry/function-registry.d.ts +24 -0
- package/dist/types/src/registry/function-registry.d.ts.map +1 -0
- package/dist/types/src/registry/function-registry.test.d.ts +2 -0
- package/dist/types/src/registry/function-registry.test.d.ts.map +1 -0
- package/dist/types/src/registry/index.d.ts +2 -0
- package/dist/types/src/registry/index.d.ts.map +1 -0
- package/dist/types/src/runtime/dev-server.d.ts +16 -13
- package/dist/types/src/runtime/dev-server.d.ts.map +1 -1
- package/dist/types/src/runtime/dev-server.test.d.ts +2 -0
- package/dist/types/src/runtime/dev-server.test.d.ts.map +1 -0
- package/dist/types/src/runtime/scheduler.d.ts +12 -27
- package/dist/types/src/runtime/scheduler.d.ts.map +1 -1
- package/dist/types/src/testing/functions-integration.test.d.ts +2 -0
- package/dist/types/src/testing/functions-integration.test.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +4 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/setup.d.ts +5 -0
- package/dist/types/src/testing/setup.d.ts.map +1 -0
- package/dist/types/src/testing/test/handler.d.ts +4 -0
- package/dist/types/src/testing/test/handler.d.ts.map +1 -0
- package/dist/types/src/testing/test/index.d.ts +3 -0
- package/dist/types/src/testing/test/index.d.ts.map +1 -0
- package/dist/types/src/testing/types.d.ts +9 -0
- package/dist/types/src/testing/types.d.ts.map +1 -0
- package/dist/types/src/testing/util.d.ts +3 -0
- package/dist/types/src/testing/util.d.ts.map +1 -0
- package/dist/types/src/trigger/index.d.ts +2 -0
- package/dist/types/src/trigger/index.d.ts.map +1 -0
- package/dist/types/src/trigger/trigger-registry.d.ts +40 -0
- package/dist/types/src/trigger/trigger-registry.d.ts.map +1 -0
- package/dist/types/src/trigger/trigger-registry.test.d.ts +2 -0
- package/dist/types/src/trigger/trigger-registry.test.d.ts.map +1 -0
- package/dist/types/src/trigger/type/index.d.ts +5 -0
- package/dist/types/src/trigger/type/index.d.ts.map +1 -0
- package/dist/types/src/trigger/type/subscription-trigger.d.ts +4 -0
- package/dist/types/src/trigger/type/subscription-trigger.d.ts.map +1 -0
- package/dist/types/src/trigger/type/timer-trigger.d.ts +4 -0
- package/dist/types/src/trigger/type/timer-trigger.d.ts.map +1 -0
- package/dist/types/src/trigger/type/webhook-trigger.d.ts +4 -0
- package/dist/types/src/trigger/type/webhook-trigger.d.ts.map +1 -0
- package/dist/types/src/trigger/type/websocket-trigger.d.ts +13 -0
- package/dist/types/src/trigger/type/websocket-trigger.d.ts.map +1 -0
- package/dist/types/src/types.d.ts +129 -101
- package/dist/types/src/types.d.ts.map +1 -1
- package/package.json +18 -13
- package/schema/functions.json +128 -101
- package/src/handler.ts +54 -31
- package/src/index.ts +2 -0
- package/src/registry/function-registry.test.ts +105 -0
- package/src/registry/function-registry.ts +84 -0
- package/src/registry/index.ts +5 -0
- package/src/runtime/dev-server.test.ts +60 -0
- package/src/runtime/dev-server.ts +104 -52
- package/src/runtime/scheduler.test.ts +56 -73
- package/src/runtime/scheduler.ts +79 -271
- package/src/testing/functions-integration.test.ts +99 -0
- package/src/testing/index.ts +7 -0
- package/src/testing/setup.ts +45 -0
- package/src/testing/test/handler.ts +15 -0
- package/src/testing/test/index.ts +7 -0
- package/src/testing/types.ts +9 -0
- package/src/testing/util.ts +16 -0
- package/src/trigger/index.ts +5 -0
- package/src/trigger/trigger-registry.test.ts +229 -0
- package/src/trigger/trigger-registry.ts +176 -0
- package/src/trigger/type/index.ts +8 -0
- package/src/trigger/type/subscription-trigger.ts +73 -0
- package/src/trigger/type/timer-trigger.ts +44 -0
- package/src/trigger/type/webhook-trigger.ts +47 -0
- package/src/trigger/type/websocket-trigger.ts +91 -0
- package/src/types.ts +57 -32
|
@@ -7,18 +7,19 @@ import { getPort } from 'get-port-please';
|
|
|
7
7
|
import type http from 'http';
|
|
8
8
|
import { join } from 'node:path';
|
|
9
9
|
|
|
10
|
-
import { Trigger } from '@dxos/async';
|
|
10
|
+
import { Event, Trigger } from '@dxos/async';
|
|
11
11
|
import { type Client } from '@dxos/client';
|
|
12
|
+
import { Context } from '@dxos/context';
|
|
12
13
|
import { invariant } from '@dxos/invariant';
|
|
13
14
|
import { log } from '@dxos/log';
|
|
14
15
|
|
|
15
|
-
import { type FunctionContext, type FunctionHandler, type
|
|
16
|
-
import { type
|
|
16
|
+
import { type FunctionContext, type FunctionEvent, type FunctionHandler, type FunctionResponse } from '../handler';
|
|
17
|
+
import { type FunctionRegistry } from '../registry';
|
|
18
|
+
import { type FunctionDef } from '../types';
|
|
17
19
|
|
|
18
20
|
export type DevServerOptions = {
|
|
21
|
+
baseDir: string;
|
|
19
22
|
port?: number;
|
|
20
|
-
directory: string;
|
|
21
|
-
manifest: FunctionManifest;
|
|
22
23
|
reload?: boolean;
|
|
23
24
|
dataDir?: string;
|
|
24
25
|
};
|
|
@@ -27,20 +28,37 @@ export type DevServerOptions = {
|
|
|
27
28
|
* Functions dev server provides a local HTTP server for testing functions.
|
|
28
29
|
*/
|
|
29
30
|
export class DevServer {
|
|
31
|
+
private _ctx = createContext();
|
|
32
|
+
|
|
30
33
|
// Function handlers indexed by name (URL path).
|
|
31
34
|
private readonly _handlers: Record<string, { def: FunctionDef; handler: FunctionHandler<any> }> = {};
|
|
32
35
|
|
|
33
36
|
private _server?: http.Server;
|
|
34
37
|
private _port?: number;
|
|
35
|
-
private
|
|
38
|
+
private _functionServiceRegistration?: string;
|
|
36
39
|
private _proxy?: string;
|
|
37
40
|
private _seq = 0;
|
|
38
41
|
|
|
42
|
+
public readonly update = new Event<number>();
|
|
43
|
+
|
|
39
44
|
// prettier-ignore
|
|
40
45
|
constructor(
|
|
41
46
|
private readonly _client: Client,
|
|
47
|
+
private readonly _functionsRegistry: FunctionRegistry,
|
|
42
48
|
private readonly _options: DevServerOptions,
|
|
43
|
-
) {
|
|
49
|
+
) {
|
|
50
|
+
this._functionsRegistry.onFunctionsRegistered.on(async ({ newFunctions }) => {
|
|
51
|
+
newFunctions.forEach((def) => this._load(def));
|
|
52
|
+
await this._safeUpdateRegistration();
|
|
53
|
+
log('new functions loaded', { newFunctions });
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get stats() {
|
|
58
|
+
return {
|
|
59
|
+
seq: this._seq,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
44
62
|
|
|
45
63
|
get endpoint() {
|
|
46
64
|
invariant(this._port);
|
|
@@ -55,30 +73,26 @@ export class DevServer {
|
|
|
55
73
|
return Object.values(this._handlers);
|
|
56
74
|
}
|
|
57
75
|
|
|
58
|
-
async initialize() {
|
|
59
|
-
for (const def of this._options.manifest.functions) {
|
|
60
|
-
try {
|
|
61
|
-
await this._load(def);
|
|
62
|
-
} catch (err) {
|
|
63
|
-
log.error('parsing function (check manifest)', err);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
76
|
async start() {
|
|
77
|
+
invariant(!this._server);
|
|
78
|
+
log.info('starting...');
|
|
79
|
+
this._ctx = createContext();
|
|
80
|
+
|
|
81
|
+
// TODO(burdon): Move to hono.
|
|
69
82
|
const app = express();
|
|
70
83
|
app.use(express.json());
|
|
71
84
|
|
|
72
|
-
app.post('/:
|
|
73
|
-
const {
|
|
85
|
+
app.post('/:path', async (req, res) => {
|
|
86
|
+
const { path } = req.params;
|
|
74
87
|
try {
|
|
75
|
-
log.info('calling', {
|
|
88
|
+
log.info('calling', { path });
|
|
76
89
|
if (this._options.reload) {
|
|
77
|
-
const { def } = this._handlers[
|
|
90
|
+
const { def } = this._handlers['/' + path];
|
|
78
91
|
await this._load(def, true);
|
|
79
92
|
}
|
|
80
93
|
|
|
81
|
-
|
|
94
|
+
// TODO(burdon): Get function context.
|
|
95
|
+
res.statusCode = await this.invoke('/' + path, req.body);
|
|
82
96
|
res.end();
|
|
83
97
|
} catch (err: any) {
|
|
84
98
|
log.catch(err);
|
|
@@ -94,72 +108,110 @@ export class DevServer {
|
|
|
94
108
|
// Register functions.
|
|
95
109
|
const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService!.register({
|
|
96
110
|
endpoint: this.endpoint,
|
|
97
|
-
functions: this.functions.map(({ def: { name } }) => ({ name })),
|
|
98
111
|
});
|
|
99
112
|
|
|
100
|
-
log.info('registered', {
|
|
101
|
-
this._registrationId = registrationId;
|
|
113
|
+
log.info('registered', { endpoint });
|
|
102
114
|
this._proxy = endpoint;
|
|
115
|
+
this._functionServiceRegistration = registrationId;
|
|
116
|
+
|
|
117
|
+
// Open after registration, so that it can be updated with the list of function definitions.
|
|
118
|
+
await this._functionsRegistry.open(this._ctx);
|
|
103
119
|
} catch (err: any) {
|
|
104
120
|
await this.stop();
|
|
105
121
|
throw new Error('FunctionRegistryService not available (check plugin is configured).');
|
|
106
122
|
}
|
|
123
|
+
|
|
124
|
+
log.info('started', { port: this._port });
|
|
107
125
|
}
|
|
108
126
|
|
|
109
127
|
async stop() {
|
|
128
|
+
invariant(this._server);
|
|
129
|
+
log.info('stopping...');
|
|
130
|
+
|
|
110
131
|
const trigger = new Trigger();
|
|
111
|
-
this._server
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
132
|
+
this._server.close(async () => {
|
|
133
|
+
log.info('server stopped');
|
|
134
|
+
try {
|
|
135
|
+
if (this._functionServiceRegistration) {
|
|
136
|
+
invariant(this._client.services.services.FunctionRegistryService);
|
|
137
|
+
await this._client.services.services.FunctionRegistryService.unregister({
|
|
138
|
+
registrationId: this._functionServiceRegistration,
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
log.info('unregistered', { registrationId: this._functionServiceRegistration });
|
|
142
|
+
this._functionServiceRegistration = undefined;
|
|
143
|
+
this._proxy = undefined;
|
|
144
|
+
}
|
|
116
145
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
146
|
+
trigger.wake();
|
|
147
|
+
} catch (err) {
|
|
148
|
+
trigger.throw(err as Error);
|
|
120
149
|
}
|
|
121
|
-
|
|
122
|
-
trigger.wake();
|
|
123
150
|
});
|
|
124
151
|
|
|
125
152
|
await trigger.wait();
|
|
126
153
|
this._port = undefined;
|
|
127
154
|
this._server = undefined;
|
|
155
|
+
log.info('stopped');
|
|
128
156
|
}
|
|
129
157
|
|
|
130
158
|
/**
|
|
131
159
|
* Load function.
|
|
132
160
|
*/
|
|
133
|
-
private async _load(def: FunctionDef,
|
|
134
|
-
const {
|
|
135
|
-
const
|
|
136
|
-
log.info('loading', {
|
|
161
|
+
private async _load(def: FunctionDef, force = false) {
|
|
162
|
+
const { uri, route, handler } = def;
|
|
163
|
+
const filePath = join(this._options.baseDir, handler);
|
|
164
|
+
log.info('loading', { uri, force });
|
|
137
165
|
|
|
138
166
|
// Remove from cache.
|
|
139
|
-
if (
|
|
167
|
+
if (force) {
|
|
140
168
|
Object.keys(require.cache)
|
|
141
|
-
.filter((key) => key.startsWith(
|
|
142
|
-
.forEach((key) =>
|
|
169
|
+
.filter((key) => key.startsWith(filePath))
|
|
170
|
+
.forEach((key) => {
|
|
171
|
+
delete require.cache[key];
|
|
172
|
+
});
|
|
143
173
|
}
|
|
144
174
|
|
|
175
|
+
// TODO(burdon): Import types.
|
|
145
176
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
146
|
-
const module = require(
|
|
177
|
+
const module = require(filePath);
|
|
147
178
|
if (typeof module.default !== 'function') {
|
|
148
|
-
throw new Error(`Handler must export default function: ${
|
|
179
|
+
throw new Error(`Handler must export default function: ${uri}`);
|
|
149
180
|
}
|
|
150
181
|
|
|
151
|
-
this._handlers[
|
|
182
|
+
this._handlers[route] = { def, handler: module.default };
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private async _safeUpdateRegistration(): Promise<void> {
|
|
186
|
+
invariant(this._functionServiceRegistration);
|
|
187
|
+
try {
|
|
188
|
+
await this._client.services.services.FunctionRegistryService!.updateRegistration({
|
|
189
|
+
registrationId: this._functionServiceRegistration,
|
|
190
|
+
functions: this.functions.map(({ def: { id, route } }) => ({ id, route })),
|
|
191
|
+
});
|
|
192
|
+
} catch (e) {
|
|
193
|
+
log.catch(e);
|
|
194
|
+
}
|
|
152
195
|
}
|
|
153
196
|
|
|
154
197
|
/**
|
|
155
|
-
* Invoke function
|
|
198
|
+
* Invoke function.
|
|
156
199
|
*/
|
|
157
|
-
|
|
200
|
+
public async invoke(path: string, data: any): Promise<number> {
|
|
158
201
|
const seq = ++this._seq;
|
|
159
202
|
const now = Date.now();
|
|
160
203
|
|
|
161
|
-
log.info('req', { seq,
|
|
162
|
-
const
|
|
204
|
+
log.info('req', { seq, path });
|
|
205
|
+
const statusCode = await this._invoke(path, { data });
|
|
206
|
+
|
|
207
|
+
log.info('res', { seq, path, statusCode, duration: Date.now() - now });
|
|
208
|
+
this.update.emit(statusCode);
|
|
209
|
+
return statusCode;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
private async _invoke(path: string, event: FunctionEvent) {
|
|
213
|
+
const { handler } = this._handlers[path] ?? {};
|
|
214
|
+
invariant(handler, `invalid path: ${path}`);
|
|
163
215
|
|
|
164
216
|
const context: FunctionContext = {
|
|
165
217
|
client: this._client,
|
|
@@ -167,7 +219,7 @@ export class DevServer {
|
|
|
167
219
|
};
|
|
168
220
|
|
|
169
221
|
let statusCode = 200;
|
|
170
|
-
const response:
|
|
222
|
+
const response: FunctionResponse = {
|
|
171
223
|
status: (code: number) => {
|
|
172
224
|
statusCode = code;
|
|
173
225
|
return response;
|
|
@@ -175,8 +227,8 @@ export class DevServer {
|
|
|
175
227
|
};
|
|
176
228
|
|
|
177
229
|
await handler({ context, event, response });
|
|
178
|
-
log.info('res', { seq, name, statusCode, duration: Date.now() - now });
|
|
179
|
-
|
|
180
230
|
return statusCode;
|
|
181
231
|
}
|
|
182
232
|
}
|
|
233
|
+
|
|
234
|
+
const createContext = () => new Context({ name: 'DevServer' });
|
|
@@ -6,40 +6,43 @@ import { expect } from 'chai';
|
|
|
6
6
|
import WebSocket from 'ws';
|
|
7
7
|
|
|
8
8
|
import { Trigger } from '@dxos/async';
|
|
9
|
-
import { Client } from '@dxos/client';
|
|
9
|
+
import { type Client } from '@dxos/client';
|
|
10
10
|
import { TestBuilder } from '@dxos/client/testing';
|
|
11
|
-
import { create
|
|
11
|
+
import { create } from '@dxos/echo-schema';
|
|
12
12
|
import { describe, test } from '@dxos/test';
|
|
13
13
|
|
|
14
|
-
import { Scheduler } from './scheduler';
|
|
14
|
+
import { Scheduler, type SchedulerOptions } from './scheduler';
|
|
15
|
+
import { FunctionRegistry } from '../registry';
|
|
16
|
+
import { createInitializedClients, TestType, triggerWebhook } from '../testing';
|
|
17
|
+
import { TriggerRegistry } from '../trigger';
|
|
15
18
|
import { type FunctionManifest } from '../types';
|
|
16
19
|
|
|
17
20
|
// TODO(burdon): Test we can add and remove triggers.
|
|
18
21
|
describe('scheduler', () => {
|
|
22
|
+
let testBuilder: TestBuilder;
|
|
19
23
|
let client: Client;
|
|
20
24
|
before(async () => {
|
|
21
|
-
|
|
22
|
-
client =
|
|
23
|
-
await client.initialize();
|
|
24
|
-
await client.halo.createIdentity();
|
|
25
|
+
testBuilder = new TestBuilder();
|
|
26
|
+
client = (await createInitializedClients(testBuilder, 1))[0];
|
|
25
27
|
});
|
|
26
28
|
after(async () => {
|
|
27
|
-
await
|
|
29
|
+
await testBuilder.destroy();
|
|
28
30
|
});
|
|
29
31
|
|
|
30
32
|
test('timer', async () => {
|
|
31
33
|
const manifest: FunctionManifest = {
|
|
32
34
|
functions: [
|
|
33
35
|
{
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
uri: 'example.com/function/test',
|
|
37
|
+
route: '/test',
|
|
36
38
|
handler: 'test',
|
|
37
39
|
},
|
|
38
40
|
],
|
|
39
41
|
triggers: [
|
|
40
42
|
{
|
|
41
43
|
function: 'example.com/function/test',
|
|
42
|
-
|
|
44
|
+
spec: {
|
|
45
|
+
type: 'timer',
|
|
43
46
|
cron: '0/1 * * * * *', // Every 1s.
|
|
44
47
|
},
|
|
45
48
|
},
|
|
@@ -48,18 +51,13 @@ describe('scheduler', () => {
|
|
|
48
51
|
|
|
49
52
|
let count = 0;
|
|
50
53
|
const done = new Trigger();
|
|
51
|
-
const scheduler =
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
},
|
|
54
|
+
const scheduler = createScheduler(async () => {
|
|
55
|
+
if (++count === 3) {
|
|
56
|
+
done.wake();
|
|
57
|
+
}
|
|
57
58
|
});
|
|
58
|
-
|
|
59
|
+
await scheduler.register(client.spaces.default, manifest);
|
|
59
60
|
await scheduler.start();
|
|
60
|
-
after(async () => {
|
|
61
|
-
await scheduler.stop();
|
|
62
|
-
});
|
|
63
61
|
|
|
64
62
|
await done.wait({ timeout: 5_000 });
|
|
65
63
|
expect(count).to.equal(3);
|
|
@@ -69,52 +67,49 @@ describe('scheduler', () => {
|
|
|
69
67
|
const manifest: FunctionManifest = {
|
|
70
68
|
functions: [
|
|
71
69
|
{
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
uri: 'example.com/function/test',
|
|
71
|
+
route: '/test',
|
|
74
72
|
handler: 'test',
|
|
75
73
|
},
|
|
76
74
|
],
|
|
77
75
|
triggers: [
|
|
78
76
|
{
|
|
79
77
|
function: 'example.com/function/test',
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
spec: {
|
|
79
|
+
type: 'webhook',
|
|
80
|
+
method: 'GET',
|
|
82
81
|
},
|
|
83
82
|
},
|
|
84
83
|
],
|
|
85
84
|
};
|
|
86
85
|
|
|
87
86
|
const done = new Trigger();
|
|
88
|
-
const scheduler =
|
|
89
|
-
|
|
90
|
-
done.wake();
|
|
91
|
-
},
|
|
87
|
+
const scheduler = createScheduler(async () => {
|
|
88
|
+
done.wake();
|
|
92
89
|
});
|
|
93
|
-
|
|
90
|
+
const space = await client.spaces.create();
|
|
91
|
+
await scheduler.register(space, manifest);
|
|
94
92
|
await scheduler.start();
|
|
95
|
-
after(async () => {
|
|
96
|
-
await scheduler.stop();
|
|
97
|
-
});
|
|
98
93
|
|
|
99
|
-
setTimeout(() =>
|
|
100
|
-
|
|
101
|
-
});
|
|
94
|
+
setTimeout(async () => triggerWebhook(space, manifest.functions![0].uri));
|
|
95
|
+
|
|
102
96
|
await done.wait();
|
|
103
97
|
});
|
|
104
98
|
|
|
105
|
-
test
|
|
99
|
+
test('websocket', async () => {
|
|
106
100
|
const manifest: FunctionManifest = {
|
|
107
101
|
functions: [
|
|
108
102
|
{
|
|
109
|
-
|
|
110
|
-
|
|
103
|
+
uri: 'example.com/function/test',
|
|
104
|
+
route: '/test',
|
|
111
105
|
handler: 'test',
|
|
112
106
|
},
|
|
113
107
|
],
|
|
114
108
|
triggers: [
|
|
115
109
|
{
|
|
116
110
|
function: 'example.com/function/test',
|
|
117
|
-
|
|
111
|
+
spec: {
|
|
112
|
+
type: 'websocket',
|
|
118
113
|
// url: 'https://hub.dxos.network/api/mailbox/test',
|
|
119
114
|
url: 'http://localhost:8081',
|
|
120
115
|
init: {
|
|
@@ -126,16 +121,11 @@ describe('scheduler', () => {
|
|
|
126
121
|
};
|
|
127
122
|
|
|
128
123
|
const done = new Trigger();
|
|
129
|
-
const scheduler =
|
|
130
|
-
|
|
131
|
-
done.wake();
|
|
132
|
-
},
|
|
124
|
+
const scheduler = createScheduler(async () => {
|
|
125
|
+
done.wake();
|
|
133
126
|
});
|
|
134
|
-
|
|
127
|
+
await scheduler.register(client.spaces.default, manifest);
|
|
135
128
|
await scheduler.start();
|
|
136
|
-
after(async () => {
|
|
137
|
-
await scheduler.stop();
|
|
138
|
-
});
|
|
139
129
|
|
|
140
130
|
// Test server.
|
|
141
131
|
setTimeout(() => {
|
|
@@ -153,29 +143,20 @@ describe('scheduler', () => {
|
|
|
153
143
|
});
|
|
154
144
|
|
|
155
145
|
test('subscription', async () => {
|
|
156
|
-
class TestType extends TypedObject({ typename: 'example.com/type/Test', version: '0.1.0' })({
|
|
157
|
-
title: S.string,
|
|
158
|
-
}) {}
|
|
159
|
-
client.addSchema(TestType);
|
|
160
|
-
|
|
161
146
|
const manifest: FunctionManifest = {
|
|
162
147
|
functions: [
|
|
163
148
|
{
|
|
164
|
-
|
|
165
|
-
|
|
149
|
+
uri: 'example.com/function/test',
|
|
150
|
+
route: '/test',
|
|
166
151
|
handler: 'test',
|
|
167
152
|
},
|
|
168
153
|
],
|
|
169
154
|
triggers: [
|
|
170
155
|
{
|
|
171
156
|
function: 'example.com/function/test',
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
filter: [
|
|
175
|
-
{
|
|
176
|
-
type: TestType.typename,
|
|
177
|
-
},
|
|
178
|
-
],
|
|
157
|
+
spec: {
|
|
158
|
+
type: 'subscription',
|
|
159
|
+
filter: [{ type: TestType.typename }],
|
|
179
160
|
},
|
|
180
161
|
},
|
|
181
162
|
],
|
|
@@ -183,20 +164,14 @@ describe('scheduler', () => {
|
|
|
183
164
|
|
|
184
165
|
let count = 0;
|
|
185
166
|
const done = new Trigger();
|
|
186
|
-
const scheduler =
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
},
|
|
167
|
+
const scheduler = createScheduler(async () => {
|
|
168
|
+
if (++count === 2) {
|
|
169
|
+
done.wake();
|
|
170
|
+
}
|
|
192
171
|
});
|
|
193
|
-
|
|
172
|
+
await scheduler.register(client.spaces.default, manifest);
|
|
194
173
|
await scheduler.start();
|
|
195
|
-
after(async () => {
|
|
196
|
-
await scheduler.stop();
|
|
197
|
-
});
|
|
198
174
|
|
|
199
|
-
// TODO(burdon): Query for Expando?
|
|
200
175
|
setTimeout(() => {
|
|
201
176
|
const space = client.spaces.default;
|
|
202
177
|
const object = create(TestType, { title: 'Hello world!' });
|
|
@@ -205,4 +180,12 @@ describe('scheduler', () => {
|
|
|
205
180
|
|
|
206
181
|
await done.wait();
|
|
207
182
|
});
|
|
183
|
+
|
|
184
|
+
const createScheduler = (callback: SchedulerOptions['callback']) => {
|
|
185
|
+
const scheduler = new Scheduler(new FunctionRegistry(client), new TriggerRegistry(client), { callback });
|
|
186
|
+
after(async () => {
|
|
187
|
+
await scheduler.stop();
|
|
188
|
+
});
|
|
189
|
+
return scheduler;
|
|
190
|
+
};
|
|
208
191
|
});
|