Closed JimLiu closed 8 years ago
You can use SC with ES6, no problem.
// Import:
import SocketCluster from "socketcluster";
var sc = new SocketCluster({
brokerController: require.resolve("./mybroker.js")
});
// In mybroker.js:
export var run = function(worker) {
// ...
}
In theory, this should work.
Also, to load stuff like registrars, use the initController
option.
Cool, thanks!
Unfortunately, it can't work :disappointed:
Which version of Node.js are you using? New versions should be ES6.
@jondubois I use node v4.2 + Babel 6, the socketcluster version is 3.x, base on the sample code: https://github.com/SocketCluster/socketcluster/tree/master/sample
here is the code I changed:
index.js
require('babel-register');
require('./server');
server.js
import { SocketCluster } from 'socketcluster'
import minimist from 'minimist'
var argv = minimist(process.argv.slice(2));
var socketCluster = new SocketCluster({
workers: Number(argv.w) || 1,
brokers: Number(argv.b) || 1,
port: Number(argv.p) || 8000,
appName: argv.n || null,
workerController: __dirname + '/worker.js',
brokerController: __dirname + '/broker.js',
socketChannelLimit: 1000,
rebootWorkerOnCrash: argv['auto-reboot'] != false
});
run with
node index.js
works perfect if I did not change anything with worker.js or broker.js
but if I tried to write some ES6 code like this:
broker.js
module.exports.run = function (broker) {
const { pid } = process; // es6 code
console.log(' >> Broker PID:', pid);
};
Then got an error:
$ node index
[Busy] Launching SocketCluster
/sttest/broker.js:2
const { pid } = process; // es6 code
^
SyntaxError: Unexpected token {
at exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:414:25)
at Object.Module._extensions..js (module.js:442:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:311:12)
at Module.require (module.js:366:17)
at require (module.js:385:17)
at Object.<anonymous> (/sttest/node_modules/socketcluster/node_modules/iocluster/node_modules/ndata/server.js:25:23)
at Module._compile (module.js:435:26)
at Object.Module._extensions..js (module.js:442:10)
1450425115495 - Origin: IOCluster
[Error] Error: nData server at socket path /var/folders/4c/hh3fk19n3sq_djpcft9vpf7m0000gn/T/socketcluster/71bea5cc-fa0b-4348-b8f4-b7027900b448_9cba8c95ae/b0 exited
at EventEmitter.<anonymous> (/sttest/node_modules/socketcluster/node_modules/iocluster/index.js:353:28)
at emitTwo (events.js:87:13)
at EventEmitter.emit (events.js:172:7)
at ChildProcess.<anonymous> (/sttest/node_modules/socketcluster/node_modules/iocluster/node_modules/ndata/index.js:55:10)
at emitTwo (events.js:87:13)
at ChildProcess.emit (events.js:172:7)
at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
/sttest/broker.js:2
const { pid } = process; // es6 code
I'm not sure if I use it right, or any ES6 sample code I can refer to?
Mine. I'll upload it for you real quick (: I need to commit my changes, anyway... So give me a sec and youll have an example! ^^
I tried, but did not get the point.
server.js
works, but worker.js
can't work with ES6
Is there any ES6 sample base on this?
https://github.com/SocketCluster/socketcluster/tree/master/sample
Are you aware, that worker.js
is a new process?
In order to make it ES6 aware, use initController
.
Instantiation: https://github.com/DragonsInn/BIRD3/blob/master/app/Backend/Service/SocketCluster.js#L18-L20 The individual files: https://github.com/DragonsInn/BIRD3/tree/master/app/Backend/SocketCluster
I highlighted the relevant lines for you. Please see the mentioned files, to understand the flow.
Yes, I missed the initController
config, will try it later :)
I was the one to implement that feature for SC, for the sole reason of being able to drop registrars in, to allow custom JS dialects and transpilers to work. :).
Cool, as I suggested: The option workerController or brokerController is JS file path, could it changed to Class? Then we do not need use initController
Thats not possible. The files are being used to render a new process, so you can not drop arbitary objects there, instead you'll need to supply the path to a module that can be run instead.
I don't think it should be a path if it's used to render a new process.
I checked the code: https://github.com/SocketCluster/socketcluster/blob/master/lib/scworker.js#L240-L241
this._workerController = require(this._paths.appWorkerControllerPath);
this._workerController.run(this);
it require the path as an instance, then execute it's run
method.
so the workerController
option could be a class too.
for example:
export default class Worker {
run() {...}
}
import Worker from './worker'
var socketCluster = new SocketCluster({
workerController: Worker,
});
in scworker.js
var WorderController = this.option.workerController || defaultWorderController;
var worker = new WorderController();
workder.run();
Your research wasn't deep enough:
https://github.com/SocketCluster/socketcluster/issues/134#issuecomment-156849430
I had done this research on my own for a system I am coding, its also part of BIRD3. Read the linked post, it should be able to give you some insights of the forking and clustering done in SC. This will also explain why you can't just throw objects around - i.e., classes.
@IngwiePhoenix looks like you are right!
And it works after add initController
var socketCluster = new SocketCluster({
initController: __dirname + '/init.js',
});
init.js
module.exports.run = function(thisWorker) {
require("babel-register");
}
Thanks :)
Glad you got it working! :) Have fun with ES6!
Is it possible to use ES6 inside the Broker? Seems like initController option has no effect on the Broker.
Of course it does. initController was designed for that very purpose, to allow you to modify the global execution context. Are you using babel-register correctly? You need to explicitly call the function it returns - a mistake some people tend to do.
Yes, I call it like this require("babel/register")({stage: 0});
It does work in Workers but doesn't work in Broker somehow..
Odd. It should. I mean, I do the very same thing and it works. Hm…
You can see my working stuff here: https://github.com/dragonsinn/bird3/tree/master/app/Backend/SocketCluster https://github.com/dragonsinn/bird3/tree/master/app/Backend/SocketCluster
May I ask you to drop a line of ES6 (like import fs from 'fs'
) to the top of your Broker.js and try to run it? (At the moment you don't have ES6 code there).
I've just tried to test it on fresh SocketCluster boilerplate project and it is the same - ES6 works in Worker, but in Broker it doesn't. It looks like a bug.
Actually youre right. I re-wrote my broker. Im going to send a proper PR to fix that. Since i am the one that made initController, i should also fix it ^^
Found it. The problem is that the code of the Broker is being required before initController's run method is called https://github.com/SocketCluster/ndata/blob/master/server.js#L25
Yup. just wanted to post the same. Im going to hotfix it.
Well I just tried something else, and that actually avoids fixing!
// Enable OJ support inside NodeJS
require("oj-node");
// Bring in babel
require("../../bootstrap/nodejs/autoload");
// Enable Uniter support
//require("uniter-node");
module.exports.run = function(thisWorker) {
// Time to bootstrap workers.
// Put a global BIRD3 object in place
global.BIRD3 = require("../../Support/GlobalConfig");
//if(thisWorker.kind == "worker") { require("../Communicator")(redis, sc); }
}
(ignore my comments...)
You can also just supply an empty run method. But for reigstrars, just add them outside of it. I will think of a better way by fixing this code, so it is symmetric to SCWorkerCluster...but for now that will do.
Thanks :thumbsup:
Hello - is it ok to to use this method for production? According to babel , the module isnt meant for production
babel/example-node-server#13
Is there any other way possible though?
I'd like to write the code with es6, but
socketcluster
dose not support es6 code.The option
workerController
orbrokerController
is JS file path, could it changed to Class? for example:Then I can use
babel-register
to work with es6, like:entry.js
server.js