29 Commits

Author SHA1 Message Date
7e5c0fe678 2.0.2 2018-08-07 11:13:03 +02:00
93b44ba888 fix(core): update testing framework 2018-08-07 11:13:03 +02:00
30249ad254 2.0.1 2018-08-02 15:35:55 +02:00
07be849d2f fix(package): npm access level 2018-08-02 15:35:55 +02:00
d31f85c6cb 2.0.0 2018-08-02 15:31:06 +02:00
fb2b72a97f BREAKING CHANGE(package): change scope 2018-08-02 15:31:05 +02:00
18dfa70d16 1.0.11 2017-11-28 16:30:04 +01:00
1cb892c357 update ci 2017-11-28 16:30:02 +01:00
275e242ad8 1.0.10 2017-11-28 16:10:19 +01:00
b295b55a92 update to latest standards 2017-11-28 16:10:15 +01:00
8fbd9c0b51 1.0.9 2017-03-04 19:20:03 +01:00
1850f7d132 add argvArgs to simpleThread 2017-03-04 19:20:00 +01:00
e0dffad3f2 1.0.8 2017-03-04 12:24:34 +01:00
241880f2b0 add forkOptions 2017-03-04 12:24:32 +01:00
9d33a5df53 1.0.7 2017-03-04 12:05:57 +01:00
57ddf4c45d improve typings 2017-03-04 12:05:53 +01:00
1329513543 1.0.6 2017-03-04 11:59:58 +01:00
e1acfd03e6 ThreadSimple is now returning a Promise 2017-03-04 11:59:56 +01:00
d73c877815 1.0.5 2017-03-04 11:40:37 +01:00
347036cf4e add threadsimple for simple forking 2017-03-04 11:40:32 +01:00
661e782367 update wrap 2017-03-03 21:32:40 +01:00
6da41845f1 1.0.4 2017-03-03 20:58:08 +01:00
6b95c7e2ca add npmts as required global tool for CI 2017-03-03 20:58:05 +01:00
9d08755705 update README 2017-03-03 20:55:54 +01:00
00969c1d7f 1.0.3 2017-03-03 20:52:25 +01:00
a16a66f1f6 update smartipc internal code 2017-03-03 20:52:23 +01:00
05cbbda941 1.0.2 2017-01-29 23:46:19 +01:00
a0f3b1639c improve README 2017-01-29 23:46:09 +01:00
218deb9947 add basic functionality 2017-01-29 23:41:26 +01:00
36 changed files with 1499 additions and 319 deletions

View File

@ -1,49 +1,142 @@
image: hosttoday/ht-docker-node:npmts
# gitzone standard
image: hosttoday/ht-docker-node:npmci
cache:
paths:
- .npmci_cache/
key: "$CI_BUILD_STAGE"
stages:
- security
- test
- release
- page
- metadata
# ====================
# security stage
# ====================
mirror:
stage: security
script:
- npmci git mirror
tags:
- docker
- notpriv
snyk:
stage: security
script:
- npmci command npm install -g snyk
- npmci command npm install --ignore-scripts
- npmci command snyk test
tags:
- docker
- notpriv
# ====================
# test stage
# ====================
testLEGACY:
stage: test
script:
- npmci test legacy
- npmci node install legacy
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- docker
- notpriv
allow_failure: true
testLTS:
stage: test
script:
- npmci test lts
- npmci node install lts
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- docker
- notpriv
testSTABLE:
stage: test
script:
- npmci test stable
- npmci node install stable
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- docker
- notpriv
release:
stage: release
environment: npmjs-com_registry
script:
- npmci publish
- npmci node install stable
- npmci npm publish
only:
- tags
- tags
tags:
- docker
- docker
- notpriv
# ====================
# metadata stage
# ====================
codequality:
stage: metadata
image: docker:stable
allow_failure: true
services:
- docker:stable-dind
script:
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
- docker run
--env SOURCE_CODE="$PWD"
--volume "$PWD":/code
--volume /var/run/docker.sock:/var/run/docker.sock
"registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
artifacts:
paths: [codeclimate.json]
tags:
- docker
- priv
trigger:
stage: metadata
script:
- npmci trigger
only:
- tags
tags:
- docker
- notpriv
pages:
image: hosttoday/ht-docker-node:npmpage
stage: page
image: hosttoday/ht-docker-node:npmci
stage: metadata
script:
- npmci command npmpage --host gitlab
- npmci command npm install -g typedoc typescript
- npmci npm install
- npmci command typedoc --module "commonjs" --target "ES2016" --out public/ ts/
tags:
- docker
- notpriv
only:
- tags
artifacts:
expire_in: 1 week
paths:
- public
- public
allow_failure: true
windowsCompatibility:
image: stefanscherer/node-windows:10-build-tools
stage: metadata
script:
- npm install & npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- windows
allow_failure: true

View File

@ -1,15 +1,19 @@
# smartipc
# @pushrocks/smartspawn
smart subprocess handling
## Availabililty
[![npm](https://push.rocks/assets/repo-button-npm.svg)](https://www.npmjs.com/package/smartipc)
[![git](https://push.rocks/assets/repo-button-git.svg)](https://gitlab.com/pushrocks/smartipc)
[![git](https://push.rocks/assets/repo-button-mirror.svg)](https://github.com/pushrocks/smartipc)
[![docs](https://push.rocks/assets/repo-button-docs.svg)](https://pushrocks.gitlab.io/smartipc/)
[![npm](https://pushrocks.gitlab.io/assets/repo-button-npm.svg)](https://www.npmjs.com/package/smartipc)
[![git](https://pushrocks.gitlab.io/assets/repo-button-git.svg)](https://GitLab.com/pushrocks/smartipc)
[![git](https://pushrocks.gitlab.io/assets/repo-button-mirror.svg)](https://github.com/pushrocks/smartipc)
[![docs](https://pushrocks.gitlab.io/assets/repo-button-docs.svg)](https://pushrocks.gitlab.io/smartipc/)
## Status for master
[![build status](https://gitlab.com/pushrocks/smartipc/badges/master/build.svg)](https://gitlab.com/pushrocks/smartipc/commits/master)
[![coverage report](https://gitlab.com/pushrocks/smartipc/badges/master/coverage.svg)](https://gitlab.com/pushrocks/smartipc/commits/master)
[![build status](https://GitLab.com/pushrocks/smartipc/badges/master/build.svg)](https://GitLab.com/pushrocks/smartipc/commits/master)
[![coverage report](https://GitLab.com/pushrocks/smartipc/badges/master/coverage.svg)](https://GitLab.com/pushrocks/smartipc/commits/master)
[![npm downloads per month](https://img.shields.io/npm/dm/smartipc.svg)](https://www.npmjs.com/package/smartipc)
[![Dependency Status](https://david-dm.org/pushrocks/smartipc.svg)](https://david-dm.org/pushrocks/smartipc)
[![bitHound Dependencies](https://www.bithound.io/github/pushrocks/smartipc/badges/dependencies.svg)](https://www.bithound.io/github/pushrocks/smartipc/master/dependencies/npm)
[![bitHound Code](https://www.bithound.io/github/pushrocks/smartipc/badges/code.svg)](https://www.bithound.io/github/pushrocks/smartipc)
@ -17,52 +21,37 @@ smart subprocess handling
[![node](https://img.shields.io/badge/node->=%206.x.x-blue.svg)](https://nodejs.org/dist/latest-v6.x/docs/api/)
[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
## The purpose
## Usage
Use TypeScript for best in class instellisense.
### Understand the Purpose
smartipc makes it easy to spawn tasks into subprocesses without loosing control over what those processes do.
You can transparently call functions and expect returned data using promises.
## Usage
### How To
Server:
```typescript
import {Ipcserver} from 'smartipc'
import * as q from 'q'
**Master.ts:**
let myIpcserver = new Ipcserver({
appspace: 'mymodule'
})
// The subprocess js file cannot have any cli arguments
// since this mechanism is used by IpcServer to setup the connection
myIpcServer.spawnProcess('./myFile','mySubProcessNameAlias') // nameAlias identifies the subprocess and will prefix any logs from child Process
let someData = {
key1: 'value1',
key2: 'value2'
}
myIpcServer.call('mySubProcessNameAlias','myAwesomeFunction',someData).then(someAnswerData => {
console.log(someAnswerData.key1)
})
```javascript
import * as smartspawn from 'smartspawn';
smartspawn.setBasePathArg(__dirname); // if you want to avoid typings out full paths every time
let myThread = new smartspawn.Thread('worker');
myThread.send('someMessageOrObject').then(messageResponse => {
console.log(messageResponse);
});
```
Client:
```typescript
import { Ipcclient } from './smartipc'
import * as q from 'q'
**worker.ts**
let localIpc = new Ipcclient() // gets its connection information automatically using CLI args internally
let myAwesomeFunction = (dataArg) => {
let done = plugins.q.defer()
console.log('awesome') // this will log transparently in the same console stream as the host process
let someAnswerData = {key1: 'this is an answer'}
done.resolve(someAnswerData)
return done.promise
}
localIpc.register([myAwesomeFunction])
```javascript
```
[![npm](https://push.rocks/assets/repo-header.svg)](https://push.rocks)
For further information read the linked docs at the top of this README.
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
> | By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy.html)
[![repo-footer](https://pushrocks.gitlab.io/assets/repo-footer.svg)](https://push.rocks)

2
assets/typescriptwrap.js Normal file
View File

@ -0,0 +1,2 @@
require('@gitzone/tsrun');
require('spawn-wrap').runMain()

2
dist/index.d.ts vendored
View File

@ -1,2 +0,0 @@
export * from './smartipc.classes.thread';
export * from './smartipc.classes.threadfunction';

7
dist/index.js vendored
View File

@ -1,7 +0,0 @@
"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
__export(require("./smartipc.classes.thread"));
__export(require("./smartipc.classes.threadfunction"));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsK0NBQXlDO0FBQ3pDLHVEQUFpRCJ9

View File

@ -1,10 +0,0 @@
export declare let setWorkerBasePath: (basePathArg: string) => void;
export declare class Thread {
thread: any;
constructor(filePathArg: string);
/**
* sends a message to the spawned process
*/
send<T>(message: any): Promise<T>;
kill(): void;
}

View File

@ -1,32 +0,0 @@
"use strict";
const plugins = require("./smartipc.plugins");
const q = require("smartq");
exports.setWorkerBasePath = (basePathArg) => {
plugins.threads.config.set({
basepath: {
node: basePathArg
}
});
};
class Thread {
constructor(filePathArg) {
this.thread = plugins.threads.spawn(filePathArg);
}
/**
* sends a message to the spawned process
*/
send(message) {
let done = q.defer();
this.thread.send(message).on('message', (message) => {
done.resolve(message);
}).on('error', err => {
done.reject(err);
});
return done.promise;
}
kill() {
this.thread.kill();
}
}
exports.Thread = Thread;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRpcGMuY2xhc3Nlcy50aHJlYWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGlwYy5jbGFzc2VzLnRocmVhZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsOENBQTZDO0FBQzdDLDRCQUEyQjtBQUVoQixRQUFBLGlCQUFpQixHQUFHLENBQUMsV0FBbUI7SUFDL0MsT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDO1FBQ3ZCLFFBQVEsRUFBRTtZQUNOLElBQUksRUFBRSxXQUFXO1NBQ3BCO0tBQ0osQ0FBQyxDQUFBO0FBQ04sQ0FBQyxDQUFBO0FBRUQ7SUFFSSxZQUFZLFdBQW1CO1FBQzNCLElBQUksQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUE7SUFDcEQsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBSSxDQUFJLE9BQVk7UUFDaEIsSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBSyxDQUFBO1FBQ3ZCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxPQUFVO1lBQy9DLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDekIsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxHQUFHO1lBQ2QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQTtRQUNwQixDQUFDLENBQUMsQ0FBQTtRQUNGLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFBO0lBQ3ZCLENBQUM7SUFFRCxJQUFJO1FBQ0EsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQTtJQUN0QixDQUFDO0NBQ0o7QUF0QkQsd0JBc0JDIn0=

View File

@ -1,13 +0,0 @@
import 'typings-global';
export interface IThreadFunction {
(input: any, done: any): void;
}
export declare class ThreadFunction {
thread: any;
constructor(functionArg: IThreadFunction);
/**
* sends a message to the spawned process
*/
send<T>(message: any): Promise<T>;
kill(): void;
}

View File

@ -1,26 +0,0 @@
"use strict";
require("typings-global");
const plugins = require("./smartipc.plugins");
const q = require("smartq");
class ThreadFunction {
constructor(functionArg) {
this.thread = plugins.threads.spawn(functionArg);
}
/**
* sends a message to the spawned process
*/
send(message) {
let done = q.defer();
this.thread.send(message).on('message', (message) => {
done.resolve(message);
}).on('error', err => {
done.reject(err);
});
return done.promise;
}
kill() {
this.thread.kill();
}
}
exports.ThreadFunction = ThreadFunction;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRpcGMuY2xhc3Nlcy50aHJlYWRmdW5jdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0aXBjLmNsYXNzZXMudGhyZWFkZnVuY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLDBCQUF1QjtBQUN2Qiw4Q0FBNkM7QUFDN0MsNEJBQTJCO0FBTTNCO0lBRUksWUFBWSxXQUE0QjtRQUNwQyxJQUFJLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFBO0lBQ3BELENBQUM7SUFFRDs7T0FFRztJQUNILElBQUksQ0FBSSxPQUFZO1FBQ2hCLElBQUksSUFBSSxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUssQ0FBQTtRQUN2QixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLENBQUMsU0FBUyxFQUFFLENBQUMsT0FBVTtZQUMvQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFBO1FBQ3pCLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsR0FBRztZQUNkLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDcEIsQ0FBQyxDQUFDLENBQUE7UUFDRixNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQTtJQUN2QixDQUFDO0lBRUQsSUFBSTtRQUNBLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUE7SUFDdEIsQ0FBQztDQUNKO0FBdEJELHdDQXNCQyJ9

View File

@ -1,4 +0,0 @@
import 'typings-global';
declare let threads: any;
import * as smartq from 'smartq';
export { smartq, threads };

View File

@ -1,7 +0,0 @@
"use strict";
require("typings-global");
let threads = require('threads');
exports.threads = threads;
const smartq = require("smartq");
exports.smartq = smartq;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRpcGMucGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0aXBjLnBsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLDBCQUF1QjtBQUN2QixJQUFJLE9BQU8sR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUE7QUFLNUIsMEJBQU87QUFKWCxpQ0FBZ0M7QUFHNUIsd0JBQU0ifQ==

View File

View File

@ -1 +0,0 @@
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRpcGMucG9vbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0aXBjLnBvb2wudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9

View File

@ -1,7 +1,11 @@
{
"npmts": {
"testTs": {
"./test/*.ts": "./test/"
}
"npmts": {
"testTs": {
"./test/*.ts": "./test/"
}
},
"npmci": {
"npmGlobalTools": [],
"npmAccessLevel": "public"
}
}

1068
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,13 @@
{
"name": "smartipc",
"version": "1.0.1",
"name": "@pushrocks/smartspawn",
"version": "2.0.2",
"private": false,
"description": "smart subprocess handling",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"scripts": {
"test": "(npmts)"
"test": "tstest test/",
"build": "echo \"Not needed for now\""
},
"repository": {
"type": "git",
@ -18,16 +20,14 @@
},
"homepage": "https://gitlab.com/pushrocks/smartipc#README",
"dependencies": {
"@types/lodash": "^4.14.50",
"beautylog": "^6.0.0",
"lodash": "^4.17.4",
"smartq": "^1.1.0",
"threads": "^0.7.2",
"typings-global": "^1.0.14"
"@pushrocks/smartpromise": "^2.0.5",
"spawn-wrap": "^1.4.2",
"threads": "^0.8.1"
},
"devDependencies": {
"@types/should": "^8.1.30",
"should": "^11.1.2",
"typings-test": "^1.0.3"
"@gitzone/tsrun": "^1.1.9",
"@gitzone/tstest": "^1.0.12",
"@pushrocks/tapbundle": "^3.0.1",
"@types/node": "^10.5.5"
}
}

2
test/child.d.ts vendored
View File

@ -1,2 +0,0 @@
import 'typings-global';
import 'smartq';

View File

@ -1,7 +0,0 @@
"use strict";
require("typings-global");
require("smartq");
module.exports = (input, done) => {
done('hi');
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hpbGQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjaGlsZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsMEJBQXVCO0FBQ3ZCLGtCQUFlO0FBQ2YsTUFBTSxDQUFDLE9BQU8sR0FBRyxDQUFDLEtBQUssRUFBRSxJQUFJO0lBQ3pCLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtBQUNkLENBQUMsQ0FBQSJ9

View File

@ -1,5 +0,0 @@
import 'typings-global'
import 'smartq'
module.exports = (input, done) => {
done('hi')
}

1
test/test.d.ts vendored
View File

@ -1 +0,0 @@
import 'typings-test';

View File

@ -1,26 +0,0 @@
"use strict";
require("typings-test");
const smartipc = require("../dist/index");
let testThreadFunction;
let testThread;
describe('smartipc', function () {
it('should create an instance of ThreadFunction', function () {
testThreadFunction = new smartipc.ThreadFunction((input, done) => {
let url = require('url');
done(url.parse(input));
});
testThreadFunction.send('https://google.com').then(message => {
console.log(message);
testThreadFunction.kill();
});
});
it('should create an instance of Thread', function () {
smartipc.setWorkerBasePath(__dirname);
testThread = new smartipc.Thread('child.js');
testThread.send('https://google.com').then(message => {
console.log(message);
testThread.kill();
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUFxQjtBQUVyQiwwQ0FBeUM7QUFFekMsSUFBSSxrQkFBMkMsQ0FBQTtBQUMvQyxJQUFJLFVBQTJCLENBQUE7QUFFL0IsUUFBUSxDQUFDLFVBQVUsRUFBQztJQUNoQixFQUFFLENBQUMsNkNBQTZDLEVBQUM7UUFDN0Msa0JBQWtCLEdBQUcsSUFBSSxRQUFRLENBQUMsY0FBYyxDQUFDLENBQUMsS0FBSyxFQUFFLElBQUk7WUFDekQsSUFBSSxHQUFHLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFBO1lBQ3hCLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUE7UUFDMUIsQ0FBQyxDQUFDLENBQUE7UUFDRixrQkFBa0IsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTztZQUN0RCxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFBO1lBQ3BCLGtCQUFrQixDQUFDLElBQUksRUFBRSxDQUFBO1FBQzdCLENBQUMsQ0FBQyxDQUFBO0lBQ04sQ0FBQyxDQUFDLENBQUE7SUFDRixFQUFFLENBQUMscUNBQXFDLEVBQUM7UUFDckMsUUFBUSxDQUFDLGlCQUFpQixDQUFDLFNBQVMsQ0FBQyxDQUFBO1FBQ3JDLFVBQVUsR0FBRyxJQUFJLFFBQVEsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUE7UUFDNUMsVUFBVSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPO1lBQzlDLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUE7WUFDcEIsVUFBVSxDQUFDLElBQUksRUFBRSxDQUFBO1FBQ3JCLENBQUMsQ0FBQyxDQUFBO0lBQ04sQ0FBQyxDQUFDLENBQUE7QUFDTixDQUFDLENBQUMsQ0FBQSJ9

View File

@ -1,27 +1,61 @@
import 'typings-test'
import { expect, tap } from '@pushrocks/tapbundle';
import * as smartipc from '../dist/index'
import * as smartspawn from '../ts/index';
let testThreadFunction: smartipc.ThreadFunction
let testThread: smartipc.Thread
let testThreadFunction: smartspawn.ThreadFunction;
let testThread: smartspawn.Thread;
let testPool: smartspawn.Pool;
describe('smartipc',function(){
it('should create an instance of ThreadFunction',function(){
testThreadFunction = new smartipc.ThreadFunction((input, done) => {
let url = require('url')
done(url.parse(input))
})
testThreadFunction.send('https://google.com').then(message => {
console.log(message)
testThreadFunction.kill()
})
})
it('should create an instance of Thread',function(){
smartipc.setWorkerBasePath(__dirname)
testThread = new smartipc.Thread('child.js')
testThread.send('https://google.com').then(message => {
console.log(message)
testThread.kill()
})
})
})
/**
* create a normal ThreadFunction
*/
tap.test('should create an instance of ThreadFunction', async () => {
testThreadFunction = new smartspawn.ThreadFunction((input, done) => {
let url = require('url');
done(url.parse(input));
});
const message = await testThreadFunction.send('https://google.com');
console.log(message);
testThreadFunction.kill();
});
tap.test('should create an instance of Thread', async () => {
smartspawn.setWorkerBasePath(__dirname);
testThread = new smartspawn.Thread('../testassets/child.ts');
testThread.enableTypeScript();
const message = await testThread.send('https://google.com');
console.log(message);
testThread.kill();
});
tap.test('should not spawn when nothing is sent', async () => {
smartspawn.setWorkerBasePath(__dirname);
let testThread = new smartspawn.Thread('../testassets/child.ts');
});
tap.test('should run in a Pool', async () => {
let testPool = new smartspawn.Pool();
let testThread = new smartspawn.Thread('../testassets/child.ts');
testThread.assignToPool(testPool);
// first run
let message = await testThread.send('what');
expect(message).to.equal('what');
console.log(message);
// second run
message = await testThread.send('another');
expect(message).to.equal('another');
console.log(message);
// kill all
testThread.assignedPool.pool.killAll();
});
tap.test('should once', async () => {
let testThread = new smartspawn.Thread('../testassets/child.ts');
const message = await testThread.sendOnce('what');
expect(message).to.equal('what');
});
tap.start();

3
testassets/child.ts Normal file
View File

@ -0,0 +1,3 @@
module.exports = (input, done) => {
done(input);
};

View File

@ -1,2 +1,5 @@
export * from './smartipc.classes.thread'
export * from './smartipc.classes.threadfunction'
export * from './smartspawn.classes.thread';
export * from './smartspawn.classes.threadfunction';
export * from './smartspawn.classes.threadsimple';
export * from './smartspawn.classes.pool';
export * from './smartspawn.wrap';

View File

@ -1,34 +0,0 @@
import * as plugins from './smartipc.plugins'
import * as q from 'smartq'
export let setWorkerBasePath = (basePathArg: string) => {
plugins.threads.config.set({
basepath: {
node: basePathArg
}
})
}
export class Thread {
thread
constructor(filePathArg: string) {
this.thread = plugins.threads.spawn(filePathArg)
}
/**
* sends a message to the spawned process
*/
send<T>(message: any): Promise<T> {
let done = q.defer<T>()
this.thread.send(message).on('message', (message: T) => {
done.resolve(message)
}).on('error', err => {
done.reject(err)
})
return done.promise
}
kill() {
this.thread.kill()
}
}

View File

@ -1,31 +0,0 @@
import 'typings-global'
import * as plugins from './smartipc.plugins'
import * as q from 'smartq'
export interface IThreadFunction {
(input, done): void
}
export class ThreadFunction {
thread
constructor(functionArg: IThreadFunction) {
this.thread = plugins.threads.spawn(functionArg)
}
/**
* sends a message to the spawned process
*/
send<T>(message: any): Promise<T> {
let done = q.defer<T>()
this.thread.send(message).on('message', (message: T) => {
done.resolve(message)
}).on('error', err => {
done.reject(err)
})
return done.promise
}
kill() {
this.thread.kill()
}
}

View File

@ -1,8 +0,0 @@
import 'typings-global'
let threads = require('threads')
import * as smartq from 'smartq'
export {
smartq,
threads
}

View File

View File

@ -0,0 +1,6 @@
// ==============
// This file handles clustering of nodejs programs
// ==============
import * as plugins from './smartspawn.plugins';
export class Cluster {}

View File

@ -0,0 +1,13 @@
import * as plugins from './smartspawn.plugins';
export class Pool {
pool;
// the constructor for pool
constructor() {
this.pool = new plugins.threads.Pool();
}
run(workerPathArg: string) {
return this.pool.run(workerPathArg);
}
}

View File

@ -0,0 +1,85 @@
import * as plugins from './smartspawn.plugins';
import * as paths from './smartspawn.paths';
import * as q from 'smartq';
import { Pool } from './smartspawn.classes.pool';
import { startSpawnWrap, endSpawnWrap } from './smartspawn.wrap';
export let workerBasePath: string = null;
export const setWorkerBasePath = (basePathArg: string) => {
workerBasePath = basePathArg;
plugins.threads.config.set({
basepath: {
node: workerBasePath
}
});
};
export class Thread {
thread;
workerPath: string;
running: boolean = false;
assignedPool: Pool = null;
constructor(filePathArg: string) {
this.workerPath = filePathArg;
}
/**
* sends a message to the spawned process
* spawns it and keeps running
*/
send<T>(message: any): Promise<T> {
let done = q.defer<T>();
this._checkSpawn();
this.thread.send(message);
this.thread.on('message', (message: T) => {
done.resolve(message);
});
this.thread.on('done', (job, message: T) => {
done.resolve(message);
});
this.thread.on('error', err => {
done.reject(err);
});
return done.promise;
}
/**
* sends a command once and then kills the child process
*/
sendOnce<T>(message): Promise<T> {
let done = q.defer<T>();
this.send<T>(message).then(message => {
done.resolve(message);
this.kill();
});
return done.promise;
}
/**
* kills the thread
*/
kill() {
this.thread.kill();
this.running = false;
}
assignToPool(poolArg: Pool) {
this.assignedPool = poolArg;
}
enableTypeScript () {
// TODO:
}
private _checkSpawn() {
if (!this.running && !this.assignedPool) {
this.running = true;
this.thread = plugins.threads.spawn(this.workerPath);
} else if (!this.running && this.assignedPool) {
this.running = true;
this.thread = this.assignedPool.run(this.workerPath);
}
}
}

View File

@ -0,0 +1,34 @@
import 'typings-global';
import * as plugins from './smartspawn.plugins';
import * as q from 'smartq';
export interface IThreadFunction {
(input, done): void;
}
export class ThreadFunction {
thread;
constructor(functionArg: IThreadFunction) {
this.thread = plugins.threads.spawn(functionArg);
}
/**
* sends a message to the spawned process
*/
send<T>(message: any): Promise<T> {
let done = q.defer<T>();
this.thread
.send(message)
.on('message', (message: T) => {
done.resolve(message);
})
.on('error', err => {
done.reject(err);
});
return done.promise;
}
kill() {
this.thread.kill();
}
}

View File

@ -0,0 +1,35 @@
import * as plugins from './smartspawn.plugins';
import * as smartq from 'smartq';
import * as childProcess from 'child_process';
import { workerBasePath } from './smartspawn.classes.thread';
export class ThreadSimple {
workerPath: string;
threadChildProcess: childProcess.ChildProcess;
forkOptions: childProcess.ForkOptions;
argvArgs: string[];
constructor(
filePathArg: string,
argvArgs: string[] = [],
forkOptionsArg: childProcess.ForkOptions = {}
) {
this.workerPath = filePathArg;
this.forkOptions = forkOptionsArg;
this.argvArgs = argvArgs;
}
run() {
let done = smartq.defer<childProcess.ChildProcess>();
let forkPath = (() => {
if (workerBasePath) {
return plugins.path.join(workerBasePath, this.workerPath);
} else {
return this.workerPath;
}
})();
this.threadChildProcess = childProcess.fork(forkPath, this.argvArgs, this.forkOptions);
done.resolve(this.threadChildProcess);
return done.promise;
}
}

4
ts/smartspawn.paths.ts Normal file
View File

@ -0,0 +1,4 @@
import * as plugins from './smartspawn.plugins'
export const packageBase = plugins.path.join(__dirname, '../');
export const typescriptwrapJs = plugins.path.join(packageBase, 'assets/typescriptwrap.js');

5
ts/smartspawn.plugins.ts Normal file
View File

@ -0,0 +1,5 @@
import * as path from 'path';
let threads = require('threads');
import * as smartpromise from '@pushrocks/smartpromise';
export { path, smartpromise, threads };

18
ts/smartspawn.wrap.ts Normal file
View File

@ -0,0 +1,18 @@
import * as spawnWrap from 'spawn-wrap';
let unwrap: any = null;
export const startSpawnWrap = (filePath: string, cliArgs: string[] = [], envArgs: any = {}) => {
let spawnArray = [filePath];
for (let cliArg of cliArgs) {
spawnArray.push(cliArg);
}
unwrap = spawnWrap(spawnArray, envArgs);
};
export const endSpawnWrap = () => {
if (unwrap) {
unwrap();
unwrap = null;
}
};