@sockethub/server 5.0.0-alpha.3 → 5.0.0-alpha.4
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/coverage/tmp/coverage-39338-1663949520416-0.json +1 -0
- package/dist/bootstrap/init.js +2 -1
- package/dist/bootstrap/init.js.map +1 -1
- package/dist/config.d.ts +7 -1
- package/dist/config.js +6 -1
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/janitor.d.ts +27 -12
- package/dist/janitor.js +97 -66
- package/dist/janitor.js.map +1 -1
- package/dist/listener.d.ts +4 -1
- package/dist/listener.js +8 -5
- package/dist/listener.js.map +1 -1
- package/dist/middleware/create-activity-object.d.ts +3 -1
- package/dist/middleware/create-activity-object.js.map +1 -1
- package/dist/middleware/expand-activity-stream.d.ts +2 -1
- package/dist/middleware/expand-activity-stream.js +4 -1
- package/dist/middleware/expand-activity-stream.js.map +1 -1
- package/dist/middleware/expand-activity-stream.test.data.js +4 -4
- package/dist/middleware/expand-activity-stream.test.data.js.map +1 -1
- package/dist/middleware/store-credentials.d.ts +3 -3
- package/dist/middleware/store-credentials.js +2 -12
- package/dist/middleware/store-credentials.js.map +1 -1
- package/dist/middleware/validate.d.ts +2 -2
- package/dist/middleware/validate.js +1 -3
- package/dist/middleware/validate.js.map +1 -1
- package/dist/middleware/validate.test.data.js +5 -5
- package/dist/middleware/validate.test.data.js.map +1 -1
- package/dist/middleware.d.ts +14 -3
- package/dist/middleware.js +3 -1
- package/dist/middleware.js.map +1 -1
- package/dist/platform-instance.d.ts +11 -10
- package/dist/platform-instance.js +77 -62
- package/dist/platform-instance.js.map +1 -1
- package/dist/platform.js +93 -104
- package/dist/platform.js.map +1 -1
- package/dist/process-manager.js +7 -3
- package/dist/process-manager.js.map +1 -1
- package/dist/routes.d.ts +1 -1
- package/dist/routes.js +1 -1
- package/dist/routes.js.map +1 -1
- package/dist/sockethub.d.ts +1 -22
- package/dist/sockethub.js +19 -26
- package/dist/sockethub.js.map +1 -1
- package/package.json +30 -36
- package/src/bootstrap/init.d.ts +17 -7
- package/src/bootstrap/init.ts +2 -1
- package/src/config.ts +9 -1
- package/src/index.ts +3 -2
- package/src/janitor.test.ts +189 -0
- package/src/janitor.ts +110 -65
- package/src/listener.ts +11 -7
- package/src/middleware/create-activity-object.ts +5 -2
- package/src/middleware/expand-activity-stream.test.data.ts +5 -5
- package/src/middleware/expand-activity-stream.test.ts +2 -2
- package/src/middleware/expand-activity-stream.ts +12 -7
- package/src/middleware/store-credentials.test.ts +4 -6
- package/src/middleware/store-credentials.ts +8 -14
- package/src/middleware/validate.test.data.ts +5 -5
- package/src/middleware/validate.ts +4 -6
- package/src/middleware.ts +28 -11
- package/src/platform-instance.test.ts +18 -18
- package/src/platform-instance.ts +98 -73
- package/src/platform.ts +79 -101
- package/src/process-manager.ts +1 -1
- package/src/routes.ts +3 -2
- package/src/sockethub.ts +29 -57
- package/views/examples/dummy.ejs +3 -1
- package/views/examples/shared.js +1 -1
- package/views/examples/xmpp.ejs +60 -34
- package/coverage/tmp/coverage-93126-1649152190997-0.json +0 -1
- package/dist/common.d.ts +0 -3
- package/dist/common.js +0 -20
- package/dist/common.js.map +0 -1
- package/dist/crypto.d.ts +0 -10
- package/dist/crypto.js +0 -38
- package/dist/crypto.js.map +0 -1
- package/dist/store.d.ts +0 -5
- package/dist/store.js +0 -17
- package/dist/store.js.map +0 -1
- package/src/common.test.ts +0 -54
- package/src/common.ts +0 -14
- package/src/config.d.ts +0 -2
- package/src/crypto.d.ts +0 -5
- package/src/crypto.test.ts +0 -41
- package/src/crypto.ts +0 -41
- package/src/janitor.d.ts +0 -8
- package/src/middleware/validate.d.ts +0 -1
- package/src/middleware.d.ts +0 -21
- package/src/sockethub.d.ts +0 -1
- package/src/store.test.ts +0 -28
- package/src/store.ts +0 -17
- package/test/queue.functional.test.js +0 -0
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import {IActivityStream, CallbackInterface} from "@sockethub/schemas";
|
|
2
|
+
import { CredentialsStore } from "@sockethub/data-layer";
|
|
3
3
|
|
|
4
|
-
export default function storeCredentials(
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
done(err);
|
|
10
|
-
} else {
|
|
11
|
-
sessionLog('credentials encrypted and saved');
|
|
12
|
-
done();
|
|
13
|
-
}
|
|
14
|
-
});
|
|
4
|
+
export default function storeCredentials(
|
|
5
|
+
credentialsStore: CredentialsStore
|
|
6
|
+
) {
|
|
7
|
+
return (creds: IActivityStream, done: CallbackInterface) => {
|
|
8
|
+
credentialsStore.save(creds.actor.id, creds, done);
|
|
15
9
|
};
|
|
16
|
-
}
|
|
10
|
+
}
|
|
@@ -130,10 +130,10 @@ export default [
|
|
|
130
130
|
"image":{
|
|
131
131
|
"height":250,
|
|
132
132
|
"mediaType":"image/jpeg",
|
|
133
|
-
"url":"
|
|
133
|
+
"url":"https://example.org/image.jpg",
|
|
134
134
|
"width":250
|
|
135
135
|
},
|
|
136
|
-
"url":"
|
|
136
|
+
"url":"https://sockethub.org"
|
|
137
137
|
},
|
|
138
138
|
"output":"same"
|
|
139
139
|
},
|
|
@@ -145,7 +145,7 @@ export default [
|
|
|
145
145
|
"id":"irc://sh-9K3Vk@irc.freenode.net",
|
|
146
146
|
"type":"person",
|
|
147
147
|
"name":"sh-9K3Vk",
|
|
148
|
-
"url":"
|
|
148
|
+
"url":"https://sockethub.org"
|
|
149
149
|
},
|
|
150
150
|
"output":"same"
|
|
151
151
|
},
|
|
@@ -211,7 +211,7 @@ export default [
|
|
|
211
211
|
"context":"fake",
|
|
212
212
|
"target": { "id": "irc://irc.dooder.net/a-room", "type": "room" }
|
|
213
213
|
},
|
|
214
|
-
"error": "Error: activity stream: must have required property
|
|
214
|
+
"error": "Error: activity stream: must have required property 'type'"
|
|
215
215
|
},
|
|
216
216
|
{
|
|
217
217
|
"name":"invalid context property",
|
|
@@ -234,7 +234,7 @@ export default [
|
|
|
234
234
|
"context":"fake",
|
|
235
235
|
"target": { "id": "irc://irc.dooder.net/a-room", "type": "room" }
|
|
236
236
|
},
|
|
237
|
-
"error": "Error: activity stream: must have required property
|
|
237
|
+
"error": "Error: activity stream: must have required property 'actor'"
|
|
238
238
|
},
|
|
239
239
|
{
|
|
240
240
|
"name":"traditional message",
|
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
* responsible for handling the validation and expansion (when applicable) of all incoming objects
|
|
3
3
|
*/
|
|
4
4
|
import debug from 'debug';
|
|
5
|
-
import schemas from '@sockethub/schemas';
|
|
6
|
-
import { IActivityStream } from "@sockethub/schemas";
|
|
5
|
+
import schemas, {IActivityStream, CallbackActivityStreamInterface} from '@sockethub/schemas';
|
|
7
6
|
|
|
8
|
-
// @ts-ignore
|
|
9
7
|
import init from "../bootstrap/init";
|
|
10
8
|
|
|
11
9
|
init.platforms.forEach((platform) => {
|
|
@@ -18,8 +16,8 @@ init.platforms.forEach((platform) => {
|
|
|
18
16
|
// called when registered with the middleware function, define the type of validation
|
|
19
17
|
// that will be called when the middleware eventually does.
|
|
20
18
|
export default function validate(type: string, sockethubId: string) {
|
|
21
|
-
const sessionLog = debug(`sockethub:validate:${sockethubId}`);
|
|
22
|
-
return (msg: IActivityStream, done:
|
|
19
|
+
const sessionLog = debug(`sockethub:server:validate:${sockethubId}`);
|
|
20
|
+
return (msg: IActivityStream, done: CallbackActivityStreamInterface) => {
|
|
23
21
|
sessionLog('applying schema validation for ' + type);
|
|
24
22
|
if (type === 'activity-object') {
|
|
25
23
|
const err = schemas.validateActivityObject(msg);
|
|
@@ -46,4 +44,4 @@ export default function validate(type: string, sockethubId: string) {
|
|
|
46
44
|
}
|
|
47
45
|
}
|
|
48
46
|
};
|
|
49
|
-
}
|
|
47
|
+
}
|
package/src/middleware.ts
CHANGED
|
@@ -1,28 +1,43 @@
|
|
|
1
1
|
import { debug } from 'debug';
|
|
2
|
+
import {IActivityStream} from "@sockethub/schemas";
|
|
2
3
|
|
|
3
4
|
export default function middleware(name: string): MiddlewareChain {
|
|
4
5
|
return new MiddlewareChain(name);
|
|
5
6
|
}
|
|
6
7
|
|
|
8
|
+
export interface MiddlewareChainInterface {
|
|
9
|
+
(error: IActivityStream | Error,
|
|
10
|
+
data?: IActivityStream | MiddlewareChainInterface,
|
|
11
|
+
next?: MiddlewareChainInterface): void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface ErrorHandlerInterface {
|
|
15
|
+
(err: Error, data?: unknown, cb?: unknown): void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface LogErrorInterface {
|
|
19
|
+
(msg: Error): void;
|
|
20
|
+
}
|
|
21
|
+
|
|
7
22
|
export class MiddlewareChain {
|
|
8
23
|
public name: string;
|
|
9
|
-
private chain: Array<
|
|
10
|
-
private errHandler:
|
|
11
|
-
private logger:
|
|
24
|
+
private chain: Array<MiddlewareChainInterface> = [];
|
|
25
|
+
private errHandler: ErrorHandlerInterface = (err: Error) => { throw err; };
|
|
26
|
+
private readonly logger: LogErrorInterface;
|
|
12
27
|
|
|
13
28
|
constructor(name: string) {
|
|
14
29
|
this.name = name;
|
|
15
30
|
this.logger = debug(`sockethub:middleware:${name}`);
|
|
16
31
|
}
|
|
17
32
|
|
|
18
|
-
use(func:
|
|
33
|
+
use(func: ErrorHandlerInterface | MiddlewareChainInterface): this {
|
|
19
34
|
if (typeof func !== 'function') {
|
|
20
35
|
throw new Error('middleware use() can only take a function as an argument');
|
|
21
36
|
}
|
|
22
37
|
if (func.length === 3) {
|
|
23
|
-
this.errHandler = func;
|
|
38
|
+
this.errHandler = func as ErrorHandlerInterface;
|
|
24
39
|
} else if (func.length === 2) {
|
|
25
|
-
this.chain.push(func);
|
|
40
|
+
this.chain.push(func as MiddlewareChainInterface);
|
|
26
41
|
} else {
|
|
27
42
|
throw new Error(
|
|
28
43
|
'middleware function provided with incorrect number of params: ' + func.length);
|
|
@@ -31,19 +46,21 @@ export class MiddlewareChain {
|
|
|
31
46
|
}
|
|
32
47
|
|
|
33
48
|
done() {
|
|
34
|
-
return (data:
|
|
49
|
+
return (data: unknown, callback: MiddlewareChainInterface) => {
|
|
35
50
|
let position = 0;
|
|
36
51
|
if (typeof callback !== 'function') {
|
|
37
|
-
callback = () => {
|
|
52
|
+
callback = () => {
|
|
53
|
+
// ensure we have a callback function
|
|
54
|
+
};
|
|
38
55
|
}
|
|
39
|
-
const next = (_data:
|
|
56
|
+
const next = (_data: unknown) => {
|
|
40
57
|
if (_data instanceof Error) {
|
|
41
58
|
this.logger(_data);
|
|
42
59
|
this.errHandler(_data, data, callback);
|
|
43
60
|
} else if (typeof this.chain[position] === 'function') {
|
|
44
|
-
this.chain[position++](_data, next);
|
|
61
|
+
this.chain[position++](_data as IActivityStream, next);
|
|
45
62
|
} else {
|
|
46
|
-
callback(_data);
|
|
63
|
+
callback(_data as IActivityStream);
|
|
47
64
|
}
|
|
48
65
|
};
|
|
49
66
|
next(data);
|
|
@@ -19,13 +19,13 @@ describe("PlatformInstance", () => {
|
|
|
19
19
|
getSocketFake = sinon.fake.resolves(socketMock);
|
|
20
20
|
|
|
21
21
|
const PlatformInstanceMod = proxyquire('./platform-instance', {
|
|
22
|
-
'
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
22
|
+
'@sockethub/data-layer': {
|
|
23
|
+
JobQueue: sandbox.stub().returns({
|
|
24
|
+
shutdown: sandbox.stub(),
|
|
25
|
+
on: sandbox.stub(),
|
|
26
|
+
getJob: sandbox.stub(),
|
|
27
|
+
initResultEvents: sandbox.stub()
|
|
28
|
+
})
|
|
29
29
|
},
|
|
30
30
|
'child_process': {
|
|
31
31
|
fork: forkFake,
|
|
@@ -51,7 +51,7 @@ describe("PlatformInstance", () => {
|
|
|
51
51
|
});
|
|
52
52
|
|
|
53
53
|
describe('private instance per-actor', () => {
|
|
54
|
-
it("is set as non-global when an actor is provided", () => {
|
|
54
|
+
it("is set as non-global when an actor is provided", async () => {
|
|
55
55
|
const pi = new PlatformInstance({
|
|
56
56
|
identifier: 'id',
|
|
57
57
|
platform: 'name',
|
|
@@ -60,7 +60,7 @@ describe("PlatformInstance", () => {
|
|
|
60
60
|
});
|
|
61
61
|
expect(pi.global).to.be.equal(false);
|
|
62
62
|
sandbox.assert.calledWith(forkFake, FORK_PATH, ['parentId', 'name', 'id']);
|
|
63
|
-
pi.
|
|
63
|
+
await pi.shutdown();
|
|
64
64
|
});
|
|
65
65
|
});
|
|
66
66
|
|
|
@@ -82,8 +82,8 @@ describe("PlatformInstance", () => {
|
|
|
82
82
|
};
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
-
afterEach(() => {
|
|
86
|
-
pi.
|
|
85
|
+
afterEach(async () => {
|
|
86
|
+
await pi.shutdown();
|
|
87
87
|
});
|
|
88
88
|
|
|
89
89
|
it('has expected properties', () => {
|
|
@@ -123,23 +123,23 @@ describe("PlatformInstance", () => {
|
|
|
123
123
|
expect(pi.sessions.has('my session id')).to.be.equal(true);
|
|
124
124
|
pi.reportError('my session id', 'an error message');
|
|
125
125
|
pi.sendToClient = sandbox.stub();
|
|
126
|
-
pi.
|
|
126
|
+
pi.shutdown = sandbox.stub();
|
|
127
127
|
expect(pi.sessions.size).to.be.equal(0);
|
|
128
128
|
});
|
|
129
129
|
});
|
|
130
130
|
|
|
131
131
|
it('initializes the job queue', () => {
|
|
132
|
-
expect(pi.
|
|
132
|
+
expect(pi.jobQueue).to.be.undefined;
|
|
133
133
|
pi.initQueue('a secret');
|
|
134
|
-
expect(pi.
|
|
134
|
+
expect(pi.jobQueue).to.be.ok;
|
|
135
135
|
});
|
|
136
136
|
|
|
137
|
-
it("cleans up its references when
|
|
137
|
+
it("cleans up its references when shutdown", async () => {
|
|
138
138
|
pi.initQueue('a secret');
|
|
139
|
-
expect(pi.
|
|
139
|
+
expect(pi.jobQueue).to.be.ok;
|
|
140
140
|
expect(platformInstances.has('platform identifier')).to.be.true;
|
|
141
|
-
await pi.
|
|
142
|
-
expect(pi.
|
|
141
|
+
await pi.shutdown();
|
|
142
|
+
expect(pi.jobQueue).not.to.be.ok;
|
|
143
143
|
expect(platformInstances.has('platform identifier')).to.be.false;
|
|
144
144
|
});
|
|
145
145
|
|
package/src/platform-instance.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {ChildProcess, fork } from 'child_process';
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { debug, Debugger } from 'debug';
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
4
|
+
import {IActivityStream, CompletedJobHandler} from "@sockethub/schemas";
|
|
5
|
+
import {JobQueue, JobDataDecrypted} from "@sockethub/data-layer";
|
|
6
6
|
|
|
7
7
|
import config from "./config";
|
|
8
|
-
import { JobDataDecrypted, JobEncrypted } from "./sockethub";
|
|
9
8
|
import { getSocket } from "./listener";
|
|
10
|
-
import
|
|
9
|
+
import nconf from "nconf";
|
|
11
10
|
|
|
12
11
|
// collection of platform instances, stored by `id`
|
|
13
12
|
export const platformInstances = new Map<string, PlatformInstance>();
|
|
@@ -19,9 +18,16 @@ export interface PlatformInstanceParams {
|
|
|
19
18
|
actor?: string;
|
|
20
19
|
}
|
|
21
20
|
|
|
21
|
+
type EnvFormat = {
|
|
22
|
+
DEBUG?: string,
|
|
23
|
+
REDIS_URL?: string,
|
|
24
|
+
REDIS_HOST?: string,
|
|
25
|
+
REDIS_PORT?: string
|
|
26
|
+
}
|
|
27
|
+
|
|
22
28
|
interface MessageFromPlatform extends Array<string | IActivityStream>{
|
|
23
29
|
0: string, 1: IActivityStream, 2: string}
|
|
24
|
-
export interface MessageFromParent extends Array<string|
|
|
30
|
+
export interface MessageFromParent extends Array<string|unknown>{0: string, 1: unknown}
|
|
25
31
|
|
|
26
32
|
interface PlatformConfig {
|
|
27
33
|
persist?: boolean;
|
|
@@ -29,11 +35,13 @@ interface PlatformConfig {
|
|
|
29
35
|
}
|
|
30
36
|
|
|
31
37
|
export default class PlatformInstance {
|
|
32
|
-
flaggedForTermination: boolean = false;
|
|
33
38
|
id: string;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
flaggedForTermination = false;
|
|
40
|
+
initialized = false;
|
|
41
|
+
jobQueue: JobQueue;
|
|
42
|
+
readonly global: boolean = false;
|
|
43
|
+
readonly completedJobHandlers: Map<string, CompletedJobHandler> = new Map();
|
|
44
|
+
readonly config: PlatformConfig = {};
|
|
37
45
|
readonly name: string;
|
|
38
46
|
readonly process: ChildProcess;
|
|
39
47
|
readonly debug: Debugger;
|
|
@@ -43,7 +51,6 @@ export default class PlatformInstance {
|
|
|
43
51
|
'close': (() => new Map())(),
|
|
44
52
|
'message': (() => new Map())()
|
|
45
53
|
};
|
|
46
|
-
public readonly global?: boolean = false;
|
|
47
54
|
private readonly actor?: string;
|
|
48
55
|
|
|
49
56
|
constructor(params: PlatformInstanceParams) {
|
|
@@ -56,60 +63,68 @@ export default class PlatformInstance {
|
|
|
56
63
|
this.global = true;
|
|
57
64
|
}
|
|
58
65
|
|
|
59
|
-
this.debug = debug(`sockethub:platform-instance:${this.id}`);
|
|
66
|
+
this.debug = debug(`sockethub:server:platform-instance:${this.id}`);
|
|
67
|
+
const env: EnvFormat = {};
|
|
68
|
+
if (process.env.DEBUG) {
|
|
69
|
+
env.DEBUG = process.env.DEBUG;
|
|
70
|
+
}
|
|
71
|
+
if (config.get('redis:url')) {
|
|
72
|
+
env.REDIS_URL = config.get('redis:url') as string;
|
|
73
|
+
} else {
|
|
74
|
+
env.REDIS_HOST = config.get('redis:host') as string;
|
|
75
|
+
env.REDIS_PORT = config.get('redis:port') as string;
|
|
76
|
+
}
|
|
77
|
+
|
|
60
78
|
// spin off a process
|
|
61
|
-
const env = config.get('redis:url') ? { REDIS_URL: config.get('redis:url') }
|
|
62
|
-
: { REDIS_HOST: config.get('redis:host'), REDIS_PORT: config.get('redis:port') };
|
|
63
79
|
this.process = fork(
|
|
64
80
|
join(__dirname, 'platform.js'),
|
|
65
81
|
[this.parentId, this.name, this.id],
|
|
66
|
-
{ env: env }
|
|
82
|
+
{ env: env }
|
|
83
|
+
);
|
|
67
84
|
}
|
|
68
85
|
|
|
69
86
|
/**
|
|
70
87
|
* Destroys all references to this platform instance, internal listeners and controlled processes
|
|
71
88
|
*/
|
|
72
|
-
public async
|
|
73
|
-
this.debug(
|
|
89
|
+
public async shutdown() {
|
|
90
|
+
this.debug('shutdown');
|
|
74
91
|
this.flaggedForTermination = true;
|
|
92
|
+
|
|
75
93
|
try {
|
|
76
|
-
await this.queue.removeAllListeners();
|
|
77
|
-
} catch (e) { }
|
|
78
|
-
try {
|
|
79
|
-
await this.queue.obliterate({ force: true });
|
|
80
|
-
} catch (e) { }
|
|
81
|
-
try {
|
|
82
|
-
delete this.queue;
|
|
83
94
|
await this.process.removeAllListeners('close');
|
|
84
95
|
await this.process.unref();
|
|
85
|
-
|
|
86
|
-
} catch (e) {
|
|
87
|
-
|
|
96
|
+
this.process.kill();
|
|
97
|
+
} catch (e) {
|
|
98
|
+
// needs to happen
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
await this.jobQueue.shutdown();
|
|
103
|
+
delete this.jobQueue;
|
|
104
|
+
} catch (e) {
|
|
105
|
+
// this needs to happen
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
platformInstances.delete(this.id);
|
|
110
|
+
} catch (e) {
|
|
111
|
+
// this needs to happen
|
|
112
|
+
}
|
|
88
113
|
}
|
|
89
114
|
|
|
90
115
|
/**
|
|
91
116
|
* When jobs are completed or failed, we prepare the results and send them to the client socket
|
|
92
117
|
*/
|
|
93
118
|
public initQueue(secret: string) {
|
|
94
|
-
this.
|
|
95
|
-
|
|
96
|
-
this.queue.on('global:completed', (jobId, resultString) => {
|
|
97
|
-
const result = resultString ? JSON.parse(resultString) : "";
|
|
98
|
-
this.queue.getJob(jobId).then(async (job: JobEncrypted) => {
|
|
99
|
-
await this.handleJobResult('completed', decryptJobData(job, secret), result);
|
|
100
|
-
await job.remove();
|
|
101
|
-
});
|
|
102
|
-
});
|
|
119
|
+
this.jobQueue = new JobQueue(this.parentId, this.id, secret, nconf.get('redis'));
|
|
120
|
+
this.jobQueue.initResultEvents();
|
|
103
121
|
|
|
104
|
-
this.
|
|
105
|
-
this.
|
|
122
|
+
this.jobQueue.on('global:completed', async (job: JobDataDecrypted, result: string) => {
|
|
123
|
+
await this.handleJobResult('completed', job, result);
|
|
106
124
|
});
|
|
107
125
|
|
|
108
|
-
this.
|
|
109
|
-
this.
|
|
110
|
-
await this.handleJobResult('failed', decryptJobData(job, secret), result);
|
|
111
|
-
await job.remove();
|
|
112
|
-
});
|
|
126
|
+
this.jobQueue.on('global:failed', async (job: JobDataDecrypted, result: string) => {
|
|
127
|
+
await this.handleJobResult('failed', job, result);
|
|
113
128
|
});
|
|
114
129
|
}
|
|
115
130
|
|
|
@@ -120,7 +135,7 @@ export default class PlatformInstance {
|
|
|
120
135
|
public registerSession(sessionId: string) {
|
|
121
136
|
if (! this.sessions.has(sessionId)) {
|
|
122
137
|
this.sessions.add(sessionId);
|
|
123
|
-
for (
|
|
138
|
+
for (const type of Object.keys(this.sessionCallbacks)) {
|
|
124
139
|
const cb = this.callbackFunction(type, sessionId);
|
|
125
140
|
this.process.on(type, cb);
|
|
126
141
|
this.sessionCallbacks[type].set(sessionId, cb);
|
|
@@ -139,19 +154,20 @@ export default class PlatformInstance {
|
|
|
139
154
|
try {
|
|
140
155
|
// this property should never be exposed externally
|
|
141
156
|
delete msg.sessionSecret;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
157
|
+
} finally {
|
|
158
|
+
msg.context = this.name;
|
|
159
|
+
if ((msg.type === 'error') && (typeof msg.actor === 'undefined') && (this.actor)) {
|
|
160
|
+
// ensure an actor is present if not otherwise defined
|
|
161
|
+
msg.actor = { id: this.actor, type: 'unknown' };
|
|
162
|
+
}
|
|
163
|
+
socket.emit('message', msg);
|
|
147
164
|
}
|
|
148
|
-
socket.emit('message', msg);
|
|
149
165
|
}, (err) => this.debug(`sendToClient ${err}`));
|
|
150
166
|
}
|
|
151
167
|
|
|
152
168
|
// send message to every connected socket associated with this platform instance.
|
|
153
169
|
private async broadcastToSharedPeers(sessionId: string, msg: IActivityStream) {
|
|
154
|
-
for (
|
|
170
|
+
for (const sid of this.sessions.values()) {
|
|
155
171
|
if (sid !== sessionId) {
|
|
156
172
|
this.debug(`broadcasting message to ${sid}`);
|
|
157
173
|
await this.sendToClient(sid, msg);
|
|
@@ -160,30 +176,39 @@ export default class PlatformInstance {
|
|
|
160
176
|
}
|
|
161
177
|
|
|
162
178
|
// handle job results coming in on the queue from platform instances
|
|
163
|
-
private async handleJobResult(type: string,
|
|
164
|
-
|
|
165
|
-
delete jobData.msg.sessionSecret;
|
|
166
|
-
let msg = jobData.msg;
|
|
179
|
+
private async handleJobResult(type: string, job: JobDataDecrypted, result) {
|
|
180
|
+
const msg = job.msg;
|
|
167
181
|
if (type === 'failed') {
|
|
168
182
|
msg.error = result ? result : "job failed for unknown reason";
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
await this.destroy();
|
|
172
|
-
}
|
|
183
|
+
this.debug(`${job.title} ${type}: ${msg.error}`);
|
|
184
|
+
|
|
173
185
|
}
|
|
174
186
|
|
|
175
187
|
// send result to client
|
|
176
|
-
const callback = this.completedJobHandlers.get(
|
|
188
|
+
const callback = this.completedJobHandlers.get(job.title);
|
|
177
189
|
if (callback) {
|
|
178
190
|
callback(msg);
|
|
179
|
-
this.completedJobHandlers.delete(
|
|
191
|
+
this.completedJobHandlers.delete(job.title);
|
|
180
192
|
} else {
|
|
181
|
-
await this.sendToClient(
|
|
193
|
+
await this.sendToClient(job.sessionId, msg);
|
|
182
194
|
}
|
|
183
195
|
|
|
184
196
|
// let all related peers know of result as an independent message
|
|
185
197
|
// (not as part of a job completion, or failure)
|
|
186
|
-
await this.broadcastToSharedPeers(
|
|
198
|
+
await this.broadcastToSharedPeers(job.sessionId, msg);
|
|
199
|
+
|
|
200
|
+
if ((this.config.persist) && (this.config.requireCredentials.includes(job.msg.type))) {
|
|
201
|
+
if (type === 'failed') {
|
|
202
|
+
this.debug(`critical job type ${job.msg.type} failed, flagging for termination`);
|
|
203
|
+
await this.jobQueue.pause();
|
|
204
|
+
this.initialized = false;
|
|
205
|
+
this.flaggedForTermination = true;
|
|
206
|
+
} else {
|
|
207
|
+
await this.jobQueue.resume();
|
|
208
|
+
this.initialized = true;
|
|
209
|
+
this.flaggedForTermination = false;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
187
212
|
}
|
|
188
213
|
|
|
189
214
|
/**
|
|
@@ -191,7 +216,7 @@ export default class PlatformInstance {
|
|
|
191
216
|
* @param sessionId
|
|
192
217
|
* @param errorMessage
|
|
193
218
|
*/
|
|
194
|
-
private async reportError(sessionId: string, errorMessage:
|
|
219
|
+
private async reportError(sessionId: string, errorMessage: string) {
|
|
195
220
|
const errorObject: IActivityStream = {
|
|
196
221
|
context: this.name,
|
|
197
222
|
type: 'error',
|
|
@@ -200,7 +225,7 @@ export default class PlatformInstance {
|
|
|
200
225
|
};
|
|
201
226
|
this.sendToClient(sessionId, errorObject);
|
|
202
227
|
this.sessions.clear();
|
|
203
|
-
await this.
|
|
228
|
+
await this.shutdown();
|
|
204
229
|
}
|
|
205
230
|
|
|
206
231
|
/**
|
|
@@ -221,19 +246,19 @@ export default class PlatformInstance {
|
|
|
221
246
|
*/
|
|
222
247
|
private callbackFunction(listener: string, sessionId: string) {
|
|
223
248
|
const funcs = {
|
|
224
|
-
'close': (e: object) => {
|
|
249
|
+
'close': async (e: object) => {
|
|
225
250
|
this.debug(`close even triggered ${this.id}: ${e}`);
|
|
226
|
-
this.reportError(sessionId, `Error: session thread closed unexpectedly: ${e}`);
|
|
251
|
+
await this.reportError(sessionId, `Error: session thread closed unexpectedly: ${e}`);
|
|
227
252
|
},
|
|
228
|
-
'message': (
|
|
229
|
-
if (
|
|
253
|
+
'message': async ([first, second, third]: MessageFromPlatform) => {
|
|
254
|
+
if (first === 'updateActor') {
|
|
230
255
|
// We need to update the key to the store in order to find it in the future.
|
|
231
|
-
this.updateIdentifier(
|
|
232
|
-
} else if (
|
|
233
|
-
this.reportError(sessionId,
|
|
256
|
+
this.updateIdentifier(third);
|
|
257
|
+
} else if ((first === 'error') && (typeof second === "string")) {
|
|
258
|
+
await this.reportError(sessionId, second);
|
|
234
259
|
} else {
|
|
235
260
|
// treat like a message to clients
|
|
236
|
-
this.sendToClient(sessionId,
|
|
261
|
+
this.sendToClient(sessionId, second);
|
|
237
262
|
}
|
|
238
263
|
}
|
|
239
264
|
};
|