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

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 + '$');
}