@dxos/functions 0.3.9-main.7b9e2ad → 0.3.9-main.8045d90
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 +35 -57
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +35 -57
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/handler.d.ts +0 -10
- package/dist/types/src/handler.d.ts.map +1 -1
- package/dist/types/src/runtime/scheduler.d.ts.map +1 -1
- package/package.json +9 -9
- package/src/handler.ts +0 -17
- package/src/runtime/dev-server.ts +1 -1
- package/src/runtime/scheduler.ts +0 -3
|
@@ -17,34 +17,12 @@ import {
|
|
|
17
17
|
// packages/core/functions/src/handler.ts
|
|
18
18
|
import { PublicKey } from "@dxos/client";
|
|
19
19
|
import { isTypedObject } from "@dxos/echo-schema";
|
|
20
|
-
import { log } from "@dxos/log";
|
|
21
20
|
import { nonNullable } from "@dxos/util";
|
|
22
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/functions/src/handler.ts";
|
|
23
21
|
var subscriptionHandler = (handler) => {
|
|
24
22
|
return ({ event, context, ...rest }) => {
|
|
25
23
|
const { client } = context;
|
|
26
24
|
const space = event.space ? client.spaces.get(PublicKey.from(event.space)) : void 0;
|
|
27
25
|
const objects = space && event.objects?.map((id) => space.db.getObjectById(id)).filter(nonNullable).filter(isTypedObject);
|
|
28
|
-
if (!!event.space && !space) {
|
|
29
|
-
log.warn("invalid space", {
|
|
30
|
-
event
|
|
31
|
-
}, {
|
|
32
|
-
F: __dxlog_file,
|
|
33
|
-
L: 64,
|
|
34
|
-
S: void 0,
|
|
35
|
-
C: (f, a) => f(...a)
|
|
36
|
-
});
|
|
37
|
-
} else {
|
|
38
|
-
log.info("handler", {
|
|
39
|
-
space: space?.key.truncate(),
|
|
40
|
-
objects: objects?.length
|
|
41
|
-
}, {
|
|
42
|
-
F: __dxlog_file,
|
|
43
|
-
L: 66,
|
|
44
|
-
S: void 0,
|
|
45
|
-
C: (f, a) => f(...a)
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
26
|
return handler({
|
|
49
27
|
event: {
|
|
50
28
|
space,
|
|
@@ -62,8 +40,8 @@ import { getPort } from "get-port-please";
|
|
|
62
40
|
import { join } from "@dxos/node-std/path";
|
|
63
41
|
import { Trigger } from "@dxos/async";
|
|
64
42
|
import { invariant } from "@dxos/invariant";
|
|
65
|
-
import { log
|
|
66
|
-
var
|
|
43
|
+
import { log } from "@dxos/log";
|
|
44
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/dev-server.ts";
|
|
67
45
|
var DevServer = class {
|
|
68
46
|
// prettier-ignore
|
|
69
47
|
constructor(_client, _options) {
|
|
@@ -74,7 +52,7 @@ var DevServer = class {
|
|
|
74
52
|
}
|
|
75
53
|
get endpoint() {
|
|
76
54
|
invariant(this._port, void 0, {
|
|
77
|
-
F:
|
|
55
|
+
F: __dxlog_file,
|
|
78
56
|
L: 46,
|
|
79
57
|
S: this,
|
|
80
58
|
A: [
|
|
@@ -95,8 +73,8 @@ var DevServer = class {
|
|
|
95
73
|
try {
|
|
96
74
|
await this._load(def);
|
|
97
75
|
} catch (err) {
|
|
98
|
-
|
|
99
|
-
F:
|
|
76
|
+
log.error("parsing function (check manifest)", err, {
|
|
77
|
+
F: __dxlog_file,
|
|
100
78
|
L: 63,
|
|
101
79
|
S: this,
|
|
102
80
|
C: (f, a) => f(...a)
|
|
@@ -117,8 +95,8 @@ var DevServer = class {
|
|
|
117
95
|
res.statusCode = await this._invoke(name, req.body);
|
|
118
96
|
res.end();
|
|
119
97
|
} catch (err) {
|
|
120
|
-
|
|
121
|
-
F:
|
|
98
|
+
log.catch(err, void 0, {
|
|
99
|
+
F: __dxlog_file,
|
|
122
100
|
L: 83,
|
|
123
101
|
S: this,
|
|
124
102
|
C: (f, a) => f(...a)
|
|
@@ -143,11 +121,11 @@ var DevServer = class {
|
|
|
143
121
|
name
|
|
144
122
|
}))
|
|
145
123
|
});
|
|
146
|
-
|
|
124
|
+
log.info("registered", {
|
|
147
125
|
registrationId,
|
|
148
126
|
endpoint
|
|
149
127
|
}, {
|
|
150
|
-
F:
|
|
128
|
+
F: __dxlog_file,
|
|
151
129
|
L: 99,
|
|
152
130
|
S: this,
|
|
153
131
|
C: (f, a) => f(...a)
|
|
@@ -166,10 +144,10 @@ var DevServer = class {
|
|
|
166
144
|
await this._client.services.services.FunctionRegistryService.unregister({
|
|
167
145
|
registrationId: this._registrationId
|
|
168
146
|
});
|
|
169
|
-
|
|
147
|
+
log.info("unregistered", {
|
|
170
148
|
registrationId: this._registrationId
|
|
171
149
|
}, {
|
|
172
|
-
F:
|
|
150
|
+
F: __dxlog_file,
|
|
173
151
|
L: 116,
|
|
174
152
|
S: this,
|
|
175
153
|
C: (f, a) => f(...a)
|
|
@@ -189,10 +167,10 @@ var DevServer = class {
|
|
|
189
167
|
async _load(def, flush = false) {
|
|
190
168
|
const { id, name, handler } = def;
|
|
191
169
|
const path = join(this._options.directory, handler);
|
|
192
|
-
|
|
170
|
+
log.info("loading", {
|
|
193
171
|
id
|
|
194
172
|
}, {
|
|
195
|
-
F:
|
|
173
|
+
F: __dxlog_file,
|
|
196
174
|
L: 135,
|
|
197
175
|
S: this,
|
|
198
176
|
C: (f, a) => f(...a)
|
|
@@ -215,11 +193,11 @@ var DevServer = class {
|
|
|
215
193
|
async _invoke(name, event) {
|
|
216
194
|
const seq = ++this._seq;
|
|
217
195
|
const now = Date.now();
|
|
218
|
-
|
|
196
|
+
log.info("req", {
|
|
219
197
|
seq,
|
|
220
198
|
name
|
|
221
199
|
}, {
|
|
222
|
-
F:
|
|
200
|
+
F: __dxlog_file,
|
|
223
201
|
L: 160,
|
|
224
202
|
S: this,
|
|
225
203
|
C: (f, a) => f(...a)
|
|
@@ -241,13 +219,13 @@ var DevServer = class {
|
|
|
241
219
|
event,
|
|
242
220
|
response
|
|
243
221
|
});
|
|
244
|
-
|
|
222
|
+
log.info("res", {
|
|
245
223
|
seq,
|
|
246
224
|
name,
|
|
247
225
|
statusCode,
|
|
248
226
|
duration: Date.now() - now
|
|
249
227
|
}, {
|
|
250
|
-
F:
|
|
228
|
+
F: __dxlog_file,
|
|
251
229
|
L: 177,
|
|
252
230
|
S: this,
|
|
253
231
|
C: (f, a) => f(...a)
|
|
@@ -263,9 +241,9 @@ import { TextObject } from "@dxos/client/echo";
|
|
|
263
241
|
import { Context } from "@dxos/context";
|
|
264
242
|
import { Filter, createSubscription, subscribe } from "@dxos/echo-schema";
|
|
265
243
|
import { invariant as invariant2 } from "@dxos/invariant";
|
|
266
|
-
import { log as
|
|
244
|
+
import { log as log2 } from "@dxos/log";
|
|
267
245
|
import { ComplexMap } from "@dxos/util";
|
|
268
|
-
var
|
|
246
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/scheduler.ts";
|
|
269
247
|
var Scheduler = class {
|
|
270
248
|
constructor(_client, _manifest, _options = {}) {
|
|
271
249
|
this._client = _client;
|
|
@@ -295,7 +273,7 @@ var Scheduler = class {
|
|
|
295
273
|
};
|
|
296
274
|
const def = this._manifest.functions.find((config) => config.id === trigger.function);
|
|
297
275
|
invariant2(def, `Function not found: ${trigger.function}`, {
|
|
298
|
-
F:
|
|
276
|
+
F: __dxlog_file2,
|
|
299
277
|
L: 63,
|
|
300
278
|
S: this,
|
|
301
279
|
A: [
|
|
@@ -309,11 +287,11 @@ var Scheduler = class {
|
|
|
309
287
|
ctx,
|
|
310
288
|
trigger
|
|
311
289
|
});
|
|
312
|
-
|
|
290
|
+
log2("mount", {
|
|
313
291
|
space: space.key,
|
|
314
292
|
trigger
|
|
315
293
|
}, {
|
|
316
|
-
F:
|
|
294
|
+
F: __dxlog_file2,
|
|
317
295
|
L: 69,
|
|
318
296
|
S: this,
|
|
319
297
|
C: (f, a) => f(...a)
|
|
@@ -347,7 +325,7 @@ var Scheduler = class {
|
|
|
347
325
|
});
|
|
348
326
|
});
|
|
349
327
|
invariant2(trigger.schedule, void 0, {
|
|
350
|
-
F:
|
|
328
|
+
F: __dxlog_file2,
|
|
351
329
|
L: 103,
|
|
352
330
|
S: this,
|
|
353
331
|
A: [
|
|
@@ -382,13 +360,13 @@ var Scheduler = class {
|
|
|
382
360
|
const update = ({ objects }) => {
|
|
383
361
|
subscription.update(objects);
|
|
384
362
|
if (deep) {
|
|
385
|
-
|
|
363
|
+
log2.info("update", {
|
|
386
364
|
type,
|
|
387
365
|
deep,
|
|
388
366
|
objects: objects.length
|
|
389
367
|
}, {
|
|
390
|
-
F:
|
|
391
|
-
L:
|
|
368
|
+
F: __dxlog_file2,
|
|
369
|
+
L: 139,
|
|
392
370
|
S: this,
|
|
393
371
|
C: (f, a) => f(...a)
|
|
394
372
|
});
|
|
@@ -410,11 +388,11 @@ var Scheduler = class {
|
|
|
410
388
|
}
|
|
411
389
|
async _execFunction(def, data) {
|
|
412
390
|
try {
|
|
413
|
-
|
|
391
|
+
log2("request", {
|
|
414
392
|
function: def.id
|
|
415
393
|
}, {
|
|
416
|
-
F:
|
|
417
|
-
L:
|
|
394
|
+
F: __dxlog_file2,
|
|
395
|
+
L: 161,
|
|
418
396
|
S: this,
|
|
419
397
|
C: (f, a) => f(...a)
|
|
420
398
|
});
|
|
@@ -432,22 +410,22 @@ var Scheduler = class {
|
|
|
432
410
|
} else if (callback) {
|
|
433
411
|
status = await callback(data);
|
|
434
412
|
}
|
|
435
|
-
|
|
413
|
+
log2("result", {
|
|
436
414
|
function: def.id,
|
|
437
415
|
result: status
|
|
438
416
|
}, {
|
|
439
|
-
F:
|
|
440
|
-
L:
|
|
417
|
+
F: __dxlog_file2,
|
|
418
|
+
L: 180,
|
|
441
419
|
S: this,
|
|
442
420
|
C: (f, a) => f(...a)
|
|
443
421
|
});
|
|
444
422
|
} catch (err) {
|
|
445
|
-
|
|
423
|
+
log2.error("error", {
|
|
446
424
|
function: def.id,
|
|
447
425
|
error: err.message
|
|
448
426
|
}, {
|
|
449
|
-
F:
|
|
450
|
-
L:
|
|
427
|
+
F: __dxlog_file2,
|
|
428
|
+
L: 182,
|
|
451
429
|
S: this,
|
|
452
430
|
C: (f, a) => f(...a)
|
|
453
431
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/handler.ts", "../../../src/runtime/dev-server.ts", "../../../src/runtime/scheduler.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Client, PublicKey } from '@dxos/client';\nimport { type Space } from '@dxos/client/echo';\nimport { isTypedObject, type TypedObject } from '@dxos/echo-schema';\nimport { log } from '@dxos/log';\nimport { nonNullable } from '@dxos/util';\n\n// TODO(burdon): No response?\nexport interface Response {\n status(code: number): Response;\n}\n\n// TODO(burdon): Limit access to individual space?\nexport interface FunctionContext {\n client: Client;\n dataDir?: string;\n}\n\n// TODO(burdon): Model after http request. Ref Lambda/OpenFaaS.\n// https://docs.aws.amazon.com/lambda/latest/dg/typescript-handler.html\nexport type FunctionHandler<T extends {}> = (params: {\n event: T;\n context: FunctionContext;\n response: Response;\n}) => Promise<Response | void>;\n\nexport type FunctionSubscriptionEvent = {\n space?: string; // TODO(burdon): Convert to PublicKey.\n objects?: string[];\n};\n\nexport type FunctionSubscriptionEvent2 = {\n space?: Space;\n objects?: TypedObject[];\n};\n\n/**\n * Handler wrapper for subscription events; extracts space and objects.\n *\n * To test:\n * ```\n * curl -s -X POST -H \"Content-Type: application/json\" --data '{\"space\": \"0446...1cbb\"}' http://localhost:7100/dev/email-extractor\n * ```\n *\n * NOTE: Get space key from devtools or `dx space list --json`\n */\nexport const subscriptionHandler = (\n handler: FunctionHandler<FunctionSubscriptionEvent2>,\n): FunctionHandler<FunctionSubscriptionEvent> => {\n return ({ event, context, ...rest }) => {\n const { client } = context;\n const space = event.space ? client.spaces.get(PublicKey.from(event.space)) : undefined;\n const objects =\n space &&\n event.objects\n ?.map<TypedObject | undefined>((id) => space!.db.getObjectById(id))\n .filter(nonNullable)\n .filter(isTypedObject);\n\n if (!!event.space && !space) {\n log.warn('invalid space', { event });\n } else {\n log.info('handler', { space: space?.key.truncate(), objects: objects?.length });\n }\n\n return handler({ event: { space, objects }, context, ...rest });\n };\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport express from 'express';\nimport { getPort } from 'get-port-please';\nimport type http from 'http';\nimport { join } from 'node:path';\n\nimport { Trigger } from '@dxos/async';\nimport { type Client } from '@dxos/client';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\n\nimport { type FunctionContext, type FunctionHandler, type Response } from '../handler';\nimport { type FunctionDef, type FunctionManifest } from '../manifest';\n\nexport type DevServerOptions = {\n port?: number;\n directory: string;\n manifest: FunctionManifest;\n reload?: boolean;\n dataDir?: string;\n};\n\n/**\n * Functions dev server provides a local HTTP server for testing functions.\n */\nexport class DevServer {\n // Function handlers indexed by name (URL path).\n private readonly _handlers: Record<string, { def: FunctionDef; handler: FunctionHandler<any> }> = {};\n\n private _server?: http.Server;\n private _port?: number;\n private _registrationId?: string;\n private _proxy?: string;\n private _seq = 0;\n\n // prettier-ignore\n constructor(\n private readonly _client: Client,\n private readonly _options: DevServerOptions,\n ) {}\n\n get endpoint() {\n invariant(this._port);\n return `http://localhost:${this._port}`;\n }\n\n get proxy() {\n return this._proxy;\n }\n\n get functions() {\n return Object.values(this._handlers);\n }\n\n async initialize() {\n for (const def of this._options.manifest.functions) {\n try {\n await this._load(def);\n } catch (err) {\n log.error('parsing function (check manifest)', err);\n }\n }\n }\n\n async start() {\n const app = express();\n app.use(express.json());\n\n app.post('/:name', async (req, res) => {\n const { name } = req.params;\n try {\n if (this._options.reload) {\n const { def } = this._handlers[name];\n await this._load(def, true);\n }\n\n res.statusCode = await this._invoke(name, req.body);\n res.end();\n } catch (err: any) {\n log.error(`Function failed: ${name}`, err);\n res.statusCode = 500;\n res.end();\n }\n });\n\n this._port = await getPort({ host: 'localhost', port: 7200, portRange: [7200, 7299] });\n this._server = app.listen(this._port);\n\n try {\n // Register functions.\n const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService!.register({\n endpoint: this.endpoint,\n functions: this.functions.map(({ def: { name } }) => ({ name })),\n });\n\n log.info('registered', { registrationId, endpoint });\n this._registrationId = registrationId;\n this._proxy = endpoint;\n } catch (err: any) {\n await this.stop();\n throw new Error('FunctionRegistryService not available (check plugin is configured).');\n }\n }\n\n async stop() {\n const trigger = new Trigger();\n this._server?.close(async () => {\n if (this._registrationId) {\n await this._client.services.services.FunctionRegistryService!.unregister({\n registrationId: this._registrationId,\n });\n\n log.info('unregistered', { registrationId: this._registrationId });\n this._registrationId = undefined;\n this._proxy = undefined;\n }\n\n trigger.wake();\n });\n\n await trigger.wait();\n this._port = undefined;\n this._server = undefined;\n }\n\n /**\n * Load function.\n */\n private async _load(def: FunctionDef, flush = false) {\n const { id, name, handler } = def;\n const path = join(this._options.directory, handler);\n log.info('loading', { id });\n\n // Remove from cache.\n if (flush) {\n Object.keys(require.cache)\n .filter((key) => key.startsWith(path))\n .forEach((key) => delete require.cache[key]);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const module = require(path);\n if (typeof module.default !== 'function') {\n throw new Error(`Handler must export default function: ${id}`);\n }\n\n this._handlers[name] = { def, handler: module.default };\n }\n\n /**\n * Invoke function handler.\n */\n private async _invoke(name: string, event: any) {\n const seq = ++this._seq;\n const now = Date.now();\n\n log.info('req', { seq, name });\n const { handler } = this._handlers[name];\n\n const context: FunctionContext = {\n client: this._client,\n dataDir: this._options.dataDir,\n };\n\n let statusCode = 200;\n const response: Response = {\n status: (code: number) => {\n statusCode = code;\n return response;\n },\n };\n\n await handler({ context, event, response });\n log.info('res', { seq, name, statusCode, duration: Date.now() - now });\n\n return statusCode;\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { CronJob } from 'cron';\n\nimport { debounce, DeferredTask } from '@dxos/async';\nimport { type Client, type PublicKey } from '@dxos/client';\nimport { type Space, TextObject } from '@dxos/client/echo';\nimport { Context } from '@dxos/context';\nimport { Filter, createSubscription, type Query, subscribe } from '@dxos/echo-schema';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { ComplexMap } from '@dxos/util';\n\nimport { type FunctionSubscriptionEvent } from '../handler';\nimport { type FunctionDef, type FunctionManifest, type FunctionTrigger, type TriggerSubscription } from '../manifest';\n\ntype Callback = (data: FunctionSubscriptionEvent) => Promise<number>;\n\ntype SchedulerOptions = {\n endpoint?: string;\n callback?: Callback;\n};\n\n/**\n * Functions scheduler.\n */\n// TODO(burdon): Create tests.\nexport class Scheduler {\n // Map of mounted functions.\n private readonly _mounts = new ComplexMap<\n { id: string; spaceKey: PublicKey },\n { ctx: Context; trigger: FunctionTrigger }\n >(({ id, spaceKey }) => `${spaceKey.toHex()}:${id}`);\n\n constructor(\n private readonly _client: Client,\n private readonly _manifest: FunctionManifest,\n private readonly _options: SchedulerOptions = {},\n ) {}\n\n async start() {\n this._client.spaces.subscribe(async (spaces) => {\n for (const space of spaces) {\n await space.waitUntilReady();\n for (const trigger of this._manifest.triggers ?? []) {\n await this.mount(new Context(), space, trigger);\n }\n }\n });\n }\n\n async stop() {\n for (const { id, spaceKey } of this._mounts.keys()) {\n await this.unmount(id, spaceKey);\n }\n }\n\n private async mount(ctx: Context, space: Space, trigger: FunctionTrigger) {\n const key = { id: trigger.function, spaceKey: space.key };\n const def = this._manifest.functions.find((config) => config.id === trigger.function);\n invariant(def, `Function not found: ${trigger.function}`);\n\n // Currently supports only one trigger declaration per function.\n const exists = this._mounts.get(key);\n if (!exists) {\n this._mounts.set(key, { ctx, trigger });\n log('mount', { space: space.key, trigger });\n if (ctx.disposed) {\n return;\n }\n\n // Timer.\n if (trigger.schedule) {\n this._createTimer(ctx, space, def, trigger);\n }\n\n // Subscription.\n for (const triggerSubscription of trigger.subscriptions ?? []) {\n this._createSubscription(ctx, space, def, triggerSubscription);\n }\n }\n }\n\n private async unmount(id: string, spaceKey: PublicKey) {\n const key = { id, spaceKey };\n const { ctx } = this._mounts.get(key) ?? {};\n if (ctx) {\n this._mounts.delete(key);\n await ctx.dispose();\n }\n }\n\n private _createTimer(ctx: Context, space: Space, def: FunctionDef, trigger: FunctionTrigger) {\n const task = new DeferredTask(ctx, async () => {\n await this._execFunction(def, {\n space: space.key,\n });\n });\n\n // TODO(burdon): Check greater than 30s min (use cron-parser).\n invariant(trigger.schedule);\n const job = new CronJob(trigger.schedule, () => task.schedule());\n\n job.start();\n ctx.onDispose(() => job.stop());\n }\n\n private _createSubscription(ctx: Context, space: Space, def: FunctionDef, triggerSubscription: TriggerSubscription) {\n const objectIds = new Set<string>();\n const task = new DeferredTask(ctx, async () => {\n await this._execFunction(def, {\n space: space.key,\n objects: Array.from(objectIds),\n });\n });\n\n // TODO(burdon): Don't fire initially.\n // TODO(burdon): Standardize subscription handles.\n const subscriptions: (() => void)[] = [];\n const subscription = createSubscription(({ added, updated }) => {\n for (const object of added) {\n objectIds.add(object.id);\n }\n for (const object of updated) {\n objectIds.add(object.id);\n }\n\n task.schedule();\n });\n subscriptions.push(() => subscription.unsubscribe());\n\n // TODO(burdon): Create queue. Only allow one invocation per trigger at a time?\n // TODO(burdon): Disable trigger if keeps failing.\n const { type, props, deep, delay } = triggerSubscription;\n const update = ({ objects }: Query) => {\n subscription.update(objects);\n\n // TODO(burdon): Hack to monitor changes to Document's text object.\n if (deep) {\n log.info('update', { type, deep, objects: objects.length });\n for (const object of objects) {\n const content = object.content;\n if (content instanceof TextObject) {\n subscriptions.push(content[subscribe](debounce(() => subscription.update([object]), 1_000)));\n }\n }\n }\n };\n\n // TODO(burdon): [Bug]: all callbacks are fired on the first mutation.\n // TODO(burdon): [Bug]: not updated when document is deleted (either top or hierarchically).\n const query = space.db.query(Filter.typename(type, props));\n subscriptions.push(query.subscribe(delay ? debounce(update, delay * 1_000) : update));\n\n ctx.onDispose(() => {\n subscriptions.forEach((unsubscribe) => unsubscribe());\n });\n }\n\n private async _execFunction(def: FunctionDef, data: any) {\n try {\n log('request', { function: def.id });\n const { endpoint, callback } = this._options;\n let status = 0;\n if (endpoint) {\n // TODO(burdon): Move out of scheduler (generalize as callback).\n const response = await fetch(`${this._options.endpoint}/${def.name}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(data),\n });\n\n status = response.status;\n } else if (callback) {\n status = await callback(data);\n }\n\n // const result = await response.json();\n log('result', { function: def.id, result: status });\n } catch (err: any) {\n log.error('error', { function: def.id, error: err.message });\n }\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;AAIA,SAAsBA,iBAAiB;AAEvC,SAASC,qBAAuC;AAChD,SAASC,
|
|
6
|
-
"names": ["PublicKey", "isTypedObject", "
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Client, PublicKey } from '@dxos/client';\nimport { type Space } from '@dxos/client/echo';\nimport { isTypedObject, type TypedObject } from '@dxos/echo-schema';\nimport { nonNullable } from '@dxos/util';\n\n// TODO(burdon): No response?\nexport interface Response {\n status(code: number): Response;\n}\n\n// TODO(burdon): Limit access to individual space?\nexport interface FunctionContext {\n client: Client;\n dataDir?: string;\n}\n\n// TODO(burdon): Model after http request. Ref Lambda/OpenFaaS.\n// https://docs.aws.amazon.com/lambda/latest/dg/typescript-handler.html\nexport type FunctionHandler<T extends {}> = (params: {\n event: T;\n context: FunctionContext;\n response: Response;\n}) => Promise<Response | void>;\n\nexport type FunctionSubscriptionEvent = {\n space?: string; // TODO(burdon): Convert to PublicKey.\n objects?: string[];\n};\n\nexport type FunctionSubscriptionEvent2 = {\n space?: Space;\n objects?: TypedObject[];\n};\n\nexport const subscriptionHandler = (\n handler: FunctionHandler<FunctionSubscriptionEvent2>,\n): FunctionHandler<FunctionSubscriptionEvent> => {\n return ({ event, context, ...rest }) => {\n const { client } = context;\n const space = event.space ? client.spaces.get(PublicKey.from(event.space)) : undefined;\n const objects =\n space &&\n event.objects\n ?.map<TypedObject | undefined>((id) => space!.db.getObjectById(id))\n .filter(nonNullable)\n .filter(isTypedObject);\n\n return handler({ event: { space, objects }, context, ...rest });\n };\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport express from 'express';\nimport { getPort } from 'get-port-please';\nimport type http from 'http';\nimport { join } from 'node:path';\n\nimport { Trigger } from '@dxos/async';\nimport { type Client } from '@dxos/client';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\n\nimport { type FunctionContext, type FunctionHandler, type Response } from '../handler';\nimport { type FunctionDef, type FunctionManifest } from '../manifest';\n\nexport type DevServerOptions = {\n port?: number;\n directory: string;\n manifest: FunctionManifest;\n reload?: boolean;\n dataDir?: string;\n};\n\n/**\n * Functions dev server provides a local HTTP server for testing functions.\n */\nexport class DevServer {\n // Function handlers indexed by name (URL path).\n private readonly _handlers: Record<string, { def: FunctionDef; handler: FunctionHandler<any> }> = {};\n\n private _server?: http.Server;\n private _port?: number;\n private _registrationId?: string;\n private _proxy?: string;\n private _seq = 0;\n\n // prettier-ignore\n constructor(\n private readonly _client: Client,\n private readonly _options: DevServerOptions,\n ) {}\n\n get endpoint() {\n invariant(this._port);\n return `http://localhost:${this._port}`;\n }\n\n get proxy() {\n return this._proxy;\n }\n\n get functions() {\n return Object.values(this._handlers);\n }\n\n async initialize() {\n for (const def of this._options.manifest.functions) {\n try {\n await this._load(def);\n } catch (err) {\n log.error('parsing function (check manifest)', err);\n }\n }\n }\n\n async start() {\n const app = express();\n app.use(express.json());\n\n app.post('/:name', async (req, res) => {\n const { name } = req.params;\n try {\n if (this._options.reload) {\n const { def } = this._handlers[name];\n await this._load(def, true);\n }\n\n res.statusCode = await this._invoke(name, req.body);\n res.end();\n } catch (err: any) {\n log.catch(err);\n res.statusCode = 500;\n res.end();\n }\n });\n\n this._port = await getPort({ host: 'localhost', port: 7200, portRange: [7200, 7299] });\n this._server = app.listen(this._port);\n\n try {\n // Register functions.\n const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService!.register({\n endpoint: this.endpoint,\n functions: this.functions.map(({ def: { name } }) => ({ name })),\n });\n\n log.info('registered', { registrationId, endpoint });\n this._registrationId = registrationId;\n this._proxy = endpoint;\n } catch (err: any) {\n await this.stop();\n throw new Error('FunctionRegistryService not available (check plugin is configured).');\n }\n }\n\n async stop() {\n const trigger = new Trigger();\n this._server?.close(async () => {\n if (this._registrationId) {\n await this._client.services.services.FunctionRegistryService!.unregister({\n registrationId: this._registrationId,\n });\n\n log.info('unregistered', { registrationId: this._registrationId });\n this._registrationId = undefined;\n this._proxy = undefined;\n }\n\n trigger.wake();\n });\n\n await trigger.wait();\n this._port = undefined;\n this._server = undefined;\n }\n\n /**\n * Load function.\n */\n private async _load(def: FunctionDef, flush = false) {\n const { id, name, handler } = def;\n const path = join(this._options.directory, handler);\n log.info('loading', { id });\n\n // Remove from cache.\n if (flush) {\n Object.keys(require.cache)\n .filter((key) => key.startsWith(path))\n .forEach((key) => delete require.cache[key]);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const module = require(path);\n if (typeof module.default !== 'function') {\n throw new Error(`Handler must export default function: ${id}`);\n }\n\n this._handlers[name] = { def, handler: module.default };\n }\n\n /**\n * Invoke function handler.\n */\n private async _invoke(name: string, event: any) {\n const seq = ++this._seq;\n const now = Date.now();\n\n log.info('req', { seq, name });\n const { handler } = this._handlers[name];\n\n const context: FunctionContext = {\n client: this._client,\n dataDir: this._options.dataDir,\n };\n\n let statusCode = 200;\n const response: Response = {\n status: (code: number) => {\n statusCode = code;\n return response;\n },\n };\n\n await handler({ context, event, response });\n log.info('res', { seq, name, statusCode, duration: Date.now() - now });\n\n return statusCode;\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { CronJob } from 'cron';\n\nimport { debounce, DeferredTask } from '@dxos/async';\nimport { type Client, type PublicKey } from '@dxos/client';\nimport { type Space, TextObject } from '@dxos/client/echo';\nimport { Context } from '@dxos/context';\nimport { Filter, createSubscription, type Query, subscribe } from '@dxos/echo-schema';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { ComplexMap } from '@dxos/util';\n\nimport { type FunctionSubscriptionEvent } from '../handler';\nimport { type FunctionDef, type FunctionManifest, type FunctionTrigger, type TriggerSubscription } from '../manifest';\n\ntype Callback = (data: FunctionSubscriptionEvent) => Promise<number>;\n\ntype SchedulerOptions = {\n endpoint?: string;\n callback?: Callback;\n};\n\n/**\n * Functions scheduler.\n */\n// TODO(burdon): Create tests.\nexport class Scheduler {\n // Map of mounted functions.\n private readonly _mounts = new ComplexMap<\n { id: string; spaceKey: PublicKey },\n { ctx: Context; trigger: FunctionTrigger }\n >(({ id, spaceKey }) => `${spaceKey.toHex()}:${id}`);\n\n constructor(\n private readonly _client: Client,\n private readonly _manifest: FunctionManifest,\n private readonly _options: SchedulerOptions = {},\n ) {}\n\n async start() {\n this._client.spaces.subscribe(async (spaces) => {\n for (const space of spaces) {\n await space.waitUntilReady();\n for (const trigger of this._manifest.triggers ?? []) {\n await this.mount(new Context(), space, trigger);\n }\n }\n });\n }\n\n async stop() {\n for (const { id, spaceKey } of this._mounts.keys()) {\n await this.unmount(id, spaceKey);\n }\n }\n\n private async mount(ctx: Context, space: Space, trigger: FunctionTrigger) {\n const key = { id: trigger.function, spaceKey: space.key };\n const def = this._manifest.functions.find((config) => config.id === trigger.function);\n invariant(def, `Function not found: ${trigger.function}`);\n\n // Currently supports only one trigger declaration per function.\n const exists = this._mounts.get(key);\n if (!exists) {\n this._mounts.set(key, { ctx, trigger });\n log('mount', { space: space.key, trigger });\n if (ctx.disposed) {\n return;\n }\n\n // Timer.\n if (trigger.schedule) {\n this._createTimer(ctx, space, def, trigger);\n }\n\n // Subscription.\n for (const triggerSubscription of trigger.subscriptions ?? []) {\n this._createSubscription(ctx, space, def, triggerSubscription);\n }\n }\n }\n\n private async unmount(id: string, spaceKey: PublicKey) {\n const key = { id, spaceKey };\n const { ctx } = this._mounts.get(key) ?? {};\n if (ctx) {\n this._mounts.delete(key);\n await ctx.dispose();\n }\n }\n\n private _createTimer(ctx: Context, space: Space, def: FunctionDef, trigger: FunctionTrigger) {\n const task = new DeferredTask(ctx, async () => {\n await this._execFunction(def, {\n space: space.key,\n });\n });\n\n // TODO(burdon): Check greater than 30s min (use cron-parser).\n invariant(trigger.schedule);\n const job = new CronJob(trigger.schedule, () => task.schedule());\n\n job.start();\n ctx.onDispose(() => job.stop());\n }\n\n private _createSubscription(ctx: Context, space: Space, def: FunctionDef, triggerSubscription: TriggerSubscription) {\n const objectIds = new Set<string>();\n const task = new DeferredTask(ctx, async () => {\n await this._execFunction(def, {\n space: space.key,\n objects: Array.from(objectIds),\n });\n });\n\n // TODO(burdon): Standardize subscription handles.\n const subscriptions: (() => void)[] = [];\n const subscription = createSubscription(({ added, updated }) => {\n for (const object of added) {\n objectIds.add(object.id);\n }\n for (const object of updated) {\n objectIds.add(object.id);\n }\n\n task.schedule();\n });\n subscriptions.push(() => subscription.unsubscribe());\n\n const { type, props, deep, delay } = triggerSubscription;\n const update = ({ objects }: Query) => {\n subscription.update(objects);\n\n // TODO(burdon): Hack to monitor changes to Document's text object.\n if (deep) {\n log.info('update', { type, deep, objects: objects.length });\n for (const object of objects) {\n const content = object.content;\n if (content instanceof TextObject) {\n subscriptions.push(content[subscribe](debounce(() => subscription.update([object]), 1_000)));\n }\n }\n }\n };\n\n // TODO(burdon): [Bug]: all callbacks are fired on the first mutation.\n // TODO(burdon): [Bug]: not updated when document is deleted (either top or hierarchically).\n const query = space.db.query(Filter.typename(type, props));\n subscriptions.push(query.subscribe(delay ? debounce(update, delay * 1_000) : update));\n\n ctx.onDispose(() => {\n subscriptions.forEach((unsubscribe) => unsubscribe());\n });\n }\n\n private async _execFunction(def: FunctionDef, data: any) {\n try {\n log('request', { function: def.id });\n const { endpoint, callback } = this._options;\n let status = 0;\n if (endpoint) {\n // TODO(burdon): Move out of scheduler (generalize as callback).\n const response = await fetch(`${this._options.endpoint}/${def.name}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(data),\n });\n\n status = response.status;\n } else if (callback) {\n status = await callback(data);\n }\n\n // const result = await response.json();\n log('result', { function: def.id, result: status });\n } catch (err: any) {\n log.error('error', { function: def.id, error: err.message });\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["PublicKey", "isTypedObject", "nonNullable", "subscriptionHandler", "handler", "event", "context", "rest", "client", "space", "spaces", "get", "PublicKey", "from", "undefined", "objects", "map", "id", "db", "getObjectById", "filter", "nonNullable", "isTypedObject", "express", "getPort", "join", "Trigger", "invariant", "log", "DevServer", "constructor", "_client", "_options", "_handlers", "_seq", "endpoint", "invariant", "_port", "proxy", "_proxy", "functions", "Object", "values", "initialize", "def", "manifest", "_load", "err", "log", "error", "start", "app", "express", "use", "json", "post", "req", "res", "name", "params", "reload", "statusCode", "_invoke", "body", "end", "catch", "getPort", "host", "port", "portRange", "_server", "listen", "registrationId", "services", "FunctionRegistryService", "register", "map", "info", "_registrationId", "stop", "Error", "trigger", "Trigger", "close", "unregister", "undefined", "wake", "wait", "flush", "id", "handler", "path", "join", "directory", "keys", "require", "cache", "filter", "key", "startsWith", "forEach", "module", "default", "event", "seq", "now", "Date", "context", "client", "dataDir", "response", "status", "code", "duration", "CronJob", "debounce", "DeferredTask", "TextObject", "Context", "Filter", "createSubscription", "subscribe", "invariant", "log", "ComplexMap", "Scheduler", "constructor", "_client", "_manifest", "_options", "_mounts", "id", "spaceKey", "toHex", "start", "spaces", "space", "waitUntilReady", "trigger", "triggers", "mount", "stop", "keys", "unmount", "ctx", "key", "function", "def", "functions", "find", "config", "exists", "get", "set", "disposed", "schedule", "_createTimer", "triggerSubscription", "subscriptions", "_createSubscription", "delete", "dispose", "task", "_execFunction", "job", "onDispose", "objectIds", "Set", "objects", "Array", "from", "subscription", "added", "updated", "object", "add", "push", "unsubscribe", "type", "props", "deep", "delay", "update", "info", "length", "content", "query", "db", "typename", "forEach", "data", "endpoint", "callback", "status", "response", "fetch", "name", "method", "headers", "body", "JSON", "stringify", "result", "err", "error", "message"]
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"inject-globals:@inject-globals":{"bytes":384,"imports":[{"path":"@dxos/node-std/inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/handler.ts":{"bytes":
|
|
1
|
+
{"inputs":{"inject-globals:@inject-globals":{"bytes":384,"imports":[{"path":"@dxos/node-std/inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/handler.ts":{"bytes":4072,"imports":[{"path":"@dxos/client","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/manifest.ts":{"bytes":1863,"imports":[{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/dev-server.ts":{"bytes":18840,"imports":[{"path":"express","kind":"import-statement","external":true},{"path":"get-port-please","kind":"import-statement","external":true},{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@inject-globals","kind":"import-statement","external":true},{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/scheduler.ts":{"bytes":22471,"imports":[{"path":"cron","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/client/echo","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/index.ts":{"bytes":566,"imports":[{"path":"packages/core/functions/src/runtime/dev-server.ts","kind":"import-statement","original":"./dev-server"},{"path":"packages/core/functions/src/runtime/scheduler.ts","kind":"import-statement","original":"./scheduler"},{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/index.ts":{"bytes":637,"imports":[{"path":"packages/core/functions/src/handler.ts","kind":"import-statement","original":"./handler"},{"path":"packages/core/functions/src/manifest.ts","kind":"import-statement","original":"./manifest"},{"path":"packages/core/functions/src/runtime/index.ts","kind":"import-statement","original":"./runtime"},{"path":"@inject-globals","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"packages/core/functions/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":21917},"packages/core/functions/dist/lib/browser/index.mjs":{"imports":[{"path":"@dxos/node-std/inject-globals","kind":"import-statement","external":true},{"path":"@dxos/client","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"express","kind":"import-statement","external":true},{"path":"get-port-please","kind":"import-statement","external":true},{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"cron","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/client/echo","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["DevServer","Scheduler","subscriptionHandler"],"entryPoint":"packages/core/functions/src/index.ts","inputs":{"inject-globals:@inject-globals":{"bytesInOutput":90},"packages/core/functions/src/handler.ts":{"bytesInOutput":589},"packages/core/functions/src/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/dev-server.ts":{"bytesInOutput":4802},"packages/core/functions/src/runtime/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/scheduler.ts":{"bytesInOutput":5475}},"bytes":11638}}}
|
package/dist/lib/node/index.cjs
CHANGED
|
@@ -35,21 +35,20 @@ __export(node_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(node_exports);
|
|
36
36
|
var import_client = require("@dxos/client");
|
|
37
37
|
var import_echo_schema = require("@dxos/echo-schema");
|
|
38
|
-
var import_log = require("@dxos/log");
|
|
39
38
|
var import_util = require("@dxos/util");
|
|
40
39
|
var import_express = __toESM(require("express"));
|
|
41
40
|
var import_get_port_please = require("get-port-please");
|
|
42
41
|
var import_node_path = require("node:path");
|
|
43
42
|
var import_async = require("@dxos/async");
|
|
44
43
|
var import_invariant = require("@dxos/invariant");
|
|
45
|
-
var
|
|
44
|
+
var import_log = require("@dxos/log");
|
|
46
45
|
var import_cron = require("cron");
|
|
47
46
|
var import_async2 = require("@dxos/async");
|
|
48
47
|
var import_echo = require("@dxos/client/echo");
|
|
49
48
|
var import_context = require("@dxos/context");
|
|
50
49
|
var import_echo_schema2 = require("@dxos/echo-schema");
|
|
51
50
|
var import_invariant2 = require("@dxos/invariant");
|
|
52
|
-
var
|
|
51
|
+
var import_log2 = require("@dxos/log");
|
|
53
52
|
var import_util2 = require("@dxos/util");
|
|
54
53
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
55
54
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
@@ -58,32 +57,11 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
58
57
|
return require.apply(this, arguments);
|
|
59
58
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
60
59
|
});
|
|
61
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/functions/src/handler.ts";
|
|
62
60
|
var subscriptionHandler = (handler) => {
|
|
63
61
|
return ({ event, context, ...rest }) => {
|
|
64
62
|
const { client } = context;
|
|
65
63
|
const space = event.space ? client.spaces.get(import_client.PublicKey.from(event.space)) : void 0;
|
|
66
64
|
const objects = space && event.objects?.map((id) => space.db.getObjectById(id)).filter(import_util.nonNullable).filter(import_echo_schema.isTypedObject);
|
|
67
|
-
if (!!event.space && !space) {
|
|
68
|
-
import_log.log.warn("invalid space", {
|
|
69
|
-
event
|
|
70
|
-
}, {
|
|
71
|
-
F: __dxlog_file,
|
|
72
|
-
L: 64,
|
|
73
|
-
S: void 0,
|
|
74
|
-
C: (f, a) => f(...a)
|
|
75
|
-
});
|
|
76
|
-
} else {
|
|
77
|
-
import_log.log.info("handler", {
|
|
78
|
-
space: space?.key.truncate(),
|
|
79
|
-
objects: objects?.length
|
|
80
|
-
}, {
|
|
81
|
-
F: __dxlog_file,
|
|
82
|
-
L: 66,
|
|
83
|
-
S: void 0,
|
|
84
|
-
C: (f, a) => f(...a)
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
65
|
return handler({
|
|
88
66
|
event: {
|
|
89
67
|
space,
|
|
@@ -94,7 +72,7 @@ var subscriptionHandler = (handler) => {
|
|
|
94
72
|
});
|
|
95
73
|
};
|
|
96
74
|
};
|
|
97
|
-
var
|
|
75
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/dev-server.ts";
|
|
98
76
|
var DevServer = class {
|
|
99
77
|
// prettier-ignore
|
|
100
78
|
constructor(_client, _options) {
|
|
@@ -105,7 +83,7 @@ var DevServer = class {
|
|
|
105
83
|
}
|
|
106
84
|
get endpoint() {
|
|
107
85
|
(0, import_invariant.invariant)(this._port, void 0, {
|
|
108
|
-
F:
|
|
86
|
+
F: __dxlog_file,
|
|
109
87
|
L: 46,
|
|
110
88
|
S: this,
|
|
111
89
|
A: [
|
|
@@ -126,8 +104,8 @@ var DevServer = class {
|
|
|
126
104
|
try {
|
|
127
105
|
await this._load(def);
|
|
128
106
|
} catch (err) {
|
|
129
|
-
|
|
130
|
-
F:
|
|
107
|
+
import_log.log.error("parsing function (check manifest)", err, {
|
|
108
|
+
F: __dxlog_file,
|
|
131
109
|
L: 63,
|
|
132
110
|
S: this,
|
|
133
111
|
C: (f, a) => f(...a)
|
|
@@ -148,8 +126,8 @@ var DevServer = class {
|
|
|
148
126
|
res.statusCode = await this._invoke(name, req.body);
|
|
149
127
|
res.end();
|
|
150
128
|
} catch (err) {
|
|
151
|
-
|
|
152
|
-
F:
|
|
129
|
+
import_log.log.catch(err, void 0, {
|
|
130
|
+
F: __dxlog_file,
|
|
153
131
|
L: 83,
|
|
154
132
|
S: this,
|
|
155
133
|
C: (f, a) => f(...a)
|
|
@@ -174,11 +152,11 @@ var DevServer = class {
|
|
|
174
152
|
name
|
|
175
153
|
}))
|
|
176
154
|
});
|
|
177
|
-
|
|
155
|
+
import_log.log.info("registered", {
|
|
178
156
|
registrationId,
|
|
179
157
|
endpoint
|
|
180
158
|
}, {
|
|
181
|
-
F:
|
|
159
|
+
F: __dxlog_file,
|
|
182
160
|
L: 99,
|
|
183
161
|
S: this,
|
|
184
162
|
C: (f, a) => f(...a)
|
|
@@ -197,10 +175,10 @@ var DevServer = class {
|
|
|
197
175
|
await this._client.services.services.FunctionRegistryService.unregister({
|
|
198
176
|
registrationId: this._registrationId
|
|
199
177
|
});
|
|
200
|
-
|
|
178
|
+
import_log.log.info("unregistered", {
|
|
201
179
|
registrationId: this._registrationId
|
|
202
180
|
}, {
|
|
203
|
-
F:
|
|
181
|
+
F: __dxlog_file,
|
|
204
182
|
L: 116,
|
|
205
183
|
S: this,
|
|
206
184
|
C: (f, a) => f(...a)
|
|
@@ -220,10 +198,10 @@ var DevServer = class {
|
|
|
220
198
|
async _load(def, flush = false) {
|
|
221
199
|
const { id, name, handler } = def;
|
|
222
200
|
const path = (0, import_node_path.join)(this._options.directory, handler);
|
|
223
|
-
|
|
201
|
+
import_log.log.info("loading", {
|
|
224
202
|
id
|
|
225
203
|
}, {
|
|
226
|
-
F:
|
|
204
|
+
F: __dxlog_file,
|
|
227
205
|
L: 135,
|
|
228
206
|
S: this,
|
|
229
207
|
C: (f, a) => f(...a)
|
|
@@ -246,11 +224,11 @@ var DevServer = class {
|
|
|
246
224
|
async _invoke(name, event) {
|
|
247
225
|
const seq = ++this._seq;
|
|
248
226
|
const now = Date.now();
|
|
249
|
-
|
|
227
|
+
import_log.log.info("req", {
|
|
250
228
|
seq,
|
|
251
229
|
name
|
|
252
230
|
}, {
|
|
253
|
-
F:
|
|
231
|
+
F: __dxlog_file,
|
|
254
232
|
L: 160,
|
|
255
233
|
S: this,
|
|
256
234
|
C: (f, a) => f(...a)
|
|
@@ -272,13 +250,13 @@ var DevServer = class {
|
|
|
272
250
|
event,
|
|
273
251
|
response
|
|
274
252
|
});
|
|
275
|
-
|
|
253
|
+
import_log.log.info("res", {
|
|
276
254
|
seq,
|
|
277
255
|
name,
|
|
278
256
|
statusCode,
|
|
279
257
|
duration: Date.now() - now
|
|
280
258
|
}, {
|
|
281
|
-
F:
|
|
259
|
+
F: __dxlog_file,
|
|
282
260
|
L: 177,
|
|
283
261
|
S: this,
|
|
284
262
|
C: (f, a) => f(...a)
|
|
@@ -286,7 +264,7 @@ var DevServer = class {
|
|
|
286
264
|
return statusCode;
|
|
287
265
|
}
|
|
288
266
|
};
|
|
289
|
-
var
|
|
267
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/functions/src/runtime/scheduler.ts";
|
|
290
268
|
var Scheduler = class {
|
|
291
269
|
constructor(_client, _manifest, _options = {}) {
|
|
292
270
|
this._client = _client;
|
|
@@ -316,7 +294,7 @@ var Scheduler = class {
|
|
|
316
294
|
};
|
|
317
295
|
const def = this._manifest.functions.find((config) => config.id === trigger.function);
|
|
318
296
|
(0, import_invariant2.invariant)(def, `Function not found: ${trigger.function}`, {
|
|
319
|
-
F:
|
|
297
|
+
F: __dxlog_file2,
|
|
320
298
|
L: 63,
|
|
321
299
|
S: this,
|
|
322
300
|
A: [
|
|
@@ -330,11 +308,11 @@ var Scheduler = class {
|
|
|
330
308
|
ctx,
|
|
331
309
|
trigger
|
|
332
310
|
});
|
|
333
|
-
(0,
|
|
311
|
+
(0, import_log2.log)("mount", {
|
|
334
312
|
space: space.key,
|
|
335
313
|
trigger
|
|
336
314
|
}, {
|
|
337
|
-
F:
|
|
315
|
+
F: __dxlog_file2,
|
|
338
316
|
L: 69,
|
|
339
317
|
S: this,
|
|
340
318
|
C: (f, a) => f(...a)
|
|
@@ -368,7 +346,7 @@ var Scheduler = class {
|
|
|
368
346
|
});
|
|
369
347
|
});
|
|
370
348
|
(0, import_invariant2.invariant)(trigger.schedule, void 0, {
|
|
371
|
-
F:
|
|
349
|
+
F: __dxlog_file2,
|
|
372
350
|
L: 103,
|
|
373
351
|
S: this,
|
|
374
352
|
A: [
|
|
@@ -403,13 +381,13 @@ var Scheduler = class {
|
|
|
403
381
|
const update = ({ objects }) => {
|
|
404
382
|
subscription.update(objects);
|
|
405
383
|
if (deep) {
|
|
406
|
-
|
|
384
|
+
import_log2.log.info("update", {
|
|
407
385
|
type,
|
|
408
386
|
deep,
|
|
409
387
|
objects: objects.length
|
|
410
388
|
}, {
|
|
411
|
-
F:
|
|
412
|
-
L:
|
|
389
|
+
F: __dxlog_file2,
|
|
390
|
+
L: 139,
|
|
413
391
|
S: this,
|
|
414
392
|
C: (f, a) => f(...a)
|
|
415
393
|
});
|
|
@@ -431,11 +409,11 @@ var Scheduler = class {
|
|
|
431
409
|
}
|
|
432
410
|
async _execFunction(def, data) {
|
|
433
411
|
try {
|
|
434
|
-
(0,
|
|
412
|
+
(0, import_log2.log)("request", {
|
|
435
413
|
function: def.id
|
|
436
414
|
}, {
|
|
437
|
-
F:
|
|
438
|
-
L:
|
|
415
|
+
F: __dxlog_file2,
|
|
416
|
+
L: 161,
|
|
439
417
|
S: this,
|
|
440
418
|
C: (f, a) => f(...a)
|
|
441
419
|
});
|
|
@@ -453,22 +431,22 @@ var Scheduler = class {
|
|
|
453
431
|
} else if (callback) {
|
|
454
432
|
status = await callback(data);
|
|
455
433
|
}
|
|
456
|
-
(0,
|
|
434
|
+
(0, import_log2.log)("result", {
|
|
457
435
|
function: def.id,
|
|
458
436
|
result: status
|
|
459
437
|
}, {
|
|
460
|
-
F:
|
|
461
|
-
L:
|
|
438
|
+
F: __dxlog_file2,
|
|
439
|
+
L: 180,
|
|
462
440
|
S: this,
|
|
463
441
|
C: (f, a) => f(...a)
|
|
464
442
|
});
|
|
465
443
|
} catch (err) {
|
|
466
|
-
|
|
444
|
+
import_log2.log.error("error", {
|
|
467
445
|
function: def.id,
|
|
468
446
|
error: err.message
|
|
469
447
|
}, {
|
|
470
|
-
F:
|
|
471
|
-
L:
|
|
448
|
+
F: __dxlog_file2,
|
|
449
|
+
L: 182,
|
|
472
450
|
S: this,
|
|
473
451
|
C: (f, a) => f(...a)
|
|
474
452
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/handler.ts", "../../../src/runtime/dev-server.ts", "../../../src/runtime/scheduler.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Client, PublicKey } from '@dxos/client';\nimport { type Space } from '@dxos/client/echo';\nimport { isTypedObject, type TypedObject } from '@dxos/echo-schema';\nimport { log } from '@dxos/log';\nimport { nonNullable } from '@dxos/util';\n\n// TODO(burdon): No response?\nexport interface Response {\n status(code: number): Response;\n}\n\n// TODO(burdon): Limit access to individual space?\nexport interface FunctionContext {\n client: Client;\n dataDir?: string;\n}\n\n// TODO(burdon): Model after http request. Ref Lambda/OpenFaaS.\n// https://docs.aws.amazon.com/lambda/latest/dg/typescript-handler.html\nexport type FunctionHandler<T extends {}> = (params: {\n event: T;\n context: FunctionContext;\n response: Response;\n}) => Promise<Response | void>;\n\nexport type FunctionSubscriptionEvent = {\n space?: string; // TODO(burdon): Convert to PublicKey.\n objects?: string[];\n};\n\nexport type FunctionSubscriptionEvent2 = {\n space?: Space;\n objects?: TypedObject[];\n};\n\n/**\n * Handler wrapper for subscription events; extracts space and objects.\n *\n * To test:\n * ```\n * curl -s -X POST -H \"Content-Type: application/json\" --data '{\"space\": \"0446...1cbb\"}' http://localhost:7100/dev/email-extractor\n * ```\n *\n * NOTE: Get space key from devtools or `dx space list --json`\n */\nexport const subscriptionHandler = (\n handler: FunctionHandler<FunctionSubscriptionEvent2>,\n): FunctionHandler<FunctionSubscriptionEvent> => {\n return ({ event, context, ...rest }) => {\n const { client } = context;\n const space = event.space ? client.spaces.get(PublicKey.from(event.space)) : undefined;\n const objects =\n space &&\n event.objects\n ?.map<TypedObject | undefined>((id) => space!.db.getObjectById(id))\n .filter(nonNullable)\n .filter(isTypedObject);\n\n if (!!event.space && !space) {\n log.warn('invalid space', { event });\n } else {\n log.info('handler', { space: space?.key.truncate(), objects: objects?.length });\n }\n\n return handler({ event: { space, objects }, context, ...rest });\n };\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport express from 'express';\nimport { getPort } from 'get-port-please';\nimport type http from 'http';\nimport { join } from 'node:path';\n\nimport { Trigger } from '@dxos/async';\nimport { type Client } from '@dxos/client';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\n\nimport { type FunctionContext, type FunctionHandler, type Response } from '../handler';\nimport { type FunctionDef, type FunctionManifest } from '../manifest';\n\nexport type DevServerOptions = {\n port?: number;\n directory: string;\n manifest: FunctionManifest;\n reload?: boolean;\n dataDir?: string;\n};\n\n/**\n * Functions dev server provides a local HTTP server for testing functions.\n */\nexport class DevServer {\n // Function handlers indexed by name (URL path).\n private readonly _handlers: Record<string, { def: FunctionDef; handler: FunctionHandler<any> }> = {};\n\n private _server?: http.Server;\n private _port?: number;\n private _registrationId?: string;\n private _proxy?: string;\n private _seq = 0;\n\n // prettier-ignore\n constructor(\n private readonly _client: Client,\n private readonly _options: DevServerOptions,\n ) {}\n\n get endpoint() {\n invariant(this._port);\n return `http://localhost:${this._port}`;\n }\n\n get proxy() {\n return this._proxy;\n }\n\n get functions() {\n return Object.values(this._handlers);\n }\n\n async initialize() {\n for (const def of this._options.manifest.functions) {\n try {\n await this._load(def);\n } catch (err) {\n log.error('parsing function (check manifest)', err);\n }\n }\n }\n\n async start() {\n const app = express();\n app.use(express.json());\n\n app.post('/:name', async (req, res) => {\n const { name } = req.params;\n try {\n if (this._options.reload) {\n const { def } = this._handlers[name];\n await this._load(def, true);\n }\n\n res.statusCode = await this._invoke(name, req.body);\n res.end();\n } catch (err: any) {\n log.error(`Function failed: ${name}`, err);\n res.statusCode = 500;\n res.end();\n }\n });\n\n this._port = await getPort({ host: 'localhost', port: 7200, portRange: [7200, 7299] });\n this._server = app.listen(this._port);\n\n try {\n // Register functions.\n const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService!.register({\n endpoint: this.endpoint,\n functions: this.functions.map(({ def: { name } }) => ({ name })),\n });\n\n log.info('registered', { registrationId, endpoint });\n this._registrationId = registrationId;\n this._proxy = endpoint;\n } catch (err: any) {\n await this.stop();\n throw new Error('FunctionRegistryService not available (check plugin is configured).');\n }\n }\n\n async stop() {\n const trigger = new Trigger();\n this._server?.close(async () => {\n if (this._registrationId) {\n await this._client.services.services.FunctionRegistryService!.unregister({\n registrationId: this._registrationId,\n });\n\n log.info('unregistered', { registrationId: this._registrationId });\n this._registrationId = undefined;\n this._proxy = undefined;\n }\n\n trigger.wake();\n });\n\n await trigger.wait();\n this._port = undefined;\n this._server = undefined;\n }\n\n /**\n * Load function.\n */\n private async _load(def: FunctionDef, flush = false) {\n const { id, name, handler } = def;\n const path = join(this._options.directory, handler);\n log.info('loading', { id });\n\n // Remove from cache.\n if (flush) {\n Object.keys(require.cache)\n .filter((key) => key.startsWith(path))\n .forEach((key) => delete require.cache[key]);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const module = require(path);\n if (typeof module.default !== 'function') {\n throw new Error(`Handler must export default function: ${id}`);\n }\n\n this._handlers[name] = { def, handler: module.default };\n }\n\n /**\n * Invoke function handler.\n */\n private async _invoke(name: string, event: any) {\n const seq = ++this._seq;\n const now = Date.now();\n\n log.info('req', { seq, name });\n const { handler } = this._handlers[name];\n\n const context: FunctionContext = {\n client: this._client,\n dataDir: this._options.dataDir,\n };\n\n let statusCode = 200;\n const response: Response = {\n status: (code: number) => {\n statusCode = code;\n return response;\n },\n };\n\n await handler({ context, event, response });\n log.info('res', { seq, name, statusCode, duration: Date.now() - now });\n\n return statusCode;\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { CronJob } from 'cron';\n\nimport { debounce, DeferredTask } from '@dxos/async';\nimport { type Client, type PublicKey } from '@dxos/client';\nimport { type Space, TextObject } from '@dxos/client/echo';\nimport { Context } from '@dxos/context';\nimport { Filter, createSubscription, type Query, subscribe } from '@dxos/echo-schema';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { ComplexMap } from '@dxos/util';\n\nimport { type FunctionSubscriptionEvent } from '../handler';\nimport { type FunctionDef, type FunctionManifest, type FunctionTrigger, type TriggerSubscription } from '../manifest';\n\ntype Callback = (data: FunctionSubscriptionEvent) => Promise<number>;\n\ntype SchedulerOptions = {\n endpoint?: string;\n callback?: Callback;\n};\n\n/**\n * Functions scheduler.\n */\n// TODO(burdon): Create tests.\nexport class Scheduler {\n // Map of mounted functions.\n private readonly _mounts = new ComplexMap<\n { id: string; spaceKey: PublicKey },\n { ctx: Context; trigger: FunctionTrigger }\n >(({ id, spaceKey }) => `${spaceKey.toHex()}:${id}`);\n\n constructor(\n private readonly _client: Client,\n private readonly _manifest: FunctionManifest,\n private readonly _options: SchedulerOptions = {},\n ) {}\n\n async start() {\n this._client.spaces.subscribe(async (spaces) => {\n for (const space of spaces) {\n await space.waitUntilReady();\n for (const trigger of this._manifest.triggers ?? []) {\n await this.mount(new Context(), space, trigger);\n }\n }\n });\n }\n\n async stop() {\n for (const { id, spaceKey } of this._mounts.keys()) {\n await this.unmount(id, spaceKey);\n }\n }\n\n private async mount(ctx: Context, space: Space, trigger: FunctionTrigger) {\n const key = { id: trigger.function, spaceKey: space.key };\n const def = this._manifest.functions.find((config) => config.id === trigger.function);\n invariant(def, `Function not found: ${trigger.function}`);\n\n // Currently supports only one trigger declaration per function.\n const exists = this._mounts.get(key);\n if (!exists) {\n this._mounts.set(key, { ctx, trigger });\n log('mount', { space: space.key, trigger });\n if (ctx.disposed) {\n return;\n }\n\n // Timer.\n if (trigger.schedule) {\n this._createTimer(ctx, space, def, trigger);\n }\n\n // Subscription.\n for (const triggerSubscription of trigger.subscriptions ?? []) {\n this._createSubscription(ctx, space, def, triggerSubscription);\n }\n }\n }\n\n private async unmount(id: string, spaceKey: PublicKey) {\n const key = { id, spaceKey };\n const { ctx } = this._mounts.get(key) ?? {};\n if (ctx) {\n this._mounts.delete(key);\n await ctx.dispose();\n }\n }\n\n private _createTimer(ctx: Context, space: Space, def: FunctionDef, trigger: FunctionTrigger) {\n const task = new DeferredTask(ctx, async () => {\n await this._execFunction(def, {\n space: space.key,\n });\n });\n\n // TODO(burdon): Check greater than 30s min (use cron-parser).\n invariant(trigger.schedule);\n const job = new CronJob(trigger.schedule, () => task.schedule());\n\n job.start();\n ctx.onDispose(() => job.stop());\n }\n\n private _createSubscription(ctx: Context, space: Space, def: FunctionDef, triggerSubscription: TriggerSubscription) {\n const objectIds = new Set<string>();\n const task = new DeferredTask(ctx, async () => {\n await this._execFunction(def, {\n space: space.key,\n objects: Array.from(objectIds),\n });\n });\n\n // TODO(burdon): Don't fire initially.\n // TODO(burdon): Standardize subscription handles.\n const subscriptions: (() => void)[] = [];\n const subscription = createSubscription(({ added, updated }) => {\n for (const object of added) {\n objectIds.add(object.id);\n }\n for (const object of updated) {\n objectIds.add(object.id);\n }\n\n task.schedule();\n });\n subscriptions.push(() => subscription.unsubscribe());\n\n // TODO(burdon): Create queue. Only allow one invocation per trigger at a time?\n // TODO(burdon): Disable trigger if keeps failing.\n const { type, props, deep, delay } = triggerSubscription;\n const update = ({ objects }: Query) => {\n subscription.update(objects);\n\n // TODO(burdon): Hack to monitor changes to Document's text object.\n if (deep) {\n log.info('update', { type, deep, objects: objects.length });\n for (const object of objects) {\n const content = object.content;\n if (content instanceof TextObject) {\n subscriptions.push(content[subscribe](debounce(() => subscription.update([object]), 1_000)));\n }\n }\n }\n };\n\n // TODO(burdon): [Bug]: all callbacks are fired on the first mutation.\n // TODO(burdon): [Bug]: not updated when document is deleted (either top or hierarchically).\n const query = space.db.query(Filter.typename(type, props));\n subscriptions.push(query.subscribe(delay ? debounce(update, delay * 1_000) : update));\n\n ctx.onDispose(() => {\n subscriptions.forEach((unsubscribe) => unsubscribe());\n });\n }\n\n private async _execFunction(def: FunctionDef, data: any) {\n try {\n log('request', { function: def.id });\n const { endpoint, callback } = this._options;\n let status = 0;\n if (endpoint) {\n // TODO(burdon): Move out of scheduler (generalize as callback).\n const response = await fetch(`${this._options.endpoint}/${def.name}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(data),\n });\n\n status = response.status;\n } else if (callback) {\n status = await callback(data);\n }\n\n // const result = await response.json();\n log('result', { function: def.id, result: status });\n } catch (err: any) {\n log.error('error', { function: def.id, error: err.message });\n }\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,oBAAuC;AAEvC,yBAAgD;AAChD,
|
|
6
|
-
"names": ["
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Client, PublicKey } from '@dxos/client';\nimport { type Space } from '@dxos/client/echo';\nimport { isTypedObject, type TypedObject } from '@dxos/echo-schema';\nimport { nonNullable } from '@dxos/util';\n\n// TODO(burdon): No response?\nexport interface Response {\n status(code: number): Response;\n}\n\n// TODO(burdon): Limit access to individual space?\nexport interface FunctionContext {\n client: Client;\n dataDir?: string;\n}\n\n// TODO(burdon): Model after http request. Ref Lambda/OpenFaaS.\n// https://docs.aws.amazon.com/lambda/latest/dg/typescript-handler.html\nexport type FunctionHandler<T extends {}> = (params: {\n event: T;\n context: FunctionContext;\n response: Response;\n}) => Promise<Response | void>;\n\nexport type FunctionSubscriptionEvent = {\n space?: string; // TODO(burdon): Convert to PublicKey.\n objects?: string[];\n};\n\nexport type FunctionSubscriptionEvent2 = {\n space?: Space;\n objects?: TypedObject[];\n};\n\nexport const subscriptionHandler = (\n handler: FunctionHandler<FunctionSubscriptionEvent2>,\n): FunctionHandler<FunctionSubscriptionEvent> => {\n return ({ event, context, ...rest }) => {\n const { client } = context;\n const space = event.space ? client.spaces.get(PublicKey.from(event.space)) : undefined;\n const objects =\n space &&\n event.objects\n ?.map<TypedObject | undefined>((id) => space!.db.getObjectById(id))\n .filter(nonNullable)\n .filter(isTypedObject);\n\n return handler({ event: { space, objects }, context, ...rest });\n };\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport express from 'express';\nimport { getPort } from 'get-port-please';\nimport type http from 'http';\nimport { join } from 'node:path';\n\nimport { Trigger } from '@dxos/async';\nimport { type Client } from '@dxos/client';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\n\nimport { type FunctionContext, type FunctionHandler, type Response } from '../handler';\nimport { type FunctionDef, type FunctionManifest } from '../manifest';\n\nexport type DevServerOptions = {\n port?: number;\n directory: string;\n manifest: FunctionManifest;\n reload?: boolean;\n dataDir?: string;\n};\n\n/**\n * Functions dev server provides a local HTTP server for testing functions.\n */\nexport class DevServer {\n // Function handlers indexed by name (URL path).\n private readonly _handlers: Record<string, { def: FunctionDef; handler: FunctionHandler<any> }> = {};\n\n private _server?: http.Server;\n private _port?: number;\n private _registrationId?: string;\n private _proxy?: string;\n private _seq = 0;\n\n // prettier-ignore\n constructor(\n private readonly _client: Client,\n private readonly _options: DevServerOptions,\n ) {}\n\n get endpoint() {\n invariant(this._port);\n return `http://localhost:${this._port}`;\n }\n\n get proxy() {\n return this._proxy;\n }\n\n get functions() {\n return Object.values(this._handlers);\n }\n\n async initialize() {\n for (const def of this._options.manifest.functions) {\n try {\n await this._load(def);\n } catch (err) {\n log.error('parsing function (check manifest)', err);\n }\n }\n }\n\n async start() {\n const app = express();\n app.use(express.json());\n\n app.post('/:name', async (req, res) => {\n const { name } = req.params;\n try {\n if (this._options.reload) {\n const { def } = this._handlers[name];\n await this._load(def, true);\n }\n\n res.statusCode = await this._invoke(name, req.body);\n res.end();\n } catch (err: any) {\n log.catch(err);\n res.statusCode = 500;\n res.end();\n }\n });\n\n this._port = await getPort({ host: 'localhost', port: 7200, portRange: [7200, 7299] });\n this._server = app.listen(this._port);\n\n try {\n // Register functions.\n const { registrationId, endpoint } = await this._client.services.services.FunctionRegistryService!.register({\n endpoint: this.endpoint,\n functions: this.functions.map(({ def: { name } }) => ({ name })),\n });\n\n log.info('registered', { registrationId, endpoint });\n this._registrationId = registrationId;\n this._proxy = endpoint;\n } catch (err: any) {\n await this.stop();\n throw new Error('FunctionRegistryService not available (check plugin is configured).');\n }\n }\n\n async stop() {\n const trigger = new Trigger();\n this._server?.close(async () => {\n if (this._registrationId) {\n await this._client.services.services.FunctionRegistryService!.unregister({\n registrationId: this._registrationId,\n });\n\n log.info('unregistered', { registrationId: this._registrationId });\n this._registrationId = undefined;\n this._proxy = undefined;\n }\n\n trigger.wake();\n });\n\n await trigger.wait();\n this._port = undefined;\n this._server = undefined;\n }\n\n /**\n * Load function.\n */\n private async _load(def: FunctionDef, flush = false) {\n const { id, name, handler } = def;\n const path = join(this._options.directory, handler);\n log.info('loading', { id });\n\n // Remove from cache.\n if (flush) {\n Object.keys(require.cache)\n .filter((key) => key.startsWith(path))\n .forEach((key) => delete require.cache[key]);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const module = require(path);\n if (typeof module.default !== 'function') {\n throw new Error(`Handler must export default function: ${id}`);\n }\n\n this._handlers[name] = { def, handler: module.default };\n }\n\n /**\n * Invoke function handler.\n */\n private async _invoke(name: string, event: any) {\n const seq = ++this._seq;\n const now = Date.now();\n\n log.info('req', { seq, name });\n const { handler } = this._handlers[name];\n\n const context: FunctionContext = {\n client: this._client,\n dataDir: this._options.dataDir,\n };\n\n let statusCode = 200;\n const response: Response = {\n status: (code: number) => {\n statusCode = code;\n return response;\n },\n };\n\n await handler({ context, event, response });\n log.info('res', { seq, name, statusCode, duration: Date.now() - now });\n\n return statusCode;\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { CronJob } from 'cron';\n\nimport { debounce, DeferredTask } from '@dxos/async';\nimport { type Client, type PublicKey } from '@dxos/client';\nimport { type Space, TextObject } from '@dxos/client/echo';\nimport { Context } from '@dxos/context';\nimport { Filter, createSubscription, type Query, subscribe } from '@dxos/echo-schema';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { ComplexMap } from '@dxos/util';\n\nimport { type FunctionSubscriptionEvent } from '../handler';\nimport { type FunctionDef, type FunctionManifest, type FunctionTrigger, type TriggerSubscription } from '../manifest';\n\ntype Callback = (data: FunctionSubscriptionEvent) => Promise<number>;\n\ntype SchedulerOptions = {\n endpoint?: string;\n callback?: Callback;\n};\n\n/**\n * Functions scheduler.\n */\n// TODO(burdon): Create tests.\nexport class Scheduler {\n // Map of mounted functions.\n private readonly _mounts = new ComplexMap<\n { id: string; spaceKey: PublicKey },\n { ctx: Context; trigger: FunctionTrigger }\n >(({ id, spaceKey }) => `${spaceKey.toHex()}:${id}`);\n\n constructor(\n private readonly _client: Client,\n private readonly _manifest: FunctionManifest,\n private readonly _options: SchedulerOptions = {},\n ) {}\n\n async start() {\n this._client.spaces.subscribe(async (spaces) => {\n for (const space of spaces) {\n await space.waitUntilReady();\n for (const trigger of this._manifest.triggers ?? []) {\n await this.mount(new Context(), space, trigger);\n }\n }\n });\n }\n\n async stop() {\n for (const { id, spaceKey } of this._mounts.keys()) {\n await this.unmount(id, spaceKey);\n }\n }\n\n private async mount(ctx: Context, space: Space, trigger: FunctionTrigger) {\n const key = { id: trigger.function, spaceKey: space.key };\n const def = this._manifest.functions.find((config) => config.id === trigger.function);\n invariant(def, `Function not found: ${trigger.function}`);\n\n // Currently supports only one trigger declaration per function.\n const exists = this._mounts.get(key);\n if (!exists) {\n this._mounts.set(key, { ctx, trigger });\n log('mount', { space: space.key, trigger });\n if (ctx.disposed) {\n return;\n }\n\n // Timer.\n if (trigger.schedule) {\n this._createTimer(ctx, space, def, trigger);\n }\n\n // Subscription.\n for (const triggerSubscription of trigger.subscriptions ?? []) {\n this._createSubscription(ctx, space, def, triggerSubscription);\n }\n }\n }\n\n private async unmount(id: string, spaceKey: PublicKey) {\n const key = { id, spaceKey };\n const { ctx } = this._mounts.get(key) ?? {};\n if (ctx) {\n this._mounts.delete(key);\n await ctx.dispose();\n }\n }\n\n private _createTimer(ctx: Context, space: Space, def: FunctionDef, trigger: FunctionTrigger) {\n const task = new DeferredTask(ctx, async () => {\n await this._execFunction(def, {\n space: space.key,\n });\n });\n\n // TODO(burdon): Check greater than 30s min (use cron-parser).\n invariant(trigger.schedule);\n const job = new CronJob(trigger.schedule, () => task.schedule());\n\n job.start();\n ctx.onDispose(() => job.stop());\n }\n\n private _createSubscription(ctx: Context, space: Space, def: FunctionDef, triggerSubscription: TriggerSubscription) {\n const objectIds = new Set<string>();\n const task = new DeferredTask(ctx, async () => {\n await this._execFunction(def, {\n space: space.key,\n objects: Array.from(objectIds),\n });\n });\n\n // TODO(burdon): Standardize subscription handles.\n const subscriptions: (() => void)[] = [];\n const subscription = createSubscription(({ added, updated }) => {\n for (const object of added) {\n objectIds.add(object.id);\n }\n for (const object of updated) {\n objectIds.add(object.id);\n }\n\n task.schedule();\n });\n subscriptions.push(() => subscription.unsubscribe());\n\n const { type, props, deep, delay } = triggerSubscription;\n const update = ({ objects }: Query) => {\n subscription.update(objects);\n\n // TODO(burdon): Hack to monitor changes to Document's text object.\n if (deep) {\n log.info('update', { type, deep, objects: objects.length });\n for (const object of objects) {\n const content = object.content;\n if (content instanceof TextObject) {\n subscriptions.push(content[subscribe](debounce(() => subscription.update([object]), 1_000)));\n }\n }\n }\n };\n\n // TODO(burdon): [Bug]: all callbacks are fired on the first mutation.\n // TODO(burdon): [Bug]: not updated when document is deleted (either top or hierarchically).\n const query = space.db.query(Filter.typename(type, props));\n subscriptions.push(query.subscribe(delay ? debounce(update, delay * 1_000) : update));\n\n ctx.onDispose(() => {\n subscriptions.forEach((unsubscribe) => unsubscribe());\n });\n }\n\n private async _execFunction(def: FunctionDef, data: any) {\n try {\n log('request', { function: def.id });\n const { endpoint, callback } = this._options;\n let status = 0;\n if (endpoint) {\n // TODO(burdon): Move out of scheduler (generalize as callback).\n const response = await fetch(`${this._options.endpoint}/${def.name}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(data),\n });\n\n status = response.status;\n } else if (callback) {\n status = await callback(data);\n }\n\n // const result = await response.json();\n log('result', { function: def.id, result: status });\n } catch (err: any) {\n log.error('error', { function: def.id, error: err.message });\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_async", "import_echo_schema", "import_invariant", "import_log", "import_util", "subscriptionHandler", "handler", "event", "context", "rest", "client", "space", "spaces", "get", "PublicKey", "from", "undefined", "objects", "map", "id", "db", "getObjectById", "filter", "nonNullable", "isTypedObject", "DevServer", "constructor", "_client", "_options", "_handlers", "_seq", "endpoint", "invariant", "_port", "proxy", "_proxy", "functions", "Object", "values", "initialize", "def", "manifest", "_load", "err", "log", "error", "start", "app", "express", "use", "json", "post", "req", "res", "name", "params", "reload", "statusCode", "_invoke", "body", "end", "catch", "getPort", "host", "port", "portRange", "_server", "listen", "registrationId", "services", "FunctionRegistryService", "register", "info", "_registrationId", "stop", "Error", "trigger", "Trigger", "close", "unregister", "wake", "wait", "flush", "path", "join", "directory", "keys", "require", "cache", "key", "startsWith", "forEach", "module", "default", "seq", "now", "Date", "dataDir", "response", "status", "code", "duration", "Scheduler", "_manifest", "_mounts", "ComplexMap", "spaceKey", "toHex", "subscribe", "waitUntilReady", "triggers", "mount", "Context", "unmount", "ctx", "function", "find", "config", "exists", "set", "disposed", "schedule", "_createTimer", "triggerSubscription", "subscriptions", "_createSubscription", "delete", "dispose", "task", "DeferredTask", "_execFunction", "job", "CronJob", "onDispose", "objectIds", "Set", "Array", "subscription", "createSubscription", "added", "updated", "object", "add", "push", "unsubscribe", "type", "props", "deep", "delay", "update", "length", "content", "TextObject", "debounce", "query", "Filter", "typename", "data", "callback", "fetch", "method", "headers", "JSON", "stringify", "result", "message"]
|
|
7
7
|
}
|
package/dist/lib/node/meta.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"packages/core/functions/src/handler.ts":{"bytes":
|
|
1
|
+
{"inputs":{"packages/core/functions/src/handler.ts":{"bytes":4072,"imports":[{"path":"@dxos/client","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/manifest.ts":{"bytes":1863,"imports":[],"format":"esm"},"packages/core/functions/src/runtime/dev-server.ts":{"bytes":18840,"imports":[{"path":"express","kind":"import-statement","external":true},{"path":"get-port-please","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/scheduler.ts":{"bytes":22471,"imports":[{"path":"cron","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/client/echo","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/functions/src/runtime/index.ts":{"bytes":566,"imports":[{"path":"packages/core/functions/src/runtime/dev-server.ts","kind":"import-statement","original":"./dev-server"},{"path":"packages/core/functions/src/runtime/scheduler.ts","kind":"import-statement","original":"./scheduler"}],"format":"esm"},"packages/core/functions/src/index.ts":{"bytes":637,"imports":[{"path":"packages/core/functions/src/handler.ts","kind":"import-statement","original":"./handler"},{"path":"packages/core/functions/src/manifest.ts","kind":"import-statement","original":"./manifest"},{"path":"packages/core/functions/src/runtime/index.ts","kind":"import-statement","original":"./runtime"}],"format":"esm"}},"outputs":{"packages/core/functions/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":21909},"packages/core/functions/dist/lib/node/index.cjs":{"imports":[{"path":"@dxos/client","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"express","kind":"import-statement","external":true},{"path":"get-port-please","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"cron","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/client/echo","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["DevServer","Scheduler","subscriptionHandler"],"entryPoint":"packages/core/functions/src/index.ts","inputs":{"packages/core/functions/src/handler.ts":{"bytesInOutput":589},"packages/core/functions/src/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/dev-server.ts":{"bytesInOutput":4792},"packages/core/functions/src/runtime/index.ts":{"bytesInOutput":0},"packages/core/functions/src/runtime/scheduler.ts":{"bytesInOutput":5475}},"bytes":11470}}}
|
|
@@ -21,15 +21,5 @@ export type FunctionSubscriptionEvent2 = {
|
|
|
21
21
|
space?: Space;
|
|
22
22
|
objects?: TypedObject[];
|
|
23
23
|
};
|
|
24
|
-
/**
|
|
25
|
-
* Handler wrapper for subscription events; extracts space and objects.
|
|
26
|
-
*
|
|
27
|
-
* To test:
|
|
28
|
-
* ```
|
|
29
|
-
* curl -s -X POST -H "Content-Type: application/json" --data '{"space": "0446...1cbb"}' http://localhost:7100/dev/email-extractor
|
|
30
|
-
* ```
|
|
31
|
-
*
|
|
32
|
-
* NOTE: Get space key from devtools or `dx space list --json`
|
|
33
|
-
*/
|
|
34
24
|
export declare const subscriptionHandler: (handler: FunctionHandler<FunctionSubscriptionEvent2>) => FunctionHandler<FunctionSubscriptionEvent>;
|
|
35
25
|
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/handler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,MAAM,EAAa,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/handler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,MAAM,EAAa,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIpE,MAAM,WAAW,QAAQ;IACvB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;CAChC;AAGD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE;IACnD,KAAK,EAAE,CAAC,CAAC;IACT,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,EAAE,QAAQ,CAAC;CACpB,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;AAE/B,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;CACzB,CAAC;AAEF,eAAO,MAAM,mBAAmB,YACrB,gBAAgB,0BAA0B,CAAC,KACnD,gBAAgB,yBAAyB,CAa3C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../../../src/runtime/scheduler.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,MAAM,EAAkB,MAAM,cAAc,CAAC;AAQ3D,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAoB,KAAK,gBAAgB,EAAkD,MAAM,aAAa,CAAC;AAEtH,KAAK,QAAQ,GAAG,CAAC,IAAI,EAAE,yBAAyB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAErE,KAAK,gBAAgB,GAAG;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAEF;;GAEG;AAEH,qBAAa,SAAS;IAQlB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAR3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAG6B;gBAGlC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,gBAAgB,EAC3B,QAAQ,GAAE,gBAAqB;IAG5C,KAAK;IAWL,IAAI;YAMI,KAAK;YA0BL,OAAO;IASrB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,mBAAmB;
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../../../src/runtime/scheduler.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,MAAM,EAAkB,MAAM,cAAc,CAAC;AAQ3D,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAoB,KAAK,gBAAgB,EAAkD,MAAM,aAAa,CAAC;AAEtH,KAAK,QAAQ,GAAG,CAAC,IAAI,EAAE,yBAAyB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAErE,KAAK,gBAAgB,GAAG;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAEF;;GAEG;AAEH,qBAAa,SAAS;IAQlB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAR3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAG6B;gBAGlC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,gBAAgB,EAC3B,QAAQ,GAAE,gBAAqB;IAG5C,KAAK;IAWL,IAAI;YAMI,KAAK;YA0BL,OAAO;IASrB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,mBAAmB;YAiDb,aAAa;CA0B5B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/functions",
|
|
3
|
-
"version": "0.3.9-main.
|
|
3
|
+
"version": "0.3.9-main.8045d90",
|
|
4
4
|
"description": "Functions SDK and runtime.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -24,14 +24,14 @@
|
|
|
24
24
|
"deepsignal": "1.4.0-shallow.0",
|
|
25
25
|
"express": "^4.17.1",
|
|
26
26
|
"get-port-please": "^3.1.1",
|
|
27
|
-
"@dxos/async": "0.3.9-main.
|
|
28
|
-
"@dxos/client": "0.3.9-main.
|
|
29
|
-
"@dxos/
|
|
30
|
-
"@dxos/
|
|
31
|
-
"@dxos/invariant": "0.3.9-main.
|
|
32
|
-
"@dxos/
|
|
33
|
-
"@dxos/
|
|
34
|
-
"@dxos/util": "0.3.9-main.
|
|
27
|
+
"@dxos/async": "0.3.9-main.8045d90",
|
|
28
|
+
"@dxos/client": "0.3.9-main.8045d90",
|
|
29
|
+
"@dxos/context": "0.3.9-main.8045d90",
|
|
30
|
+
"@dxos/echo-schema": "0.3.9-main.8045d90",
|
|
31
|
+
"@dxos/invariant": "0.3.9-main.8045d90",
|
|
32
|
+
"@dxos/node-std": "0.3.9-main.8045d90",
|
|
33
|
+
"@dxos/log": "0.3.9-main.8045d90",
|
|
34
|
+
"@dxos/util": "0.3.9-main.8045d90"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/express": "^4.17.17"
|
package/src/handler.ts
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
import { type Client, PublicKey } from '@dxos/client';
|
|
6
6
|
import { type Space } from '@dxos/client/echo';
|
|
7
7
|
import { isTypedObject, type TypedObject } from '@dxos/echo-schema';
|
|
8
|
-
import { log } from '@dxos/log';
|
|
9
8
|
import { nonNullable } from '@dxos/util';
|
|
10
9
|
|
|
11
10
|
// TODO(burdon): No response?
|
|
@@ -37,16 +36,6 @@ export type FunctionSubscriptionEvent2 = {
|
|
|
37
36
|
objects?: TypedObject[];
|
|
38
37
|
};
|
|
39
38
|
|
|
40
|
-
/**
|
|
41
|
-
* Handler wrapper for subscription events; extracts space and objects.
|
|
42
|
-
*
|
|
43
|
-
* To test:
|
|
44
|
-
* ```
|
|
45
|
-
* curl -s -X POST -H "Content-Type: application/json" --data '{"space": "0446...1cbb"}' http://localhost:7100/dev/email-extractor
|
|
46
|
-
* ```
|
|
47
|
-
*
|
|
48
|
-
* NOTE: Get space key from devtools or `dx space list --json`
|
|
49
|
-
*/
|
|
50
39
|
export const subscriptionHandler = (
|
|
51
40
|
handler: FunctionHandler<FunctionSubscriptionEvent2>,
|
|
52
41
|
): FunctionHandler<FunctionSubscriptionEvent> => {
|
|
@@ -60,12 +49,6 @@ export const subscriptionHandler = (
|
|
|
60
49
|
.filter(nonNullable)
|
|
61
50
|
.filter(isTypedObject);
|
|
62
51
|
|
|
63
|
-
if (!!event.space && !space) {
|
|
64
|
-
log.warn('invalid space', { event });
|
|
65
|
-
} else {
|
|
66
|
-
log.info('handler', { space: space?.key.truncate(), objects: objects?.length });
|
|
67
|
-
}
|
|
68
|
-
|
|
69
52
|
return handler({ event: { space, objects }, context, ...rest });
|
|
70
53
|
};
|
|
71
54
|
};
|
package/src/runtime/scheduler.ts
CHANGED
|
@@ -116,7 +116,6 @@ export class Scheduler {
|
|
|
116
116
|
});
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
-
// TODO(burdon): Don't fire initially.
|
|
120
119
|
// TODO(burdon): Standardize subscription handles.
|
|
121
120
|
const subscriptions: (() => void)[] = [];
|
|
122
121
|
const subscription = createSubscription(({ added, updated }) => {
|
|
@@ -131,8 +130,6 @@ export class Scheduler {
|
|
|
131
130
|
});
|
|
132
131
|
subscriptions.push(() => subscription.unsubscribe());
|
|
133
132
|
|
|
134
|
-
// TODO(burdon): Create queue. Only allow one invocation per trigger at a time?
|
|
135
|
-
// TODO(burdon): Disable trigger if keeps failing.
|
|
136
133
|
const { type, props, deep, delay } = triggerSubscription;
|
|
137
134
|
const update = ({ objects }: Query) => {
|
|
138
135
|
subscription.update(objects);
|