@dxos/functions 0.5.3-main.d7fe7b5 → 0.5.3-main.e38fceb
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/chunk-4D4I3YMJ.mjs +86 -0
- package/dist/lib/browser/chunk-4D4I3YMJ.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +390 -336
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/types.mjs +14 -0
- package/dist/lib/browser/types.mjs.map +7 -0
- package/dist/lib/node/chunk-3UYUR5N5.cjs +103 -0
- package/dist/lib/node/chunk-3UYUR5N5.cjs.map +7 -0
- package/dist/lib/node/index.cjs +393 -333
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/types.cjs +35 -0
- package/dist/lib/node/types.cjs.map +7 -0
- package/dist/types/src/browser/index.d.ts +2 -0
- package/dist/types/src/browser/index.d.ts.map +1 -0
- package/dist/types/src/{registry → function}/function-registry.d.ts +4 -4
- package/dist/types/src/function/function-registry.d.ts.map +1 -0
- package/dist/types/src/function/function-registry.test.d.ts.map +1 -0
- package/dist/types/src/function/index.d.ts.map +1 -0
- package/dist/types/src/handler.d.ts.map +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/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 +2 -1
- package/dist/types/src/runtime/scheduler.d.ts.map +1 -1
- package/dist/types/src/testing/setup.d.ts.map +1 -1
- package/dist/types/src/trigger/trigger-registry.d.ts +2 -5
- 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/trigger/type/timer-trigger.d.ts.map +1 -1
- package/dist/types/src/trigger/type/webhook-trigger.d.ts.map +1 -1
- package/dist/types/src/trigger/type/websocket-trigger.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +70 -43
- package/dist/types/src/types.d.ts.map +1 -1
- package/package.json +31 -18
- package/schema/functions.json +23 -9
- package/src/browser/index.ts +5 -0
- package/src/{registry → function}/function-registry.test.ts +10 -10
- package/src/function/function-registry.ts +90 -0
- package/src/index.ts +1 -1
- package/src/runtime/dev-server.test.ts +2 -2
- package/src/runtime/dev-server.ts +8 -9
- package/src/runtime/scheduler.test.ts +15 -10
- package/src/runtime/scheduler.ts +26 -13
- package/src/testing/functions-integration.test.ts +2 -1
- package/src/testing/setup.ts +8 -10
- package/src/trigger/trigger-registry.test.ts +88 -45
- package/src/trigger/trigger-registry.ts +66 -31
- package/src/trigger/type/subscription-trigger.ts +30 -17
- package/src/trigger/type/timer-trigger.ts +4 -3
- package/src/trigger/type/webhook-trigger.ts +3 -2
- package/src/trigger/type/websocket-trigger.ts +4 -3
- package/src/types.ts +51 -37
- package/dist/types/src/registry/function-registry.d.ts.map +0 -1
- package/dist/types/src/registry/function-registry.test.d.ts.map +0 -1
- package/dist/types/src/registry/index.d.ts.map +0 -1
- package/src/registry/function-registry.ts +0 -84
- /package/dist/types/src/{registry → function}/function-registry.test.d.ts +0 -0
- /package/dist/types/src/{registry → function}/index.d.ts +0 -0
- /package/src/{registry → function}/index.ts +0 -0
|
@@ -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 '../function';
|
|
16
16
|
import { createInitializedClients, TestType, triggerWebhook } from '../testing';
|
|
17
17
|
import { TriggerRegistry } from '../trigger';
|
|
18
18
|
import { type FunctionManifest } from '../types';
|
|
@@ -29,6 +29,15 @@ describe('scheduler', () => {
|
|
|
29
29
|
await testBuilder.destroy();
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
+
const createScheduler = (callback: SchedulerOptions['callback']) => {
|
|
33
|
+
const scheduler = new Scheduler(new FunctionRegistry(client), new TriggerRegistry(client), { callback });
|
|
34
|
+
after(async () => {
|
|
35
|
+
await scheduler.stop();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return scheduler;
|
|
39
|
+
};
|
|
40
|
+
|
|
32
41
|
test('timer', async () => {
|
|
33
42
|
const manifest: FunctionManifest = {
|
|
34
43
|
functions: [
|
|
@@ -41,6 +50,7 @@ describe('scheduler', () => {
|
|
|
41
50
|
triggers: [
|
|
42
51
|
{
|
|
43
52
|
function: 'example.com/function/test',
|
|
53
|
+
enabled: true,
|
|
44
54
|
spec: {
|
|
45
55
|
type: 'timer',
|
|
46
56
|
cron: '0/1 * * * * *', // Every 1s.
|
|
@@ -75,6 +85,7 @@ describe('scheduler', () => {
|
|
|
75
85
|
triggers: [
|
|
76
86
|
{
|
|
77
87
|
function: 'example.com/function/test',
|
|
88
|
+
enabled: true,
|
|
78
89
|
spec: {
|
|
79
90
|
type: 'webhook',
|
|
80
91
|
method: 'GET',
|
|
@@ -108,6 +119,7 @@ describe('scheduler', () => {
|
|
|
108
119
|
triggers: [
|
|
109
120
|
{
|
|
110
121
|
function: 'example.com/function/test',
|
|
122
|
+
enabled: true,
|
|
111
123
|
spec: {
|
|
112
124
|
type: 'websocket',
|
|
113
125
|
// url: 'https://hub.dxos.network/api/mailbox/test',
|
|
@@ -154,6 +166,7 @@ describe('scheduler', () => {
|
|
|
154
166
|
triggers: [
|
|
155
167
|
{
|
|
156
168
|
function: 'example.com/function/test',
|
|
169
|
+
enabled: true,
|
|
157
170
|
spec: {
|
|
158
171
|
type: 'subscription',
|
|
159
172
|
filter: [{ type: TestType.typename }],
|
|
@@ -165,7 +178,7 @@ describe('scheduler', () => {
|
|
|
165
178
|
let count = 0;
|
|
166
179
|
const done = new Trigger();
|
|
167
180
|
const scheduler = createScheduler(async () => {
|
|
168
|
-
if (++count ===
|
|
181
|
+
if (++count === 1) {
|
|
169
182
|
done.wake();
|
|
170
183
|
}
|
|
171
184
|
});
|
|
@@ -180,12 +193,4 @@ describe('scheduler', () => {
|
|
|
180
193
|
|
|
181
194
|
await done.wait();
|
|
182
195
|
});
|
|
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
|
-
};
|
|
191
196
|
});
|
package/src/runtime/scheduler.ts
CHANGED
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
|
|
7
|
+
import { Mutex } from '@dxos/async';
|
|
7
8
|
import { type Space } from '@dxos/client/echo';
|
|
8
9
|
import { Context } from '@dxos/context';
|
|
9
10
|
import { log } from '@dxos/log';
|
|
10
11
|
|
|
12
|
+
import { type FunctionRegistry } from '../function';
|
|
11
13
|
import { type FunctionEventMeta } from '../handler';
|
|
12
|
-
import { type FunctionRegistry } from '../registry';
|
|
13
14
|
import { type TriggerRegistry } from '../trigger';
|
|
14
15
|
import { type FunctionDef, type FunctionManifest, type FunctionTrigger } from '../types';
|
|
15
16
|
|
|
@@ -26,13 +27,15 @@ export type SchedulerOptions = {
|
|
|
26
27
|
export class Scheduler {
|
|
27
28
|
private _ctx = createContext();
|
|
28
29
|
|
|
30
|
+
private readonly _functionUriToCallMutex = new Map<string, Mutex>();
|
|
31
|
+
|
|
29
32
|
constructor(
|
|
30
33
|
public readonly functions: FunctionRegistry,
|
|
31
34
|
public readonly triggers: TriggerRegistry,
|
|
32
35
|
private readonly _options: SchedulerOptions = {},
|
|
33
36
|
) {
|
|
34
|
-
this.functions.
|
|
35
|
-
await this._safeActivateTriggers(space, this.triggers.getInactiveTriggers(space),
|
|
37
|
+
this.functions.registered.on(async ({ space, added }) => {
|
|
38
|
+
await this._safeActivateTriggers(space, this.triggers.getInactiveTriggers(space), added);
|
|
36
39
|
});
|
|
37
40
|
this.triggers.registered.on(async ({ space, triggers }) => {
|
|
38
41
|
await this._safeActivateTriggers(space, triggers, this.functions.getFunctions(space));
|
|
@@ -52,8 +55,9 @@ export class Scheduler {
|
|
|
52
55
|
await this.triggers.close();
|
|
53
56
|
}
|
|
54
57
|
|
|
58
|
+
// TODO(burdon): Remove and update registries directly.
|
|
55
59
|
public async register(space: Space, manifest: FunctionManifest) {
|
|
56
|
-
await this.functions.register(space, manifest);
|
|
60
|
+
await this.functions.register(space, manifest.functions);
|
|
57
61
|
await this.triggers.register(space, manifest);
|
|
58
62
|
}
|
|
59
63
|
|
|
@@ -68,24 +72,33 @@ export class Scheduler {
|
|
|
68
72
|
await Promise.all(mountTasks).catch(log.catch);
|
|
69
73
|
}
|
|
70
74
|
|
|
71
|
-
private async activate(space: Space, functions: FunctionDef[],
|
|
72
|
-
const definition = functions.find((def) => def.uri ===
|
|
75
|
+
private async activate(space: Space, functions: FunctionDef[], trigger: FunctionTrigger) {
|
|
76
|
+
const definition = functions.find((def) => def.uri === trigger.function);
|
|
73
77
|
if (!definition) {
|
|
74
|
-
log.info('function is not found for trigger', {
|
|
78
|
+
log.info('function is not found for trigger', { trigger });
|
|
75
79
|
return;
|
|
76
80
|
}
|
|
77
81
|
|
|
78
|
-
await this.triggers.activate(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
await this.triggers.activate(space, trigger, async (args) => {
|
|
83
|
+
const mutex = this._functionUriToCallMutex.get(definition.uri) ?? new Mutex();
|
|
84
|
+
this._functionUriToCallMutex.set(definition.uri, mutex);
|
|
85
|
+
|
|
86
|
+
log.info('function triggered, waiting for mutex', { uri: definition.uri });
|
|
87
|
+
return mutex.executeSynchronized(() => {
|
|
88
|
+
log.info('mutex acquired', { uri: definition.uri });
|
|
89
|
+
return this._execFunction(definition, trigger, {
|
|
90
|
+
meta: trigger.meta ?? {},
|
|
91
|
+
data: { ...args, spaceKey: space.key },
|
|
92
|
+
});
|
|
82
93
|
});
|
|
83
94
|
});
|
|
84
|
-
|
|
95
|
+
|
|
96
|
+
log('activated trigger', { space: space.key, trigger });
|
|
85
97
|
}
|
|
86
98
|
|
|
87
99
|
private async _execFunction<TData, TMeta>(
|
|
88
100
|
def: FunctionDef,
|
|
101
|
+
trigger: FunctionTrigger,
|
|
89
102
|
{ data, meta }: { data: TData; meta?: TMeta },
|
|
90
103
|
): Promise<number> {
|
|
91
104
|
let status = 0;
|
|
@@ -97,7 +110,7 @@ export class Scheduler {
|
|
|
97
110
|
if (endpoint) {
|
|
98
111
|
// TODO(burdon): Move out of scheduler (generalize as callback).
|
|
99
112
|
const url = path.join(endpoint, def.route);
|
|
100
|
-
log.info('exec', { function: def.uri, url });
|
|
113
|
+
log.info('exec', { function: def.uri, url, triggerType: trigger.spec.type });
|
|
101
114
|
const response = await fetch(url, {
|
|
102
115
|
method: 'POST',
|
|
103
116
|
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 '../function';
|
|
17
17
|
import { DevServer, Scheduler } from '../runtime';
|
|
18
18
|
import { createFunctionRuntime, createInitializedClients, TestType } from '../testing';
|
|
19
19
|
import { TriggerRegistry } from '../trigger';
|
|
@@ -44,6 +44,7 @@ describe('functions e2e', () => {
|
|
|
44
44
|
space.db.add(
|
|
45
45
|
create(FunctionTrigger, {
|
|
46
46
|
function: uri,
|
|
47
|
+
enabled: true,
|
|
47
48
|
meta: triggerMeta,
|
|
48
49
|
spec: {
|
|
49
50
|
type: 'subscription',
|
package/src/testing/setup.ts
CHANGED
|
@@ -10,16 +10,16 @@ import { range } from '@dxos/util';
|
|
|
10
10
|
import { TestType } from './types';
|
|
11
11
|
import { FunctionDef, FunctionTrigger } from '../types';
|
|
12
12
|
|
|
13
|
-
// TODO(burdon):
|
|
13
|
+
// TODO(burdon): Extend/wrap 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() }));
|
|
17
|
-
testBuilder.ctx.onDispose(() => Promise.all(clients.map((
|
|
17
|
+
testBuilder.ctx.onDispose(() => Promise.all(clients.map((client) => client.destroy())));
|
|
18
18
|
return Promise.all(
|
|
19
19
|
clients.map(async (client, index) => {
|
|
20
20
|
await client.initialize();
|
|
21
21
|
await client.halo.createIdentity({ displayName: `Peer ${index}` });
|
|
22
|
-
client.addSchema(
|
|
22
|
+
client.addSchema(FunctionDef, FunctionTrigger, TestType);
|
|
23
23
|
return client;
|
|
24
24
|
}),
|
|
25
25
|
);
|
|
@@ -34,12 +34,10 @@ export const createFunctionRuntime = async (testBuilder: TestBuilder): Promise<C
|
|
|
34
34
|
},
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
-
const client =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
await functionsPlugin.open();
|
|
43
|
-
testBuilder.ctx.onDispose(() => functionsPlugin.close());
|
|
37
|
+
const [client] = await createInitializedClients(testBuilder, 1, config);
|
|
38
|
+
const plugin = new FunctionsPlugin();
|
|
39
|
+
await plugin.initialize({ client, clientServices: client.services });
|
|
40
|
+
await plugin.open();
|
|
41
|
+
testBuilder.ctx.onDispose(() => plugin.close());
|
|
44
42
|
return client;
|
|
45
43
|
};
|
|
@@ -11,7 +11,7 @@ import { type Space } from '@dxos/client/echo';
|
|
|
11
11
|
import { TestBuilder } from '@dxos/client/testing';
|
|
12
12
|
import { Context } from '@dxos/context';
|
|
13
13
|
import { Filter } from '@dxos/echo-db';
|
|
14
|
-
import { create } from '@dxos/echo-schema';
|
|
14
|
+
import { create, splitMeta } from '@dxos/echo-schema';
|
|
15
15
|
import { describe, test } from '@dxos/test';
|
|
16
16
|
import { range } from '@dxos/util';
|
|
17
17
|
|
|
@@ -19,20 +19,42 @@ import { TriggerRegistry } from './trigger-registry';
|
|
|
19
19
|
import { createInitializedClients, TestType, triggerWebhook } from '../testing';
|
|
20
20
|
import { type FunctionManifest, FunctionTrigger } from '../types';
|
|
21
21
|
|
|
22
|
-
const
|
|
22
|
+
const manifest: FunctionManifest = {
|
|
23
23
|
triggers: [
|
|
24
24
|
{
|
|
25
|
+
'@meta': {
|
|
26
|
+
keys: [
|
|
27
|
+
{
|
|
28
|
+
source: 'example.com',
|
|
29
|
+
id: 'trigger-1',
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
},
|
|
25
33
|
function: 'example.com/function/webhook-test',
|
|
34
|
+
enabled: true,
|
|
26
35
|
spec: {
|
|
27
36
|
type: 'webhook',
|
|
28
37
|
method: 'GET',
|
|
29
38
|
},
|
|
30
39
|
},
|
|
31
40
|
{
|
|
41
|
+
'@meta': {
|
|
42
|
+
keys: [
|
|
43
|
+
{
|
|
44
|
+
source: 'example.com',
|
|
45
|
+
id: 'trigger-2',
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
32
49
|
function: 'example.com/function/subscription-test',
|
|
50
|
+
enabled: true,
|
|
33
51
|
spec: {
|
|
34
52
|
type: 'subscription',
|
|
35
|
-
filter: [
|
|
53
|
+
filter: [
|
|
54
|
+
{
|
|
55
|
+
type: TestType.typename,
|
|
56
|
+
},
|
|
57
|
+
],
|
|
36
58
|
},
|
|
37
59
|
},
|
|
38
60
|
],
|
|
@@ -54,30 +76,44 @@ describe('trigger registry', () => {
|
|
|
54
76
|
|
|
55
77
|
describe('register', () => {
|
|
56
78
|
test('creates new triggers', async () => {
|
|
57
|
-
const client =
|
|
79
|
+
const [client] = await createInitializedClients(testBuilder);
|
|
58
80
|
const registry = createRegistry(client);
|
|
59
81
|
const space = await client.spaces.create();
|
|
60
|
-
await registry.register(space,
|
|
82
|
+
await registry.register(space, manifest);
|
|
61
83
|
const { objects } = await space.db.query(Filter.schema(FunctionTrigger)).run();
|
|
62
|
-
expect(objects.length).to.eq(
|
|
63
|
-
|
|
64
|
-
|
|
84
|
+
expect(objects.length).to.eq(manifest.triggers?.length);
|
|
85
|
+
|
|
86
|
+
const expected = manifest.triggers?.map((trigger) => trigger.function).sort();
|
|
87
|
+
expect(objects.map((object: FunctionTrigger) => object.function).sort()).to.deep.eq(expected);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('set meta', () => {
|
|
91
|
+
const trigger = create(FunctionTrigger, {
|
|
92
|
+
function: 'example.com/function/webhook-test',
|
|
93
|
+
spec: {
|
|
94
|
+
type: 'webhook',
|
|
95
|
+
method: 'GET',
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
(trigger.meta ??= {}).test = 100;
|
|
100
|
+
expect(trigger.meta.test).to.eq(100);
|
|
65
101
|
});
|
|
66
102
|
});
|
|
67
103
|
|
|
68
104
|
describe('activate', () => {
|
|
69
105
|
test('invokes the provided callback', async () => {
|
|
70
|
-
const client =
|
|
106
|
+
const [client] = await createInitializedClients(testBuilder);
|
|
71
107
|
const space = await client.spaces.create();
|
|
72
108
|
const registry = createRegistry(client);
|
|
73
|
-
await registry.register(space,
|
|
109
|
+
await registry.register(space, manifest);
|
|
74
110
|
await registry.open(ctx);
|
|
75
|
-
await
|
|
111
|
+
await waitForInactiveTriggers(registry, space);
|
|
76
112
|
|
|
77
113
|
const callbackInvoked = new Trigger();
|
|
78
114
|
const { objects: allTriggers } = await space.db.query(Filter.schema(FunctionTrigger)).run();
|
|
79
|
-
const webhookTrigger = allTriggers.find((
|
|
80
|
-
await registry.activate(
|
|
115
|
+
const webhookTrigger = allTriggers.find((trigger: FunctionTrigger) => trigger.spec.type === 'webhook')!;
|
|
116
|
+
await registry.activate(space, webhookTrigger, async () => {
|
|
81
117
|
callbackInvoked.wake();
|
|
82
118
|
return 200;
|
|
83
119
|
});
|
|
@@ -87,34 +123,37 @@ describe('trigger registry', () => {
|
|
|
87
123
|
});
|
|
88
124
|
|
|
89
125
|
test('removes from inactive list', async () => {
|
|
90
|
-
const client =
|
|
126
|
+
const [client] = await createInitializedClients(testBuilder);
|
|
91
127
|
const space = await client.spaces.create();
|
|
92
128
|
const registry = createRegistry(client);
|
|
93
|
-
await registry.register(space,
|
|
129
|
+
await registry.register(space, manifest);
|
|
94
130
|
await registry.open(ctx);
|
|
95
|
-
await
|
|
131
|
+
await waitForInactiveTriggers(registry, space);
|
|
96
132
|
|
|
97
133
|
const inactiveTrigger = registry.getInactiveTriggers(space)[0];
|
|
98
|
-
await registry.activate(
|
|
134
|
+
await registry.activate(space, inactiveTrigger, async () => 200);
|
|
99
135
|
|
|
100
136
|
const updatedInactiveList = registry.getInactiveTriggers(space);
|
|
101
|
-
expect(updatedInactiveList.find((
|
|
137
|
+
expect(updatedInactiveList.find((trigger: FunctionTrigger) => trigger.function === inactiveTrigger.function)).to
|
|
138
|
+
.be.undefined;
|
|
102
139
|
});
|
|
140
|
+
|
|
141
|
+
// TODO(burdon): Test enable/disable trigger.
|
|
103
142
|
});
|
|
104
143
|
|
|
105
144
|
describe('deactivate', () => {
|
|
106
145
|
test('trigger object deletion deactivates a trigger', async () => {
|
|
107
|
-
const client =
|
|
146
|
+
const [client] = await createInitializedClients(testBuilder);
|
|
108
147
|
const space = await client.spaces.create();
|
|
109
148
|
const registry = createRegistry(client);
|
|
110
|
-
await registry.register(space,
|
|
149
|
+
await registry.register(space, manifest);
|
|
111
150
|
await registry.open(ctx);
|
|
112
|
-
await
|
|
151
|
+
await waitForInactiveTriggers(registry, space);
|
|
113
152
|
|
|
114
153
|
const { objects: allTriggers } = await space.db.query(Filter.schema(FunctionTrigger)).run();
|
|
115
|
-
const echoTrigger = allTriggers.find((
|
|
154
|
+
const echoTrigger = allTriggers.find((trigger: FunctionTrigger) => trigger.spec.type === 'subscription')!;
|
|
116
155
|
let count = 0;
|
|
117
|
-
await registry.activate(
|
|
156
|
+
await registry.activate(space, echoTrigger, async () => {
|
|
118
157
|
count++;
|
|
119
158
|
return 200;
|
|
120
159
|
});
|
|
@@ -124,24 +163,23 @@ describe('trigger registry', () => {
|
|
|
124
163
|
expect(count).to.eq(1);
|
|
125
164
|
|
|
126
165
|
space.db.remove(echoTrigger);
|
|
127
|
-
|
|
128
166
|
space.db.add(create(TestType, { title: '2' }));
|
|
129
167
|
await sleep(20);
|
|
130
168
|
expect(count).to.eq(1);
|
|
131
169
|
});
|
|
132
170
|
|
|
133
171
|
test('registry closing deactivates a trigger', async () => {
|
|
134
|
-
const client =
|
|
172
|
+
const [client] = await createInitializedClients(testBuilder);
|
|
135
173
|
const space = await client.spaces.create();
|
|
136
174
|
const registry = createRegistry(client);
|
|
137
|
-
await registry.register(space,
|
|
175
|
+
await registry.register(space, manifest);
|
|
138
176
|
await registry.open(ctx);
|
|
139
|
-
await
|
|
177
|
+
await waitForInactiveTriggers(registry, space);
|
|
140
178
|
|
|
141
179
|
const { objects: allTriggers } = await space.db.query(Filter.schema(FunctionTrigger)).run();
|
|
142
|
-
const echoTrigger = allTriggers.find((
|
|
180
|
+
const echoTrigger = allTriggers.find((trigger: FunctionTrigger) => trigger.spec.type === 'subscription')!;
|
|
143
181
|
let count = 0;
|
|
144
|
-
await registry.activate(
|
|
182
|
+
await registry.activate(space, echoTrigger, async () => {
|
|
145
183
|
count++;
|
|
146
184
|
return 200;
|
|
147
185
|
});
|
|
@@ -156,23 +194,24 @@ describe('trigger registry', () => {
|
|
|
156
194
|
|
|
157
195
|
describe('trigger events', () => {
|
|
158
196
|
test('event fired when all registered when opened', async () => {
|
|
159
|
-
const client =
|
|
197
|
+
const [client] = await createInitializedClients(testBuilder);
|
|
160
198
|
const registry = createRegistry(client);
|
|
161
|
-
const triggers =
|
|
199
|
+
const triggers = createTriggers(client.spaces.default, 3);
|
|
162
200
|
|
|
163
201
|
const triggersRegistered = new Trigger<FunctionTrigger[]>();
|
|
164
202
|
registry.registered.on((fn) => {
|
|
165
203
|
expect(fn.space.key.toHex()).to.eq(client.spaces.default.key.toHex());
|
|
166
204
|
triggersRegistered.wake(fn.triggers);
|
|
167
205
|
});
|
|
206
|
+
|
|
168
207
|
void registry.open(ctx);
|
|
169
208
|
const functions = await triggersRegistered.wait();
|
|
170
|
-
const expected = triggers.map((
|
|
209
|
+
const expected = triggers.map((object) => object.id).sort();
|
|
171
210
|
expect(functions.map((fn) => fn.id).sort()).to.deep.eq(expected);
|
|
172
211
|
});
|
|
173
212
|
|
|
174
213
|
test('event fired when a new trigger is added', async () => {
|
|
175
|
-
const client =
|
|
214
|
+
const [client] = await createInitializedClients(testBuilder);
|
|
176
215
|
const registry = createRegistry(client);
|
|
177
216
|
const space = await client.spaces.create();
|
|
178
217
|
|
|
@@ -182,16 +221,16 @@ describe('trigger registry', () => {
|
|
|
182
221
|
triggerRegistered.wake(fn.triggers[0]);
|
|
183
222
|
});
|
|
184
223
|
await registry.open(ctx);
|
|
185
|
-
await registry.register(space, { triggers:
|
|
224
|
+
await registry.register(space, { triggers: manifest?.triggers?.slice(0, 1) });
|
|
186
225
|
const registered = await triggerRegistered.wait();
|
|
187
|
-
expect(registered.function).to.eq(
|
|
226
|
+
expect(registered.function).to.eq(manifest.triggers![0].function);
|
|
188
227
|
});
|
|
189
228
|
|
|
190
229
|
test('event fired when a new trigger is removed', async () => {
|
|
191
|
-
const client =
|
|
230
|
+
const [client] = await createInitializedClients(testBuilder);
|
|
192
231
|
const registry = createRegistry(client);
|
|
193
232
|
const space = await client.spaces.create();
|
|
194
|
-
const triggers =
|
|
233
|
+
const triggers = createTriggers(space, 3);
|
|
195
234
|
|
|
196
235
|
const triggerLoaded = new Trigger();
|
|
197
236
|
registry.registered.on((fn) => triggerLoaded.wake());
|
|
@@ -201,7 +240,7 @@ describe('trigger registry', () => {
|
|
|
201
240
|
expect(fn.triggers.length).to.eq(1);
|
|
202
241
|
triggerRemoved.wake(fn.triggers[0]);
|
|
203
242
|
});
|
|
204
|
-
await registry.register(space,
|
|
243
|
+
await registry.register(space, manifest);
|
|
205
244
|
await registry.open(ctx);
|
|
206
245
|
await triggerLoaded.wait();
|
|
207
246
|
|
|
@@ -211,19 +250,23 @@ describe('trigger registry', () => {
|
|
|
211
250
|
});
|
|
212
251
|
});
|
|
213
252
|
|
|
214
|
-
const waitHasInactiveTriggers = async (registry: TriggerRegistry, space: Space) => {
|
|
215
|
-
await waitForCondition({ condition: () => registry.getInactiveTriggers(space).length > 0 });
|
|
216
|
-
};
|
|
217
|
-
|
|
218
253
|
const createRegistry = (client: Client) => {
|
|
219
254
|
const registry = new TriggerRegistry(client);
|
|
220
255
|
ctx.onDispose(() => registry.close());
|
|
221
256
|
return registry;
|
|
222
257
|
};
|
|
223
258
|
|
|
224
|
-
const
|
|
225
|
-
const triggers = range(count, () =>
|
|
226
|
-
|
|
259
|
+
const createTriggers = (space: Space, count: number) => {
|
|
260
|
+
const triggers = range(count, () => {
|
|
261
|
+
const { meta, object } = splitMeta(manifest.triggers![0]);
|
|
262
|
+
return create(FunctionTrigger, object, meta);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
triggers.forEach((trigger) => space.db.add(trigger));
|
|
227
266
|
return triggers;
|
|
228
267
|
};
|
|
268
|
+
|
|
269
|
+
const waitForInactiveTriggers = async (registry: TriggerRegistry, space: Space) => {
|
|
270
|
+
await waitForCondition({ condition: () => registry.getInactiveTriggers(space).length > 0 });
|
|
271
|
+
};
|
|
229
272
|
});
|