Initial commit
This commit is contained in:
commit
153265b0c0
84
infrastructure.js
Normal file
84
infrastructure.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
"use stict";
|
||||||
|
|
||||||
|
const cl = global.botanLoader;
|
||||||
|
|
||||||
|
const events = require( "events" );
|
||||||
|
const util = require( "util" );
|
||||||
|
|
||||||
|
var Infrastructure = function()
|
||||||
|
{
|
||||||
|
events.EventEmitter.call( this );
|
||||||
|
var _self = this;
|
||||||
|
|
||||||
|
var __readyList = [];
|
||||||
|
this.readyList = new Proxy( __readyList, {
|
||||||
|
|
||||||
|
get: ( target, prop ) => Reflect.get( target, prop )
|
||||||
|
|
||||||
|
, set: ( target, prop, value ) => {
|
||||||
|
|
||||||
|
// Have to emit the event at next tick
|
||||||
|
// due to error thrown from the handlers
|
||||||
|
// hangs the process
|
||||||
|
process.nextTick( () => {
|
||||||
|
if( __readyList.every( ( v ) => v === true ) )
|
||||||
|
{
|
||||||
|
_self.isReady = true;
|
||||||
|
_self.emit( "apis_ready", _self )
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
return Reflect.set( target, prop, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
this.APIs = {};
|
||||||
|
this.isReady = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
util.inherits( Infrastructure, events.EventEmitter );
|
||||||
|
|
||||||
|
Infrastructure.prototype.callAPI = function( name )
|
||||||
|
{
|
||||||
|
var _self = this;
|
||||||
|
|
||||||
|
var propName = name.split( "." );
|
||||||
|
propName = name[ name.length - 1 ];
|
||||||
|
|
||||||
|
if( this.APIs[ propName ] ) return this.APIs[ propName ];
|
||||||
|
|
||||||
|
var path = name.replace( ".", "/" );
|
||||||
|
|
||||||
|
var API = cl.load( name );
|
||||||
|
|
||||||
|
if( !API.create )
|
||||||
|
{
|
||||||
|
throw new Error( "API does not have support calling" );
|
||||||
|
}
|
||||||
|
|
||||||
|
var aclass = API.create( Array.prototype.slice.call( arguments, 1 ) );
|
||||||
|
|
||||||
|
this.APIs[ propName ] = aclass;
|
||||||
|
|
||||||
|
if( aclass.ready !== undefined )
|
||||||
|
{
|
||||||
|
this.isReady = false;
|
||||||
|
|
||||||
|
var rList = this.readyList;
|
||||||
|
rList.push( aclass.ready || aclass );
|
||||||
|
|
||||||
|
aclass.once( "ready", ( e ) => rList[ rList.indexOf( e ) ] = true );
|
||||||
|
}
|
||||||
|
|
||||||
|
return aclass;
|
||||||
|
};
|
||||||
|
|
||||||
|
Infrastructure.prototype.Ready = function( callback )
|
||||||
|
{
|
||||||
|
var _self = this;
|
||||||
|
if( this.isReady ) callback();
|
||||||
|
else this.once( "apis_ready", () => callback() );
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Infrastructure;
|
22
redisclient.js
Normal file
22
redisclient.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
const cl = global.botanLoader;
|
||||||
|
const Dragonfly = global.Dragonfly;
|
||||||
|
|
||||||
|
const Redis = require( "redis" );
|
||||||
|
|
||||||
|
const SessConf = cl.load( "config.sx.modular.session" );
|
||||||
|
|
||||||
|
var Client = Redis.createClient(
|
||||||
|
SessConf.config.port
|
||||||
|
, SessConf.config.host
|
||||||
|
, SessConf.config.options
|
||||||
|
);
|
||||||
|
|
||||||
|
Client.addListener( "error", ( e ) => { throw e; } );
|
||||||
|
|
||||||
|
Client.select( SessConf.config.database, function( err, message )
|
||||||
|
{
|
||||||
|
if( err ) throw err;
|
||||||
|
Dragonfly.Info( "[Session] Database connected. Ready." );
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Client;
|
152
session.js
Normal file
152
session.js
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const cl = global.botanLoader;
|
||||||
|
const Dragonfly = global.Dragonfly;
|
||||||
|
|
||||||
|
const util = require( "util" );
|
||||||
|
const EventEmitter = require( "events" ).EventEmitter;
|
||||||
|
|
||||||
|
const Client = cl.load( "botansx.modular.redisclient" );
|
||||||
|
const rand = cl.load( "botansx.utils.random" );
|
||||||
|
const SessConf = cl.load( "config.sx.modular.session" );
|
||||||
|
|
||||||
|
class SessionEventArgs
|
||||||
|
{
|
||||||
|
constructor( message )
|
||||||
|
{
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Session extends EventEmitter
|
||||||
|
{
|
||||||
|
static create( args )
|
||||||
|
{
|
||||||
|
if( !args ) args = [];
|
||||||
|
return new Session( args[0], args[1] );
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor( hash, prefix, noIdReset )
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
var _self = this;
|
||||||
|
|
||||||
|
if( hash && prefix )
|
||||||
|
hash = hash.replace( new RegExp( "^" + prefix + "\\." ), "" );
|
||||||
|
|
||||||
|
prefix = prefix ? prefix + "." : "";
|
||||||
|
|
||||||
|
this.id = prefix + hash;
|
||||||
|
this.ready = false;
|
||||||
|
this.exists = false;
|
||||||
|
|
||||||
|
Client.HGETALL( this.id, function( err, obj )
|
||||||
|
{
|
||||||
|
if( err ) throw err;
|
||||||
|
|
||||||
|
if( _self.exists = !!obj )
|
||||||
|
{
|
||||||
|
_self.__sess = obj;
|
||||||
|
}
|
||||||
|
// Auto reset the session id if no match
|
||||||
|
else if( !noIdReset )
|
||||||
|
{
|
||||||
|
_self.id = prefix + rand.uuid();
|
||||||
|
}
|
||||||
|
|
||||||
|
_self.ready = true;
|
||||||
|
_self.emit( "ready", _self );
|
||||||
|
} );
|
||||||
|
|
||||||
|
this.__sess = {};
|
||||||
|
this.__emitOk = ( e, m ) => {
|
||||||
|
_self.__emit( e, "set", new SessionEventArgs( m ) );
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
__emit( err, EventName, SessionArgs )
|
||||||
|
{
|
||||||
|
if( err ) throw err;
|
||||||
|
this.emit( EventName || "set", this, SessionArgs );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Spawn session with specified id
|
||||||
|
spawn( expire, handler )
|
||||||
|
{
|
||||||
|
var ttl = ( expire === undefined ? SessConf.ttl : expire ) + 0;
|
||||||
|
this.__sess[ "lifespan" ] = ttl;
|
||||||
|
|
||||||
|
var _self = this;
|
||||||
|
Client.multi()
|
||||||
|
.HSET( this.id, "spawn", new Date() )
|
||||||
|
.HSET( this.id, "lifespan", ttl )
|
||||||
|
.EXPIRE( this.id, ttl )
|
||||||
|
.exec( handler || this.__emitOk );
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy( handler )
|
||||||
|
{
|
||||||
|
this.__sess = {};
|
||||||
|
Client.DEL( this.id, handler || this.__emitOk );
|
||||||
|
}
|
||||||
|
|
||||||
|
set( name, val )
|
||||||
|
{
|
||||||
|
this.__sess[ name ] = val;
|
||||||
|
Client.HSET( this.id, name, val, this.__emitOk );
|
||||||
|
}
|
||||||
|
|
||||||
|
get( name )
|
||||||
|
{
|
||||||
|
return this.__sess[ name ];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get value asynchronously
|
||||||
|
aget( name, handler )
|
||||||
|
{
|
||||||
|
var _self = this;
|
||||||
|
Client.HGET(
|
||||||
|
this.id, name
|
||||||
|
, function( err, rep )
|
||||||
|
{
|
||||||
|
_self.__emitOk( err );
|
||||||
|
_self.__sess[ name ] = rep;
|
||||||
|
handler && handler( rep );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
remove( name )
|
||||||
|
{
|
||||||
|
delete this.__sess[ name ];
|
||||||
|
Client.HDEL( this.id, name, this.__emitOk );
|
||||||
|
}
|
||||||
|
|
||||||
|
expire( seconds )
|
||||||
|
{
|
||||||
|
// expire > lifespan > SessConf.ttl
|
||||||
|
var ttl = ( seconds === undefined
|
||||||
|
? ( ( this.__sess[ "lifespan" ] === undefined )
|
||||||
|
? SessConf.ttl
|
||||||
|
: this.__sess[ "lifespan" ]
|
||||||
|
) : seconds ) + 0
|
||||||
|
;
|
||||||
|
|
||||||
|
this.__sess[ "lifespan" ] = ttl;
|
||||||
|
|
||||||
|
Client.multi()
|
||||||
|
.HSET( this.id, "lifespan", ttl )
|
||||||
|
.EXPIRE( this.id, ttl, this.__emitOk )
|
||||||
|
.exec( this.__emitOk );
|
||||||
|
}
|
||||||
|
|
||||||
|
get busy()
|
||||||
|
{
|
||||||
|
return 0 < ( Client.command_queue.length + Client.offline_queue.length );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Session.SessionEventArgs = SessionEventArgs;
|
||||||
|
|
||||||
|
module.exports = Session;
|
Loading…
Reference in New Issue
Block a user