feat: 초기 프로젝트 설정 및 룰.md 파일 추가

This commit is contained in:
2025-07-28 09:53:31 +09:00
commit 09a4d38512
8165 changed files with 1021855 additions and 0 deletions

148
api.hyungi.net/node_modules/pm2-axon/History.md generated vendored Normal file
View File

@@ -0,0 +1,148 @@
=======
2.0.1 / 2014-09-09
==================
* fix Floating-point durations to setTimeout may cause infinite loop
2.0.0 / 2014-02-25
==================
* refactor to use the AMP protocol. Closes #577
* remove old codec support
1.0.0 / 2013-08-30
==================
* change Socket#connect() to use inaddr_any as well
0.6.1 / 2013-04-13
==================
* fix Socket#close() callback support
* add callback to reply() when peer is gone
0.6.0 / 2013-04-13
==================
* add optional reply() callback. Closes #95
* add support for optional req.send() callback. Closes #89
0.5.2 / 2013-04-09
==================
* add `sock.queue` array for logging / debugging etc
* fix connection queue flush which may drop messages on connection
0.5.1 / 2013-03-01
==================
* add exit() to HWM example
* add better HWM example
* fix: ignore closed sockets on reply(). fixes #82
0.5.0 / 2013-01-01
==================
* add HWM support. Closes #19
* add ability to pass a callback in to the Socket.close method.
* update benchmarks. Closes #72
* remove batching
0.4.6 / 2012-11-15
==================
* fix round-robin write to unwritable socket
0.4.5 / 2012-10-30
==================
* add more network errors to be ignored
* refactor `SubEmitter`
* refactor `PubEmitter`
* fix exponential backoff
0.4.4 / 2012-10-29
==================
* fix round-robin global var leak for fallback function. Closes #66
0.4.3 / 2012-10-27
==================
* add 30% throughput increase for sub-emitter by removing some indirection
* fix `PubSocket#flushBatch()` in order to avoid writing to not writable sockets [AlexeyKupershtokh]
0.4.2 / 2012-10-18
==================
* add 30% throughput increase for sub-emitter by removing some indirection
* add escaping of regexp chars for `SubSocket#subscribe()`
* fix non-multipart `SubEmitterSocket` logic
0.4.1 / 2012-10-16
==================
* add removal of sockets on error
* add handling of __ECONNRESET__, __ECONNREFUSED__, and __EPIPE__. Closes #17
* add immediate closing of sockets on `.close()`
* fix "bind" event. Closes #53
* fix 'close' event for server sockets
* remove "stream" socket type for now
0.4.0 / 2012-10-12
==================
* add emitter wildcard support
* add sub socket subscription support
* add `pub-emitter`
* add `sub-emitter`
* perf: remove `.concat()` usage, ~10% gain
* remove greetings
0.3.2 / 2012-10-08
==================
* change prefix fix to `reply()` only
0.3.1 / 2012-10-08
==================
* add fix for reply(undefined)
0.3.0 / 2012-10-05
==================
* add `Socket#address()` to help with ephemeral port binding. Closes #39
* add default identity of __PID__. Closes #35
* remove examples for router/dealer
0.2.0 / 2012-09-27
==================
* add default random `identity`
* add `req.send()` callback support
* remove router / dealer
* change `ReqSocket` to round-robin send()s
0.1.0 / 2012-09-24
==================
* add router socket [gjohnson]
* add dealer socket [gjohnson]
* add req socket [gjohnson]
* add rep socket [gjohnson]
* add multipart support [gjohnson]
* add `.set()` / `.get()` configuration methods
* add tcp://hostname:port support to .bind() and .connect(). Closes #16
* add `make bm`
* add Batch#empty()
* remove Socket#option()
0.0.3 / 2012-07-14
==================
* add resize example
* add `debug()` instrumentation
* add `PullSocket` bind support
* add `Parser`

22
api.hyungi.net/node_modules/pm2-axon/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2012-2013 TJ Holowaychuk <tj@vision-media.ca>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

361
api.hyungi.net/node_modules/pm2-axon/Readme.md generated vendored Normal file
View File

@@ -0,0 +1,361 @@
# Axon
Axon is a message-oriented socket library for node.js heavily inspired by zeromq. For a light-weight
UDP alternative you may be interested in [punt](https://github.com/visionmedia/punt).
[![Build Status](https://travis-ci.org/unitech/pm2-axon.png)](https://travis-ci.org/unitech/pm2-axon)
## Installation
$ npm install axon
## Features
- message oriented
- automated reconnection
- light-weight wire protocol
- mixed-type arguments (strings, objects, buffers, etc)
- unix domain socket support
- fast (~800 mb/s ~500,000 messages/s)
## Events
- `close` when server or connection is closed
- `error` (err) when an un-handled socket error occurs
- `ignored error` (err) when an axon-handled socket error occurs, but is ignored
- `socket error` (err) emitted regardless of handling, for logging purposes
- `reconnect attempt` when a reconnection attempt is made
- `connect` when connected to the peer, or a peer connection is accepted
- `disconnect` when an accepted peer disconnects
- `bind` when the server is bound
- `drop` (msg) when a message is dropped due to the HWM
- `flush` (msgs) queued when messages are flushed on connection
## Patterns
- push / pull
- pub / sub
- req / rep
- pub-emitter / sub-emitter
## Mixed argument types
Backed by [node-amp-message](https://github.com/visionmedia/node-amp-message)
you may pass strings, objects, and buffers as arguments.
```js
push.send('image', { w: 100, h: 200 }, imageBuffer);
pull.on('message', function(type, size, img){});
```
## Push / Pull
`PushSocket`s distribute messages round-robin:
```js
var axon = require('axon');
var sock = axon.socket('push');
sock.bind(3000);
console.log('push server started');
setInterval(function(){
sock.send('hello');
}, 150);
```
Receiver of `PushSocket` messages:
```js
var axon = require('axon');
var sock = axon.socket('pull');
sock.connect(3000);
sock.on('message', function(msg){
console.log(msg.toString());
});
```
Both `PushSocket`s and `PullSocket`s may `.bind()` or `.connect()`. In the
following configuration the push socket is bound and pull "workers" connect
to it to receive work:
![push bind](http://f.cl.ly/items/473u3m1a0k1i0J0I3s04/ss-push.png)
This configuration shows the inverse, where workers connect to a "sink"
to push results:
![pull bind](http://f.cl.ly/items/3Y0j2v153Q0l1r373i0H/ss-pull.png)
## Pub / Sub
`PubSocket`s send messages to all subscribers without queueing. This is an
important difference when compared to a `PushSocket`, where the delivery of
messages will be queued during disconnects and sent again upon the next connection.
```js
var axon = require('axon');
var sock = axon.socket('pub');
sock.bind(3000);
console.log('pub server started');
setInterval(function(){
sock.send('hello');
}, 500);
```
`SubSocket` simply receives any messages from a `PubSocket`:
```js
var axon = require('axon');
var sock = axon.socket('sub');
sock.connect(3000);
sock.on('message', function(msg){
console.log(msg.toString());
});
```
`SubSocket`s may optionally `.subscribe()` to one or more "topics" (the first multipart value),
using string patterns or regular expressions:
```js
var axon = require('axon');
var sock = axon.socket('sub');
sock.connect(3000);
sock.subscribe('user:login');
sock.subscribe('upload:*:progress');
sock.on('message', function(topic, msg){
});
```
## Req / Rep
`ReqSocket` is similar to a `PushSocket` in that it round-robins messages
to connected `RepSocket`s, however it differs in that this communication is
bi-directional, every `req.send()` _must_ provide a callback which is invoked
when the `RepSocket` replies.
```js
var axon = require('axon');
var sock = axon.socket('req');
sock.bind(3000);
sock.send(img, function(res){
});
```
`RepSocket`s receive a `reply` callback that is used to respond to the request,
you may have several of these nodes.
```js
var axon = require('axon');
var sock = axon.socket('rep');
sock.connect(3000);
sock.on('message', function(img, reply){
// resize the image
reply(img);
});
```
Like other sockets you may provide multiple arguments or an array of arguments,
followed by the callbacks. For example here we provide a task name of "resize"
to facilitate multiple tasks over a single socket:
```js
var axon = require('axon');
var sock = axon.socket('req');
sock.bind(3000);
sock.send('resize', img, function(res){
});
```
Respond to the "resize" task:
```js
var axon = require('axon');
var sock = axon.socket('rep');
sock.connect(3000);
sock.on('message', function(task, img, reply){
switch (task) {
case 'resize':
// resize the image
reply(img);
break;
}
});
```
## PubEmitter / SubEmitter
`PubEmitter` and `SubEmitter` are higher-level `Pub` / `Sub` sockets, using the "json" codec to behave much like node's `EventEmitter`. When a `SubEmitter`'s `.on()` method is invoked, the event name is `.subscribe()`d for you. Each wildcard (`*`) or regexp capture group is passed to the callback along with regular message arguments.
app.js:
```js
var axon = require('axon');
var sock = axon.socket('pub-emitter');
sock.connect(3000);
setInterval(function(){
sock.emit('login', { name: 'tobi' });
}, 500);
```
logger.js:
```js
var axon = require('axon');
var sock = axon.socket('sub-emitter');
sock.bind(3000);
sock.on('user:login', function(user){
console.log('%s signed in', user.name);
});
sock.on('user:*', function(action, user){
console.log('%s %s', user.name, action);
});
sock.on('*', function(event){
console.log(arguments);
});
```
## Socket Options
Every socket has associated options that can be configured via `get/set`.
- `identity` - the "name" of the socket that uniqued identifies it.
- `retry timeout` - connection retry timeout in milliseconds [100] (0 = do not reconnect)
- `retry max timeout` - the cap for retry timeout length in milliseconds [5000]
- `hwm` - the high water mark threshold for queues [Infinity]
## Binding / Connecting
In addition to passing a portno, binding to INADDR_ANY by default, you
may also specify the hostname via `.bind(port, host)`, another alternative
is to specify the url much like zmq via `tcp://<hostname>:<portno>`, thus
the following are equivalent:
```
sock.bind(3000)
sock.bind(3000, '0.0.0.0')
sock.bind('tcp://0.0.0.0:3000')
sock.connect(3000)
sock.connect(3000, '0.0.0.0')
sock.connect('tcp://0.0.0.0:3000')
```
You may also use unix domain sockets:
```
sock.bind('unix:///some/path')
sock.connect('unix:///some/path')
```
## Protocol
Axon 2.x uses the extremely simple [AMP](https://github.com/visionmedia/node-amp) protocol to send messages on the wire. Codecs are no longer required as they were in Axon 1.x.
## Performance
Preliminary benchmarks on my Macbook Pro based on 10 messages
per tick as a realistic production application would likely have
even less than this. "better" numbers may be acheived with batching
and a larger messages/tick count however this is not realistic.
64 byte messages:
```
min: 47,169 ops/s
mean: 465,127 ops/s
median: 500,000 ops/s
total: 2,325,636 ops in 5s
through: 28.39 mb/s
```
1k messages:
```
min: 48,076 ops/s
mean: 120,253 ops/s
median: 121,951 ops/s
total: 601,386 ops in 5.001s
through: 117.43 mb/s
```
8k messages:
```
min: 36,496 ops/s
mean: 53,194 ops/s
median: 50,505 ops/s
total: 266,506 ops in 5.01s
through: 405.84 mb/s
````
32k messages:
```
min: 12,077 ops/s
mean: 14,792 ops/s
median: 16,233 ops/s
total: 74,186 ops in 5.015s
through: 462.28 mb/s
```
## What's it good for?
Axon are not meant to combat zeromq nor provide feature parity,
but provide a nice solution when you don't need the insane
nanosecond latency or language interoperability that zeromq provides
as axon do not rely on any third-party compiled libraries.
## Running tests
```
$ npm install
$ make test
```
## Authors
- [visionmedia](http://github.com/visionmedia)
- [gjohnson](https://github.com/gjohnson)
## Links
- [Screencast](https://vimeo.com/45818408)
- [Axon RPC](https://github.com/visionmedia/axon-rpc)
## License
MIT

2
api.hyungi.net/node_modules/pm2-axon/index.js generated vendored Normal file
View File

@@ -0,0 +1,2 @@
module.exports = require('./lib');

View File

@@ -0,0 +1,5 @@
0.0.1 / 2010-01-03
==================
* Initial release

View File

@@ -0,0 +1,7 @@
test:
@./node_modules/.bin/mocha \
--require should \
--reporter spec
.PHONY: test

View File

@@ -0,0 +1,57 @@
# configurable
Configuration mixin.
## API
Make something configurable:
```js
var Configurable = require('configurable');
// plain obj
var obj = {};
Configurable(obj);
// returns the obj itself
var obj = Configurable({});
// make a prototype configurable
Configurable(MyThing.prototype);
```
```js
.get(name)
.set(name, val)
.set(obj)
.enable(name)
.disable(name)
.enabled(name)
.disabled(name)
```
## License
(The MIT License)
Copyright (c) 2012 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,2 @@
module.exports = require('./lib/configurable');

View File

@@ -0,0 +1,47 @@
/**
* Make `obj` configurable.
*
* @param {Object} obj
* @return {Object} the `obj`
* @api public
*/
module.exports = function(obj){
obj.settings = {};
obj.set = function(name, val){
if (1 == arguments.length) {
for (var key in name) {
this.set(key, name[key]);
}
} else {
this.settings[name] = val;
}
return this;
};
obj.get = function(name){
return this.settings[name];
};
obj.enable = function(name){
return this.set(name, true);
};
obj.disable = function(name){
return this.set(name, false);
};
obj.enabled = function(name){
return !! this.get(name);
};
obj.disabled = function(name){
return ! this.get(name);
};
return obj;
};

View File

@@ -0,0 +1,68 @@
{
"_args": [
[
{
"raw": "configurable@0.0.1",
"scope": null,
"escapedName": "configurable",
"name": "configurable",
"rawSpec": "0.0.1",
"spec": "0.0.1",
"type": "version"
},
"/home/unitech/keymetrics/pm2-axon"
]
],
"_from": "configurable@0.0.1",
"_id": "configurable@0.0.1",
"_inCache": true,
"_installable": true,
"_location": "/configurable",
"_phantomChildren": {},
"_requested": {
"raw": "configurable@0.0.1",
"scope": null,
"escapedName": "configurable",
"name": "configurable",
"rawSpec": "0.0.1",
"spec": "0.0.1",
"type": "version"
},
"_requiredBy": [
"/"
],
"_resolved": "https://registry.npmjs.org/configurable/-/configurable-0.0.1.tgz",
"_shasum": "47d75b727b51b4eb84c1dadafe3f8240313833b1",
"_shrinkwrap": null,
"_spec": "configurable@0.0.1",
"_where": "/home/unitech/keymetrics/pm2-axon",
"author": {
"name": "TJ Holowaychuk",
"email": "tj@vision-media.ca"
},
"dependencies": {},
"description": "Configuration mixin",
"devDependencies": {
"mocha": "*",
"should": "*"
},
"directories": {},
"dist": {
"shasum": "47d75b727b51b4eb84c1dadafe3f8240313833b1",
"tarball": "https://registry.npmjs.org/configurable/-/configurable-0.0.1.tgz"
},
"keywords": [
"configuration"
],
"main": "index",
"maintainers": [
{
"name": "tjholowaychuk",
"email": "tj@vision-media.ca"
}
],
"name": "configurable",
"optionalDependencies": {},
"readme": "ERROR: No README data found!",
"version": "0.0.1"
}

44
api.hyungi.net/node_modules/pm2-axon/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,44 @@
/**
* Constructors.
*/
exports.PubEmitterSocket = require('./sockets/pub-emitter');
exports.SubEmitterSocket = require('./sockets/sub-emitter');
exports.PushSocket = require('./sockets/push');
exports.PullSocket = require('./sockets/pull');
exports.PubSocket = require('./sockets/pub');
exports.SubSocket = require('./sockets/sub');
exports.ReqSocket = require('./sockets/req');
exports.RepSocket = require('./sockets/rep');
exports.Socket = require('./sockets/sock');
/**
* Socket types.
*/
exports.types = {
'pub-emitter': exports.PubEmitterSocket,
'sub-emitter': exports.SubEmitterSocket,
'push': exports.PushSocket,
'pull': exports.PullSocket,
'pub': exports.PubSocket,
'sub': exports.SubSocket,
'req': exports.ReqSocket,
'rep': exports.RepSocket
};
/**
* Return a new socket of the given `type`.
*
* @param {String} type
* @param {Object} options
* @return {Socket}
* @api public
*/
exports.socket = function(type, options){
var fn = exports.types[type];
if (!fn) throw new Error('invalid socket type "' + type + '"');
return new fn(options);
};

View File

@@ -0,0 +1,71 @@
/**
* Module dependencies.
*/
var debug = require('debug')('axon:queue');
/**
* Queue plugin.
*
* Provides an `.enqueue()` method to the `sock`. Messages
* passed to `enqueue` will be buffered until the next
* `connect` event is emitted.
*
* Emits:
*
* - `drop` (msg) when a message is dropped
* - `flush` (msgs) when the queue is flushed
*
* @param {Object} options
* @api private
*/
module.exports = function(options){
options = options || {};
return function(sock){
/**
* Message buffer.
*/
sock.queue = [];
/**
* Flush `buf` on `connect`.
*/
sock.on('connect', function(){
var prev = sock.queue;
var len = prev.length;
sock.queue = [];
debug('flush %d messages', len);
for (var i = 0; i < len; ++i) {
this.send.apply(this, prev[i]);
}
sock.emit('flush', prev);
});
/**
* Pushes `msg` into `buf`.
*/
sock.enqueue = function(msg){
var hwm = sock.settings.hwm;
if (sock.queue.length >= hwm) return drop(msg);
sock.queue.push(msg);
};
/**
* Drop the given `msg`.
*/
function drop(msg) {
debug('drop');
sock.emit('drop', msg);
}
};
};

View File

@@ -0,0 +1,55 @@
/**
* Deps.
*/
var slice = require('../utils').slice;
/**
* Round-robin plugin.
*
* Provides a `send` method which will
* write the `msg` to all connected peers.
*
* @param {Object} options
* @api private
*/
module.exports = function(options){
options = options || {};
var fallback = options.fallback || function(){};
return function(sock){
/**
* Bind callback to `sock`.
*/
fallback = fallback.bind(sock);
/**
* Initialize counter.
*/
var n = 0;
/**
* Sends `msg` to all connected peers round-robin.
*/
sock.send = function(){
var socks = this.socks;
var len = socks.length;
var sock = socks[n++ % len];
var msg = slice(arguments);
if (sock && sock.writable) {
sock.write(this.pack(msg));
} else {
fallback(msg);
}
};
};
};

View File

@@ -0,0 +1,26 @@
/**
* Module dependencies.
*/
var PubSocket = require('./pub');
/**
* Expose `SubPubEmitterSocket`.
*/
module.exports = PubEmitterSocket;
/**
* Initialzie a new `PubEmitterSocket`.
*
* @api private
*/
function PubEmitterSocket() {
this.sock = new PubSocket;
this.emit = this.sock.send.bind(this.sock);
this.bind = this.sock.bind.bind(this.sock);
this.connect = this.sock.connect.bind(this.sock);
this.close = this.sock.close.bind(this.sock);
}

View File

@@ -0,0 +1,77 @@
/**
* Module dependencies.
*/
var Socket = require('./sock');
var slice = require('../utils').slice;
/**
* Expose `PubSocket`.
*/
module.exports = PubSocket;
/**
* Initialize a new `PubSocket`.
*
* @api private
*/
function PubSocket() {
Socket.call(this);
}
/**
* Inherits from `Socket.prototype`.
*/
PubSocket.prototype.__proto__ = Socket.prototype;
/**
* Send `msg` to all established peers.
*
* @param {Mixed} msg
* @api public
*/
PubSocket.prototype.send = function(msg){
var socks = this.socks;
var len = socks.length;
var buf = this.pack(arguments);
for (var sock of socks) {
if (sock.writable) sock.write(buf);
}
return this;
};
PubSocket.prototype.sendv2 = function(data, cb){
var socks = this.socks;
var len = socks.length;
var sock;
if (len == 0)
return process.nextTick(cb);
var buf = this.pack([data]);
var i = 0;
socks.forEach(function(sock) {
if (sock.writable)
sock.write(buf, function() {
i++;
if (i == len)
process.nextTick(cb);
});
else {
i++;
if (i == len)
process.nextTick(cb);
}
});
return this;
};

View File

@@ -0,0 +1,37 @@
/**
* Module dependencies.
*/
var Socket = require('./sock');
/**
* Expose `PullSocket`.
*/
module.exports = PullSocket;
/**
* Initialize a new `PullSocket`.
*
* @api private
*/
function PullSocket() {
Socket.call(this);
// TODO: selective reception
}
/**
* Inherits from `Socket.prototype`.
*/
PullSocket.prototype.__proto__ = Socket.prototype;
/**
* Pull sockets should not send messages.
*/
PullSocket.prototype.send = function(){
throw new Error('pull sockets should not send messages');
};

View File

@@ -0,0 +1,32 @@
/**
* Module dependencies.
*/
var roundrobin = require('../plugins/round-robin');
var queue = require('../plugins/queue');
var Socket = require('./sock');
/**
* Expose `PushSocket`.
*/
module.exports = PushSocket;
/**
* Initialize a new `PushSocket`.
*
* @api private
*/
function PushSocket() {
Socket.call(this);
this.use(queue());
this.use(roundrobin({ fallback: this.enqueue }));
}
/**
* Inherits from `Socket.prototype`.
*/
PushSocket.prototype.__proto__ = Socket.prototype;

View File

@@ -0,0 +1,73 @@
/**
* Module dependencies.
*/
var slice = require('../utils').slice;
var debug = require('debug')('axon:rep');
var Message = require('amp-message');
var Socket = require('./sock');
/**
* Expose `RepSocket`.
*/
module.exports = RepSocket;
/**
* Initialize a new `RepSocket`.
*
* @api private
*/
function RepSocket() {
Socket.call(this);
}
/**
* Inherits from `Socket.prototype`.
*/
RepSocket.prototype.__proto__ = Socket.prototype;
/**
* Incoming.
*
* @param {net.Socket} sock
* @return {Function} closure(msg, mulitpart)
* @api private
*/
RepSocket.prototype.onmessage = function(sock){
var self = this;
return function (buf){
var msg = new Message(buf);
var args = msg.args;
var id = args.pop();
args.unshift('message');
args.push(reply);
self.emit.apply(self, args);
function reply() {
var fn = function(){};
var args = slice(arguments);
args[0] = args[0] || null;
var hasCallback = 'function' == typeof args[args.length - 1];
if (hasCallback) fn = args.pop();
args.push(id);
if (sock.writable) {
sock.write(self.pack(args), function(){ fn(true) });
return true;
} else {
debug('peer went away');
process.nextTick(function(){ fn(false) });
return false;
}
}
};
};

101
api.hyungi.net/node_modules/pm2-axon/lib/sockets/req.js generated vendored Normal file
View File

@@ -0,0 +1,101 @@
/**
* Module dependencies.
*/
var debug = require('debug')('axon:req');
var queue = require('../plugins/queue');
var slice = require('../utils').slice;
var Message = require('amp-message');
var Socket = require('./sock');
/**
* Expose `ReqSocket`.
*/
module.exports = ReqSocket;
/**
* Initialize a new `ReqSocket`.
*
* @api private
*/
function ReqSocket() {
Socket.call(this);
this.n = 0;
this.ids = 0;
this.callbacks = {};
this.identity = this.get('identity');
this.use(queue());
}
/**
* Inherits from `Socket.prototype`.
*/
ReqSocket.prototype.__proto__ = Socket.prototype;
/**
* Return a message id.
*
* @return {String}
* @api private
*/
ReqSocket.prototype.id = function(){
return this.identity + ':' + this.ids++;
};
/**
* Emits the "message" event with all message parts
* after the null delimeter part.
*
* @param {net.Socket} sock
* @return {Function} closure(msg, multipart)
* @api private
*/
ReqSocket.prototype.onmessage = function(){
var self = this;
return function(buf){
var msg = new Message(buf);
var id = msg.pop();
var fn = self.callbacks[id];
if (!fn) return debug('missing callback %s', id);
fn.apply(null, msg.args);
delete self.callbacks[id];
};
};
/**
* Sends `msg` to the remote peers. Appends
* the null message part prior to sending.
*
* @param {Mixed} msg
* @api public
*/
ReqSocket.prototype.send = function(msg){
var socks = this.socks;
var len = socks.length;
var sock = socks[this.n++ % len];
var args = slice(arguments);
if (sock) {
var hasCallback = 'function' == typeof args[args.length - 1];
if (!hasCallback) args.push(function(){});
var fn = args.pop();
fn.id = this.id();
this.callbacks[fn.id] = fn;
args.push(fn.id);
}
if (sock) {
sock.write(this.pack(args));
} else {
debug('no connected peers');
this.enqueue(args);
}
};

View File

@@ -0,0 +1,415 @@
/**
* Module dependencies.
*/
var Emitter = require('events').EventEmitter;
var Configurable = require('../configurable');
var debug = require('debug')('axon:sock');
var Message = require('amp-message');
var Parser = require('amp').Stream;
var url = require('url');
var net = require('net');
var fs = require('fs');
/**
* Errors to ignore.
*/
var ignore = [
'ECONNREFUSED',
'ECONNRESET',
'ETIMEDOUT',
'EHOSTUNREACH',
'ENETUNREACH',
'ENETDOWN',
'EPIPE',
'ENOENT'
];
/**
* Expose `Socket`.
*/
module.exports = Socket;
/**
* Initialize a new `Socket`.
*
* A "Socket" encapsulates the ability of being
* the "client" or the "server" depending on
* whether `connect()` or `bind()` was called.
*
* @api private
*/
function Socket() {
var self = this;
this.opts = {};
this.server = null;
this.socks = [];
this.settings = {};
this.set('hwm', Infinity);
this.set('identity', String(process.pid));
this.set('retry timeout', 100);
this.set('retry max timeout', 5000);
}
/**
* Inherit from `Emitter.prototype`.
*/
Socket.prototype.__proto__ = Emitter.prototype;
/**
* Make it configurable `.set()` etc.
*/
Configurable(Socket.prototype);
/**
* Use the given `plugin`.
*
* @param {Function} plugin
* @api private
*/
Socket.prototype.use = function(plugin){
plugin(this);
return this;
};
/**
* Creates a new `Message` and write the `args`.
*
* @param {Array} args
* @return {Buffer}
* @api private
*/
Socket.prototype.pack = function(args){
var msg = new Message(args);
return msg.toBuffer();
};
/**
* Close all open underlying sockets.
*
* @api private
*/
Socket.prototype.closeSockets = function(){
debug('closing %d connections', this.socks.length);
this.socks.forEach(function(sock){
sock.destroy();
});
};
/**
* Close the socket.
*
* Delegates to the server or clients
* based on the socket `type`.
*
* @param {Function} [fn]
* @api public
*/
Socket.prototype.close = function(fn){
debug('closing');
this.closing = true;
this.closeSockets();
if (this.server) this.closeServer(fn);
};
/**
* Close the server.
*
* @param {Function} [fn]
* @api public
*/
Socket.prototype.closeServer = function(fn){
debug('closing server');
this.server.on('close', this.emit.bind(this, 'close'));
this.server.close();
fn && fn();
};
/**
* Return the server address.
*
* @return {Object}
* @api public
*/
Socket.prototype.address = function(){
if (!this.server) return;
var addr = this.server.address();
addr.string = 'tcp://' + addr.address + ':' + addr.port;
return addr;
};
/**
* Remove `sock`.
*
* @param {Socket} sock
* @api private
*/
Socket.prototype.removeSocket = function(sock){
var i = this.socks.indexOf(sock);
if (!~i) return;
debug('remove socket %d', i);
this.socks.splice(i, 1);
};
/**
* Add `sock`.
*
* @param {Socket} sock
* @api private
*/
Socket.prototype.addSocket = function(sock){
var parser = new Parser;
var i = this.socks.push(sock) - 1;
debug('add socket %d', i);
sock.pipe(parser);
parser.on('data', this.onmessage(sock));
};
/**
* Handle `sock` errors.
*
* Emits:
*
* - `error` (err) when the error is not ignored
* - `ignored error` (err) when the error is ignored
* - `socket error` (err) regardless of ignoring
*
* @param {Socket} sock
* @api private
*/
Socket.prototype.handleErrors = function(sock){
var self = this;
sock.on('error', function(err){
debug('error %s', err.code || err.message);
self.emit('socket error', err);
self.removeSocket(sock);
if (!~ignore.indexOf(err.code)) return self.emit('error', err);
debug('ignored %s', err.code);
self.emit('ignored error', err);
});
};
/**
* Handles framed messages emitted from the parser, by
* default it will go ahead and emit the "message" events on
* the socket. However, if the "higher level" socket needs
* to hook into the messages before they are emitted, it
* should override this method and take care of everything
* it self, including emitted the "message" event.
*
* @param {net.Socket} sock
* @return {Function} closure(msg, mulitpart)
* @api private
*/
Socket.prototype.onmessage = function(sock){
var self = this;
return function(buf){
var msg = new Message(buf);
self.emit.apply(self, ['message'].concat(msg.args), sock);
};
};
/**
* Connect to `port` at `host` and invoke `fn()`.
*
* Defaults `host` to localhost.
*
* TODO: needs big cleanup
*
* @param {Number|String} port
* @param {String} host
* @param {Function} fn
* @return {Socket}
* @api public
*/
Socket.prototype.connect = function(port, host, fn){
var self = this;
if ('server' == this.type) throw new Error('cannot connect() after bind()');
if ('function' == typeof host) fn = host, host = undefined;
if ('string' == typeof port) {
port = url.parse(port);
if (port.pathname) {
fn = host;
host = null;
fn = undefined;
port = port.pathname;
} else {
host = port.hostname || '0.0.0.0';
port = parseInt(port.port, 10);
}
} else {
host = host || '0.0.0.0';
}
var max = self.get('retry max timeout');
var sock = new net.Socket;
sock.setNoDelay();
this.type = 'client';
port = port;
this.handleErrors(sock);
sock.on('close', function(){
self.connected = false;
self.removeSocket(sock);
if (self.closing) return self.emit('close');
var retry = self.retry || self.get('retry timeout');
if (retry === 0) return self.emit('close');
setTimeout(function(){
debug('attempting reconnect');
self.emit('reconnect attempt');
sock.destroy();
self.connect(port, host);
self.retry = Math.round(Math.min(max, retry * 1.5));
}, retry);
});
sock.on('connect', function(){
debug('connect');
self.connected = true;
self.addSocket(sock);
self.retry = self.get('retry timeout');
self.emit('connect');
fn && fn();
});
debug('connect attempt %s:%s', host, port);
sock.connect(port, host);
return this;
};
/**
* Handle connection.
*
* @param {Socket} sock
* @api private
*/
Socket.prototype.onconnect = function(sock){
var self = this;
var addr = null;
if (sock.remoteAddress && sock.remotePort)
addr = sock.remoteAddress + ':' + sock.remotePort;
else if (sock.server && sock.server._pipeName)
addr = sock.server._pipeName;
debug('accept %s', addr);
this.addSocket(sock);
this.handleErrors(sock);
this.emit('connect', sock);
sock.on('close', function(){
debug('disconnect %s', addr);
self.emit('disconnect', sock);
self.removeSocket(sock);
});
};
/**
* Bind to `port` at `host` and invoke `fn()`.
*
* Defaults `host` to INADDR_ANY.
*
* Emits:
*
* - `connection` when a client connects
* - `disconnect` when a client disconnects
* - `bind` when bound and listening
*
* @param {Number|String} port
* @param {Function} fn
* @return {Socket}
* @api public
*/
Socket.prototype.bind = function(port, host, fn){
var self = this;
if ('client' == this.type) throw new Error('cannot bind() after connect()');
if ('function' == typeof host) fn = host, host = undefined;
var unixSocket = false;
if ('string' == typeof port) {
port = url.parse(port);
if (port.pathname) {
fn = host;
host = null;
port = port.pathname;
unixSocket = true;
} else {
host = port.hostname || '0.0.0.0';
port = parseInt(port.port, 10);
}
} else {
host = host || '0.0.0.0';
}
this.type = 'server';
this.server = net.createServer(this.onconnect.bind(this));
debug('bind %s:%s', host, port);
this.server.on('listening', this.emit.bind(this, 'bind'));
if (unixSocket) {
// TODO: move out
this.server.on('error', function(e) {
debug('Got error while trying to bind', e.stack || e);
if (e.code == 'EADDRINUSE') {
// Unix file socket and error EADDRINUSE is the case if
// the file socket exists. We check if other processes
// listen on file socket, otherwise it is a stale socket
// that we could reopen
// We try to connect to socket via plain network socket
var clientSocket = new net.Socket();
clientSocket.on('error', function(e2) {
debug('Got sub-error', e2);
if (e2.code == 'ECONNREFUSED' || e2.code == 'ENOENT') {
// No other server listening, so we can delete stale
// socket file and reopen server socket
try {
fs.unlinkSync(port);
} catch(e) {}
self.server.listen(port, host, fn);
}
});
clientSocket.connect({path: port}, function() {
// Connection is possible, so other server is listening
// on this file socket
if (fn) return fn(new Error('Process already listening on socket ' + port));
});
}
else {
try {
fs.unlinkSync(port);
} catch(e) {}
self.server.listen(port, host, fn);
}
});
}
this.server.listen(port, host, fn);
return this;
};

View File

@@ -0,0 +1,92 @@
/**
* Module dependencies.
*/
var Message = require('amp-message');
var SubSocket = require('./sub');
/**
* Expose `SubEmitterSocket`.
*/
module.exports = SubEmitterSocket;
/**
* Initialzie a new `SubEmitterSocket`.
*
* @api private
*/
function SubEmitterSocket() {
this.sock = new SubSocket;
this.sock.onmessage = this.onmessage.bind(this);
this.bind = this.sock.bind.bind(this.sock);
this.connect = this.sock.connect.bind(this.sock);
this.close = this.sock.close.bind(this.sock);
this.listeners = [];
}
/**
* Message handler.
*
* @param {net.Socket} sock
* @return {Function} closure(msg, mulitpart)
* @api private
*/
SubEmitterSocket.prototype.onmessage = function(){
var listeners = this.listeners;
var self = this;
return function(buf){
var msg = new Message(buf);
var topic = msg.shift();
for (var i = 0; i < listeners.length; ++i) {
var listener = listeners[i];
var m = listener.re.exec(topic);
if (!m) continue;
listener.fn.apply(this, m.slice(1).concat(msg.args));
}
}
};
/**
* Subscribe to `event` and invoke the given callback `fn`.
*
* @param {String} event
* @param {Function} fn
* @return {SubEmitterSocket} self
* @api public
*/
SubEmitterSocket.prototype.on = function(event, fn){
var re = this.sock.subscribe(event);
this.listeners.push({
event: event,
re: re,
fn: fn
});
return this;
};
/**
* Unsubscribe with the given `event`.
*
* @param {String} event
* @return {SubEmitterSocket} self
* @api public
*/
SubEmitterSocket.prototype.off = function(event){
for (var i = 0; i < this.listeners.length; ++i) {
if (this.listeners[i].event === event) {
this.sock.unsubscribe(this.listeners[i].re);
this.listeners.splice(i--, 1);
}
}
return this;
};

148
api.hyungi.net/node_modules/pm2-axon/lib/sockets/sub.js generated vendored Normal file
View File

@@ -0,0 +1,148 @@
/**
* Module dependencies.
*/
var debug = require('debug')('axon:sub');
var escape = require('escape-string-regexp');
var Message = require('amp-message');
var Socket = require('./sock');
/**
* Expose `SubSocket`.
*/
module.exports = SubSocket;
/**
* Initialize a new `SubSocket`.
*
* @api private
*/
function SubSocket() {
Socket.call(this);
this.subscriptions = [];
}
/**
* Inherits from `Socket.prototype`.
*/
SubSocket.prototype.__proto__ = Socket.prototype;
/**
* Check if this socket has subscriptions.
*
* @return {Boolean}
* @api public
*/
SubSocket.prototype.hasSubscriptions = function(){
return !! this.subscriptions.length;
};
/**
* Check if any subscriptions match `topic`.
*
* @param {String} topic
* @return {Boolean}
* @api public
*/
SubSocket.prototype.matches = function(topic){
for (var i = 0; i < this.subscriptions.length; ++i) {
if (this.subscriptions[i].test(topic)) {
return true;
}
}
return false;
};
/**
* Message handler.
*
* @param {net.Socket} sock
* @return {Function} closure(msg, mulitpart)
* @api private
*/
SubSocket.prototype.onmessage = function(sock){
var subs = this.hasSubscriptions();
var self = this;
return function(buf){
var msg = new Message(buf);
if (subs) {
var topic = msg.args[0];
if (!self.matches(topic)) return debug('not subscribed to "%s"', topic);
}
self.emit.apply(self, ['message'].concat(msg.args).concat(sock));
};
};
/**
* Subscribe with the given `re`.
*
* @param {RegExp|String} re
* @return {RegExp}
* @api public
*/
SubSocket.prototype.subscribe = function(re){
debug('subscribe to "%s"', re);
this.subscriptions.push(re = toRegExp(re));
return re;
};
/**
* Unsubscribe with the given `re`.
*
* @param {RegExp|String} re
* @api public
*/
SubSocket.prototype.unsubscribe = function(re){
debug('unsubscribe from "%s"', re);
re = toRegExp(re);
for (var i = 0; i < this.subscriptions.length; ++i) {
if (this.subscriptions[i].toString() === re.toString()) {
this.subscriptions.splice(i--, 1);
}
}
};
/**
* Clear current subscriptions.
*
* @api public
*/
SubSocket.prototype.clearSubscriptions = function(){
this.subscriptions = [];
};
/**
* Subscribers should not send messages.
*/
SubSocket.prototype.send = function(){
throw new Error('subscribers cannot send messages');
};
/**
* Convert `str` to a `RegExp`.
*
* @param {String} str
* @return {RegExp}
* @api private
*/
function toRegExp(str) {
if (str instanceof RegExp) return str;
str = escape(str);
str = str.replace(/\\\*/g, '(.+)');
return new RegExp('^' + str + '$');
}

19
api.hyungi.net/node_modules/pm2-axon/lib/utils.js generated vendored Normal file
View File

@@ -0,0 +1,19 @@
/**
* Slice helper.
*
* @api private
* @param {Arguments} args
* @return {Array}
*/
exports.slice = function(args){
var len = args.length;
var ret = new Array(len);
for (var i = 0; i < len; i++) {
ret[i] = args[i];
}
return ret;
};

46
api.hyungi.net/node_modules/pm2-axon/package.json generated vendored Normal file
View File

@@ -0,0 +1,46 @@
{
"name": "pm2-axon",
"description": "High-level messaging & socket patterns implemented in pure js",
"version": "4.0.1",
"author": {
"name": "TJ Holowaychuk",
"email": "tj@vision-media.ca"
},
"engines": {
"node": ">=5"
},
"dependencies": {
"amp": "~0.3.1",
"amp-message": "~0.1.1",
"debug": "^4.3.1",
"escape-string-regexp": "^4.0.0"
},
"devDependencies": {
"better-assert": "*",
"commander": "*",
"humanize-number": "0.0.2",
"mocha": "^8.1",
"should": "*"
},
"keywords": [
"zmq",
"zeromq",
"pubsub",
"socket",
"emitter",
"ipc",
"rpc"
],
"repository": {
"type": "git",
"url": "https://github.com/Unitech/pm2-axon.git"
},
"scripts": {
"test": "make test"
},
"license": "MIT",
"files": [
"lib",
"index.js"
]
}