Skip to content

Commit 074da05

Browse files
authored
Worker-based Async API with await/Promise support (or plain callbacks) (#6)
* fix lint errors in eslint config :) * index.d.s: add /* eslint-disable @typescript-eslint/triple-slash-reference */ * improve eslint calling script * add async-worker version of the SRT JS API with await/Promise support + potentially out-of-order RPC-back/result-dequeuing is possible with a type of call-ID generator and callback-map that we prototyped (but not used atm since the worker is only doing sync/blocking internally with the current SRT lib binding). * add various examples for async API ("classic" callbacks / Promise / await) * add .eslintignore (should go with commit where we just call "eslint .") * index.js: add missing semi * async.js: fix method name litteral in epollUWait * async.js: allow for accept method to use a timeout opt (defaults to false), and a custom timeout value option (default to default timeout), which can potentially be set differently than the general default timeout. + make the timeout value a static class property so that it can be user-defined module-load wide. defaults to constant in module top scope. * async.js: fix for a rejected promise, make sure we don't resolve anymore + add a custom timeout value argument to _createAsyncWorkPromise * async.js: rm an experiment * fix a lint error in example * add types for async api and fix some details on binding API types * export async API to index * async.js: add some missing docs for private methods * include async types in index
1 parent c0846dd commit 074da05

12 files changed

Lines changed: 517 additions & 35 deletions

.eslintignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
build
2+
deps
3+
node_modules
4+
tsc-lib

.eslintrc.js

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
module.exports = {
2-
root: true,
3-
"env": {
4-
"commonjs": true,
5-
"es2020": true,
6-
"node": true,
7-
"jasmine": true
8-
},
9-
"extends": [
10-
"eslint:recommended",
11-
"plugin:@typescript-eslint/recommended",
12-
"plugin:jasmine/recommended"
13-
],
14-
"parser": "@typescript-eslint/parser",
15-
"parserOptions": {
16-
"ecmaVersion": 11
17-
},
18-
"plugins": ["@typescript-eslint", "jasmine"],
19-
"rules": {
20-
"indent": ["error", 2],
21-
"semi": "error",
22-
"@typescript-eslint/no-var-requires": 0,
23-
"no-constant-condition": 0
24-
}
2+
root: true,
3+
"env": {
4+
"commonjs": true,
5+
"es2020": true,
6+
"node": true,
7+
"jasmine": true
8+
},
9+
"extends": [
10+
"eslint:recommended",
11+
"plugin:@typescript-eslint/recommended",
12+
"plugin:jasmine/recommended"
13+
],
14+
"parser": "@typescript-eslint/parser",
15+
"parserOptions": {
16+
"ecmaVersion": 11
17+
},
18+
"plugins": ["@typescript-eslint", "jasmine"],
19+
"rules": {
20+
"indent": ["error", 2],
21+
"semi": "error",
22+
"@typescript-eslint/no-var-requires": 0,
23+
"no-constant-condition": 0
24+
}
2525
};

examples/async-srt-await.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const { AsyncSRT } = require('../src/async.js');
2+
3+
const asyncSrt = new AsyncSRT();
4+
5+
(async function() {
6+
const socket = await asyncSrt.createSocket(false);
7+
console.log('createSocket() result:', socket);
8+
let result = await asyncSrt.bind(socket, "0.0.0.0", 1234);
9+
console.log('bind() result:', result);
10+
result = await asyncSrt.listen(socket, 2);
11+
console.log('listen() result:', result);
12+
13+
awaitConnections(socket);
14+
15+
})();
16+
17+
async function awaitConnections(socket) {
18+
console.log('Awaiting incoming client connection ...');
19+
const fd = await asyncSrt.accept(socket);
20+
console.log('New incoming client fd:', fd);
21+
}
22+
23+
setInterval(() => {
24+
console.log('Doing other stuff in the meantime ... :)');
25+
}, 1000);

examples/async-srt-promises.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"use strict";
2+
3+
const { AsyncSRT } = require('../src/async.js');
4+
5+
const asyncSrt = new AsyncSRT();
6+
7+
let mySocket;
8+
9+
asyncSrt.createSocket(false)
10+
.catch((err) => console.error(err))
11+
.then((result) => {
12+
console.log('createSocket:', result);
13+
mySocket = result;
14+
return result;
15+
})
16+
.then((socket) => asyncSrt.bind(socket, "0.0.0.0", 1234))
17+
.then((result) => {
18+
if (result !== 0) {
19+
throw new Error('Failed bind');
20+
}
21+
console.log('Bind success');
22+
return asyncSrt.listen(mySocket, 2);
23+
})
24+
.then((result) => {
25+
if (!result) {
26+
console.log("Listen success");
27+
} else {
28+
throw new Error('SRT listen error: ' + result);
29+
}
30+
});
31+
32+

examples/async-srt.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"use strict";
2+
3+
const { AsyncSRT } = require('../src/async.js');
4+
5+
const asyncSrt = new AsyncSRT();
6+
7+
asyncSrt.createSocket(false, (result) => {
8+
console.log('createSocket:', result);
9+
const socket = result;
10+
asyncSrt.bind(socket, "0.0.0.0", 1234, (result) => {
11+
if (result !== 0) {
12+
console.log('Failed bind');
13+
} else {
14+
console.log('Bind success');
15+
asyncSrt.listen(socket, 2, (result) => {
16+
if (!result) {
17+
console.log("Listen success");
18+
} else {
19+
console.log(result);
20+
}
21+
});
22+
}
23+
});
24+
});
25+

index.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
/* eslint-disable @typescript-eslint/triple-slash-reference */
12
/// <reference path="./types/srt-api.d.ts" />
23
/// <reference path="./types/srt-stream.d.ts" />
34
/// <reference path="./types/srt-server.d.ts" />
5+
/// <reference path="./types/srt-api-async.d.ts" />
46

57
export * from "srt";

index.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
const LIB = require('./build/Release/node_srt.node');
1+
const { SRT } = require('./build/Release/node_srt.node');
22
const Server = require('./src/server.js');
33
const { SRTReadStream, SRTWriteStream } = require('./src/stream.js');
4+
const { AsyncSRT } = require('./src/async');
45

56
module.exports = {
6-
SRT: LIB.SRT,
7-
Server: Server,
7+
SRT,
8+
Server,
89
SRTReadStream,
9-
SRTWriteStream
10-
}
10+
SRTWriteStream,
11+
AsyncSRT,
12+
};

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"rebuild": "node-gyp rebuild",
1010
"clean": "node-gyp clean",
1111
"test": "$(npm bin)/jasmine",
12-
"lint": "eslint src examples types --ext .js --ext .ts",
12+
"lint": "eslint . --ext .js --ext .ts",
1313
"check-tsc": "./node_modules/.bin/tsc examples/srt.ts --outDir ./tsc-lib",
1414
"postversion": "git push && git push --tags"
1515
},

src/async-worker.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
const {
2+
Worker, isMainThread, parentPort, workerData
3+
} = require('worker_threads');
4+
5+
const { SRT } = require('../build/Release/node_srt.node');
6+
7+
if (isMainThread) {
8+
throw new Error("Worker module can not load on main thread");
9+
}
10+
11+
(function run() {
12+
const libSRT = new SRT();
13+
parentPort.on('message', (data) => {
14+
if (!data.method) {
15+
throw new Error('Worker message needs `method` property');
16+
}
17+
/*
18+
if (!data.workId) {
19+
throw new Error('Worker message needs `workId` property');
20+
}
21+
*/
22+
let result = libSRT[data.method].apply(libSRT, data.args);
23+
// TODO: see if we can do this using SharedArrayBuffer for example,
24+
// or just leveraging Transferable objects capabilities ... ?
25+
// FIXME: Performance ... ?
26+
if (result instanceof Buffer) {
27+
const buf = Buffer.allocUnsafe(result.length);
28+
result.copy(buf);
29+
result = buf;
30+
}
31+
parentPort.postMessage({
32+
// workId: data.workId,
33+
timestamp: data.timestamp,
34+
result
35+
});
36+
});
37+
})();
38+
39+
40+
41+

0 commit comments

Comments
 (0)