UNPKG

global_session

Version:

A link between LRU and messaging to peers which may store or cache LRU entries remotely

378 lines (299 loc) 10.7 kB
const {ServeMessageEndpoint} = require('message-relay-services') const { XXHash32 } = require('xxhash32-node-cmake') const {conf_loader,fix_path} = require("../lib/utils") let conf = conf_loader(process.argv[2],'./test/ml_endpoint_1.conf') console.dir(conf) // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- const DFLT_SLOW_MESSAGE_QUERY_INTERVAL = 5000 const DFLT_FAST_MESSAGE_QUERY_INTERVAL = 1000 // ---- ---- ---- ---- ---- ---- ---- ---- ---- const SESSION_GENERATION_PUB = "session" const WANT_SESSION_FOR_ID = "need_session" const APPRISE_SESSION_IN_RESPONSE = "session_known" const SESSION_ALREADY_RECEIVED = "session_received" const MAX_EVICTS = 10 const MIN_DELTA = 1000*60*60 // millisecs const MAX_FAUX_HASH = 100000 const INTER_PROC_DESCRIPTOR_WORDS = 8 const DEFAULT_RESIDENCY_TIMEOUT = MIN_DELTA // const SUPER_HEADER = 256 const MAX_LOCK_ATTEMPTS = 3 const WORD_SIZE = 4 const LONG_WORD_SIZE = 8 const HH_HEADER_SIZE = 64 // const PID_INDEX = 0 const WRITE_FLAG_INDEX = 1 const INFO_INDEX_LRU = 2 const INFO_INDEX_HH = 3 const NUM_INFO_FIELDS = 4 const LRU_HEADER = 64 var g_app_seed = 0 var g_hasher32 = null var g_buf_enc = new TextEncoder() function default_hash(data) { if ( !(g_hasher32) ) return(0) try { if ( typeof data === "string" ) { let buf = g_buf_enc.encode(data) data = buf } g_hasher32.update(data) let h = g_hasher32.digest() let hh = h.readUInt32BE(0) g_hasher32.reset() return hh } catch (e) { console.log(e) } return 0 } function init_default(seed) { g_app_seed = parseInt(seed,16); g_hasher32 = new XXHash32(g_app_seed); return default_hash } class FAUX_LRU { constructor(conf) { this.conf = conf this.hasher = init_default(conf.seed) // // removed lines for test. // this.eviction_interval = null // this._faux_map = {} // } // ---- ---- ---- ---- ---- ---- ---- ---- ---- hash(value) { let hh = this.hasher(value) let top = hh % this.count let augmented_hash_token = top + '-' + hh return( augmented_hash_token ) } async set(hash_augmented,value) { if ( typeof value === 'string' ) { if ( !(value.length) ) return(-1) if ( value.length > this.record_size ) return(-1) } else { value = (value).toString(16) } let pair = hash_augmented.split('-') // this._faux_map[hash_augmented] = [pair,value] } async get(hash_augmented) { let [pair,value] = this._faux_map[hash_augmented] return(value) } async del(hash_augmented) { delete this._faux_map[hash_augmented] let result = true return(result) } async delete(hash_augmented) { return this.del(hash_augmented) } // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- /// handle_evicted(evict_list) app_handle_evicted(evict_list) { // app may decide to forward these elsewhere are send shutdown messages, etc. } } class FAUX_FOR_TEST_LRUManager { // constructor(conf) { // //conf.module_path = conf.module_path.replace('/lib','') //conf.module_path = fix_path(conf.module_path) //conf.cache.module_path = conf.module_path //conf.cache._test_use_no_memory = true /// LINE ADDED FOR TEST // this.cache = new FAUX_LRU(conf.cache) this.in_operation = true this.conf = conf // } initialize(conf) { } // set(key,value) { let sdata = ( typeof value !== 'string' ) ? JSON.stringify(value) : value let augmented_hash_token = this.cache.hash(key) this.cache.set(augmented_hash_token, sdata) // store in the LRU cache return(augmented_hash_token) // return the derived key } set_with_token(token,value) { let sdata = ( typeof value !== 'string' ) ? JSON.stringify(value) : value this.cache.set(token, sdata) // store in the LRU cache } hash_set(key,value) { let sdata = ( typeof value !== 'string' ) ? JSON.stringify(value) : value let augmented_hash_token = this.cache.hash(key) let hh_unidentified = this.cache.hasher(sdata) this.cache.set(augmented_hash_token, hh_unidentified) // store in the LRU cache return(hh_unidentified) // return the derived key } check_hash(hh_unid,value) { let sdata = ( typeof value !== 'string' ) ? JSON.stringify(value) : value let hh_unidentified = this.cache.hasher(sdata) return hh_unidentified === hh_unid } // delete(key) { // token must have been returned by set () -> augmented_hash_token let augmented_hash_token = this.cache.hash(key) this.cache.del(augmented_hash_token) } // get(key) { // token must have been returned by set () -> augmented_hash_token let augmented_hash_token = this.cache.hash(key) let value = false if ( typeof value !== 'string' ) { return false } return value } get_with_token(token) { let value = this.cache.get(token) if ( typeof value !== 'string' ) { return false } return value } // disconnect(opt) { this.in_operation = false return this.cache.disconnect(opt) } } const NON_PUB_BLOCKING = [SESSION_GENERATION_PUB,APPRISE_SESSION_IN_RESPONSE,SESSION_ALREADY_RECEIVED] class SessionMidpoint_TEST extends ServeMessageEndpoint { constructor (conf) { super(conf) this._LRUManager = new FAUX_FOR_TEST_LRUManager(conf); } async load_data(msg_obj) { let key = msg_obj.key return this._LRUManager.get(key) } async create_entry_type(msg_obj) { let value = msg_obj.value let token = msg_obj.hash this._LRUManager.set_with_token(token,value) return true } async update_entry_type(msg_obj) { let token = msg_obj.hash this._LRUManager.get_with_token(token) return true } async delete_entry_type(msg_obj) { let key = msg_obj.key this.delete(key) return true } #has_needed_id(msg_obj) { // is the stuff in my cache? if ( msg_obj ) { // double check --- there is a topic that came to this method if ( typeof msg_obj.topic === "undefined" ) return false // if ( NON_PUB_BLOCKING.indexOf(msg_obj.topic) >= 0 ) return false // let key = msg_obj.key let value = this._LRUManager.get(key) if ( value ) { let augmented_hash_token = this._LRUManager.cache.hash(key) let msg = { "value" : value, "key" : key, "hash" : augmented_hash_token } return msg } } return false } // app_publication_pre_fan_response --> // -- in the session midpoint, only support id requests to subscribed and connected // -- clients (those should be obtaining session requests absent from their LRUs on their processors.) app_publication_pre_fan_response(topic,msg_obj,respond_to) { // respond_to is a writer // if ( WANT_SESSION_FOR_ID !== topic ) return false // let info_msg = this.#has_needed_id(msg_obj) if ( info_msg ) { info_msg._m_path = this.conf.auth_path let proc_id = msg.requester let targeted_topic = `${APPRISE_SESSION_IN_RESPONSE}-${proc_id}` info_msg.topic = targeted_topic let str_msg = JSON.stringify(info_msg) respond_to.write(str_msg) // sock made by this server managed by relayer ... pass on message return true } // return false } // app_subscription_handler // --- a post action after publication ... // this will put the augmented_hash_token into the LRU belonging to the midpoint async app_subscription_handler(topic,msg_obj) { // put the stuff into my caches if ( topic === SESSION_GENERATION_PUB ) { // insert into the endpoint server cache for later shortcutting return... let value = msg_obj.value let augmented_hash_token = msg_obj.hash this._LRUManager.set_with_token(augmented_hash_token,value) } } // async app_message_handler(msg_obj) { let op = msg_obj._tx_op let result = "OK" let user_id = msg_obj._user_dir_key ? msg_obj[msg_obj._user_dir_key] : msg_obj._id if ( this.create_OK && !!(user_id) ) { await this.ensure_user_directories(user_id) } msg_obj._id = user_id // switch ( op ) { case 'G' : { // get user information let stat = "OK" let data = await this.load_data(msg_obj) if ( data === false ) stat = "ERR" return({ "status" : stat, "data" : data, "explain" : "get", "when" : Date.now() }) } case 'D' : { // delete sesssion from everywhere if all ref counts gones. result = await this.delete_entry_type(msg_obj) break } case 'S' : { // or send let action = msg_obj._user_op if ( action === "create" ) { result = await this.create_entry_type(msg_obj) result = result ? "OK" : "ERR" } else if ( action === "update" ) { result = await this.update_entry_type(msg_obj) result = result ? "OK" : "ERR" } break } default : { break } } // return({ "status" : result, "explain" : "op performed", "when" : Date.now(), "ucwid" : msg_obj.ucwid }) } } class SessionClusterServer extends SessionMidpoint_TEST { constructor(conf) { super(conf) } report_status() { console.log(`Session Server: PORT: ${conf.port} ADDRESS: ${conf.address}`) console.log("READY") } } let cl_server = new SessionClusterServer(conf) cl_server.report_status()