oa.getOAuthAccessToken(oauth_token, api.credentials.oauth_token_secret, oauth_verifier, function(error, oauth_access_token, oauth_access_token_secret, results2) { if(error) { // handle error winston.error(error); manager.enqueue('finishAuth', error, cb); self.finished = true; } else { api.credentials.oauth_access_token = oauth_access_token; api.credentials.oauth_token_secret = oauth_access_token_secret; api.credentials.oauth_consumer_key = oaData.oauth_consumer_key; api.credentials.authConfig = oaData; client.set(bid+key+'oauth', JSON.stringify(api.credentials)); var tout = { expires: new Date(), redirect: GLOBAL.config.url+'/bundle/'+bid, err: {errnum:1, errtxt:"Authentication provider requires code."}, cname: key }; manager.enqueue('finishAuth', tout, cb, { "oauth_consumer_key": api.credentials.oauth_consumer_key, //"oauth_nonce": bid+","+key, //"oauth_signature": xxx, "oauth_signature_method": oaData.encryption, "oauth_timestamp": Math.floor( (new Date()).getTime() / 1000 ), "oauth_token": api.credentials.oauth_access_token }); self.finished = true; } });
oa.getOAuthRequestToken(function(error, oauth_token, oauth_token_secret, results){ if(error) { winston.error(error); manager.enqueue('finishAuth', error, cb); self.finished = true; } else { api.credentials = { 'oauth_token': oauth_token, 'oauth_token_secret': oauth_token_secret, 'type': 'oauth', 'provider': api.auth.provider }; client.set(bid+key+'oauth', JSON.stringify(api.credentials)); var tout = { expires: new Date(), redirect: oaData.authorize+"?oauth_token="+api.credentials.oauth_token, err: {errnum:1, errtxt:"Authentication provider requires code."}, cname: key, guid: uuid.v4() }; winston.debug('Authorize redirect response:' + JSON.stringify(tout)); manager.enqueue('finishAuth', tout, cb); self.finished = true; } });
client.get(bid+key+'oauth', function (err, doc) { if (err || doc === null) { manager.enqueue('getTemporaryCredentials', api, bid, key, cb ); } else { api.credentials = JSON.parse(doc); if (_.has(api.credentials, 'oauth_access_token')) { manager.enqueue('finishAuth', true, cb, { "oauth_consumer_key": api.credentials.oauth_consumer_key, //"oauth_nonce": bid+","+key, //"oauth_signature": xxx, "oauth_signature_method": oaData.encryption, "oauth_timestamp": Math.floor( (new Date()).getTime() / 1000 ), "oauth_token": api.credentials.oauth_access_token }); } else { manager.enqueue('getTemporaryCredentials', api, bid, key, cb ); } } });
oa.getOAuthAccessToken(thisCode, params, function(error, access_token, refresh_token, results) { winston.info('Run callback for oauth2:getOAuthAccessToken'); if(error) { winston.error('Error oauth2:getOAuthAccessToken('+bid+key+'): '+JSON.stringify(error)); var tout = { expires: new Date(), err: error, cname: key }; manager.enqueue('finishAuth', tout, cb); self.finsihed = true; } else { winston.debug('access_token = '+access_token); api.credentials.type = 'oauth2'; api.credentials.provider = api.auth.provider; api.credentials.access_token = access_token; winston.debug('typeof refresh_token = '+typeof refresh_token); if (typeof refresh_token !== 'undefined') { winston.debug('first refresh token = '+refresh_token); api.credentials.refresh_token = refresh_token; } api.credentials.expires = new Date().add({seconds: (results.expires_in - 300)}); winston.debug(JSON.stringify(api.credentials)); client.set(bid+key+'oauth2', JSON.stringify(api.credentials)); winston.debug(bid+key+'oauth2 saved'); manager.enqueue('finishAuth', true, cb, { "access_token": api.credentials.access_token }); self.finished = true; } });
work: function( api, bid, key, cb ) { winston.info('Run job oauth2:getCode'); var oaData = GLOBAL.config.authentication[api.auth.provider]; var oa = new oauth2(oaData.client_id, oaData.client_secret, oaData.baseSite, oaData.authorizePath, oaData.accessTokenPath), self = this; var tout = { expires: new Date(), redirect: oa.getAuthorizeUrl({ 'response_type': 'code', 'redirect_uri': GLOBAL.config.url+'/oauth2', 'scope': api.auth.scope, 'state': bid + "," + key, 'access_type': 'offline', 'approval_prompt': 'force' }), err: {errnum:1, errtxt:"Authentication provider requires code."}, cname: key }; winston.debug(JSON.stringify(tout)); manager.enqueue('finishAuth', tout, cb); self.finished = true; }
function get_job_data(id, job) { var data = {id: id, status: job.status}; if ('error' === job.status) { data.error = job.error; // as long as user got info about error // remove the job from the cache delete jobs[id]; } if ('enqueued' === job.status) { data.position = job_mgr.getPosition('generate-font', job.worker_id); if (-1 === data.position) { data.status = 'processing'; delete data.position; } } if ('finished' === job.status) { data.url = job.url; } return data; }
get_job(font_id, function (job) { if (job && jobs[font_id]) { nodeca.logger.info("Job already in queue: " + JSON.stringify({ font_id : font_id, queue_length: _.keys(jobs).length })); } else if (job) { nodeca.logger.info("Font already exists: " + JSON.stringify({ font_id: font_id })); } else { // enqueue new unique job job = jobs[font_id] = { start: Date.now(), status: 'enqueued', worker_id: job_mgr.enqueue('generate-font', font_id, font) }; nodeca.logger.info("New job created: " + JSON.stringify({ font_id : font_id, queue_length: _.keys(jobs).length })); } self.response.data = get_job_data(font_id, job); callback(); });
get_job(font_id, function (job) { // enqueue new unique job if (!job) { job = jobs[font_id] = { start: Date.now(), status: 'enqueued', worker_id: job_mgr.enqueue('generate-font', font_id, glyphs) }; } self.response.data = get_job_data(font_id, job); callback(); });
client.get(bid+key+'oauth', function(err, doc) { if (err || doc === null) { // handle error here } else { api.credentials = JSON.parse(doc); if (oauth_verifier) api.credentials.oauth_verifier = oauth_verifier; manager.enqueue('getAccessToken', api, bid, key, oauth_token, oauth_verifier, cb) } });
client.get(bid+key+'oauth2', function (err, doc) { if (err || doc === null) { manager.enqueue('getCode', api, bid, key, cb ); } else { api.credentials = JSON.parse(doc); api.credentials.expires = new Date(api.credentials.expires); if (_.has(api.credentials, 'access_token')) { if (api.credentials.expires.isBefore(new Date())) { manager.enqueue('getAccessToken', api, bid, key, cb, 'refresh_token' ); } else { manager.enqueue('finishAuth', true, cb, { "access_token": api.credentials.access_token }); } } else { manager.enqueue('getAccessToken', api, bid, key, cb, 'authorization_code' ); } } });
exports.saveCode = function( res, state, code, cb) { winston.info('function oauth2:saveCode'); var doc = {"code": code }; client.set(state[0]+state[1]+'oauth2', JSON.stringify(doc)); var tout = { expires: new Date(), redirect: GLOBAL.config.url + '/bundle/' + state[0] } manager.enqueue('finishAuth', tout, cb); }
N.wire.on(apiPath, function (env, callback) { var font = fontConfig(env.params), font_id, errmsg; if (env.params.css_use_suffix === 'false') { env.params.css_use_suffix = false; } if (env.params.css_use_suffix === 'true') { env.params.css_use_suffix = true; } if (!font || 0 >= font.glyphs.length) { callback("Invalid request"); return; } if (CONFIG.max_glyphs && CONFIG.max_glyphs < font.glyphs.length) { errmsg = 'Too many icons requested: ' + font.glyphs.length + ' of ' + CONFIG.max_glyphs + ' allowed.'; env.response.error = { code: 'MAX_GLYPHS_LIMIT' , message: errmsg }; logger.warn(errmsg); callback(); return; } font_id = getDownloadID(font); if (JOBS[font_id]) { logger.info("Job already in queue: " + JSON.stringify({ font_id: font_id , queue_length: _.keys(JOBS).length })); } else { // enqueue new unique job JOBS[font_id] = Date.now(); jobMgr.enqueue('generate-font', font_id, font); logger.info("New job created: " + JSON.stringify({ font_id: font_id , queue_length: _.keys(JOBS).length })); } env.response.data.id = font_id; env.response.data.status = 'enqueued'; callback(); });
module.exports.generate = function (params, callback) { var self = this, font = get_font_config(params), font_id, errmsg; if (!font || 0 >= font.glyphs.length) { callback("Invalid request"); return; } if (CONFIG.max_glyphs && CONFIG.max_glyphs < font.glyphs.length) { errmsg = 'Too many icons requested: ' + font.glyphs.length + ' of ' + CONFIG.max_glyphs + ' allowed.'; this.response.error = { code: 'MAX_GLYPHS_LIMIT', message: errmsg }; nodeca.logger.warn(errmsg); callback(); return; } font_id = get_download_id(font); if (jobs[font_id]) { nodeca.logger.info("Job already in queue: " + JSON.stringify({ font_id : font_id, queue_length: _.keys(jobs).length })); } else { // enqueue new unique job jobs[font_id] = Date.now(); job_mgr.enqueue('generate-font', font_id, font); nodeca.logger.info("New job created: " + JSON.stringify({ font_id : font_id, queue_length: _.keys(jobs).length })); } self.response.data = {id: font_id, status: 'enqueued'}; callback(); };
return [a, b, 'fontello-' + font_id].join("/") + ".zip"; } function get_download_url(font_id) { return DOWNLOAD_URL_PREFIX + get_download_path(font_id); } // status of jobs by their ids var jobs = {}; // define queue and jobs var job_mgr = new (neuron.JobManager)(); job_mgr.addJob('generate-font', { dirname: '/tmp', concurrency: (CONFIG.builder_concurrency || os.cpus().length), work: function (font_id, config) { var self = this, log_prefix = '[font::' + font_id + '] ', tmp_dir, zipball, times; try { tmp_dir = path.join(TMP_DIR, "fontello-" + font_id); zipball = path.join(DOWNLOAD_DIR, get_download_path(font_id)); times = [jobs[font_id]]; nodeca.logger.info(log_prefix + 'Start generation: ' + JSON.stringify(config));
if (!source_fonts) { source_fonts = {}; fonts_dir = path.join(APP_ROOT, 'assets/embedded_fonts'); _.each(get_font(), function (config, name) { source_fonts[name] = path.join(fonts_dir, name + '.ttf'); }); } return source_fonts; } // define queue and jobs var job_mgr = new (neuron.JobManager)(); job_mgr.addJob('generate-font', { dirname: '/tmp', concurrency: (CONFIG.builder_concurrency || os.cpus().length), work: function (font_id, glyphs, user) { var self = this, fontname = "fontello-" + font_id.substr(0, 8), tmp_dir = path.join(TMP_DIR, "fontello-" + font_id), zipball = path.join(DOWNLOAD_DIR, get_download_path(font_id)), times = [jobs[font_id].start], config; // FIXME: after server restart this might become "undefined" // // I'm still unsure WHAT might cause such behavior, as after restart // manager should have empty stack.
if (!source_fonts) { source_fonts = {}; fonts_dir = path.join(APP_ROOT, 'assets/embedded_fonts'); _.each(get_font(), function (config, name) { source_fonts[name] = path.join(fonts_dir, name + '.ttf'); }); } return source_fonts; } // define queue and jobs var job_mgr = new (neuron.JobManager)(); job_mgr.addJob('generate-font', { dirname: '/tmp', concurrency: 4, work: function (font_id, glyphs) { var self = this, fontname = "fontello-" + font_id.substr(0, 8), tmp_dir = path.join(TMP_DIR, "fontello-" + font_id), zipball = path.join(DOWNLOAD_DIR, get_download_path(font_id)), times = [jobs[font_id].start], config; // push timer checkpoint times.push(Date.now()); // generate font config
require('date-utils'); /* Connect to redis */ var client = redis.createClient(GLOBAL.config.redis.port, GLOBAL.config.redis.address); if (GLOBAL.config.redis.auth) { client.auth(GLOBAL.config.redis.auth, function (err) { if (err) { // handle err; } }); } var manager = new neuron.JobManager(); manager.addJob('finishAuth', { work: function( tout, cb, authParams ) { winston.info('Run job oauth2:finishAuth'); cb(tout, authParams); } }); manager.addJob('getCode', { work: function( api, bid, key, cb ) { winston.info('Run job oauth2:getCode'); var oaData = GLOBAL.config.authentication[api.auth.provider];
} file = path.join(DOWNLOAD_DIR, get_download_path(font_id)); path.exists(file, function (result) { if (!result) { callback(/* undefined - job not found */); return; } callback({status: 'finished', url: get_download_url(font_id)}); }); } // define queue and jobs var job_mgr = new (neuron.JobManager)(); job_mgr.addJob('generate-font', { dirname: '/tmp', concurrency: (CONFIG.builder_concurrency || os.cpus().length), work: function (font_id, config) { var self = this, log_prefix = '[font::' + font_id + '] ', tmp_dir, zipball, times; try { tmp_dir = path.join(TMP_DIR, "fontello-" + font_id); zipball = path.join(DOWNLOAD_DIR, get_download_path(font_id)); times = [jobs[font_id].start]; nodeca.logger.info(log_prefix + 'Start generation: ' + JSON.stringify(config));
exports.fulfill = function ( myRes, ip, bid, callback, gzip, override ) { winston.info('exports.fulfill: ' + bid); var bundle = GLOBAL.bundles[bid], now = new Date(); // If the user requested a bundle that is not defined if (typeof bundle === 'undefined') { myRes.writeHead(404); myRes.end(); return false; } // If a callback was not passed, and we have a default callback name in the bundle if (!callback && bundle.callback) { callback = bundle.callback; } // Count the number of queries in this bundle so we know when we are ready to respond var queriesInThisBundle = _.size(bundle), thisResponse = {}; // cleanup is not an API request if(_.has(bundle, 'cleanup')) { queriesInThisBundle--; } // callback is not an API request if(_.has(bundle, 'callback')) { queriesInThisBundle--; } // expiration is not an API request if(_.has(bundle, 'expiration')) { queriesInThisBundle--; } // locked is not an API request if(_.has(bundle, 'locked')) { queriesInThisBundle--; } // If override was not passed if( _.isUndefined( override )) { // Retrieve bundle response from Redis client.get('bid'+bid, function ( err, doc ) { if ( err || doc === null ) { // There was an error so force refresh on bundle exports.fulfill( myRes, ip, bid, callback, gzip, true ); } else { winston.debug('bid'+bid+':' + doc); jDoc = JSON.parse( doc ); GLOBAL.bundles[bid].expiration = new Date(jDoc.expires); jDoc.fromcache = true; sendResponse(jDoc, myRes, ip, bid, callback, gzip); } }); } else { // ### Override was passed so we are forcing a refresh on the bundle var manager = new neuron.JobManager(); manager.addJob('fulfillPart', { work: function(api, bid, key, override, cachedPart) { winston.info('manager:fulfillPart: ' + bid + '.' + key + ', override: '+override); var self = this; if ( _.isUndefined( override ) ) { // Load the cached api response from Redis client.get(bid+key, function (err, doc) { if (err || doc === null){ self.finished = true; manager.enqueue('fulfillPart', api, bid, key, true ); } else { doc = JSON.parse( doc ); doc.expires = new Date(doc.expires); if ( ('expires' in doc) && _.isDate(doc.expires) ) { var secleft = doc.expires.getSecondsBetween( now ) * -1; } if (secleft < 0) { self.finished = true; manager.enqueue('fulfillPart', api, bid, key, true, doc ); } else { doc.fromcache = true; manager.enqueue('finishRequest', doc ); self.finished = true; } } }); } else { if (_.has( api, 'auth')) { winston.info('Bundle uses auth type ' + api.auth.type); // If the API request object has an auth scheme defined if (api.auth.type == 'oauth') { oauth.authorize (api, bid, key, function( result, authParams ) { if (result === true) { api.params = _.extend(api.params, authParams); manager.enqueue('startRequest', api, key, cachedPart, bid); } else { manager.enqueue('finishRequest', result ); } self.finished = true; }); } else if (api.auth.type == 'oauth2') { oauth2.authorize (api, bid, key, function( result, authParams ) { if (result === true) { api.params = _.extend(api.params, authParams); manager.enqueue('startRequest', api, key, cachedPart, bid); } else { manager.enqueue('finishRequest', result ); } self.finished = true; }); } else { winston.error('auth type ' + api.auth.type + ' not recognized'); //Could potentially perma lock here if all APIs have bad types } } else { // Authentication is not needed self.finished = true; manager.enqueue('startRequest', api, key, cachedPart, bid); } } } }); manager.addJob('startRequest', { work: function( api, key, cachedPart, bid ) { winston.info('manager:startRequest: ' + key); var self = this; if (_.has( api, 'timeout') && _.isObject(cachedPart)) { self.timeout = setTimeout(function(self) { if(_.isObject(cachedPart)) { cachedPart.timeout = true; cachedPart.fromcache = true; } else { cachedPart= { "cname": key, "timeout" : true, "fromcache" : false }; } manager.enqueue('finishRequest', cachedPart ); self.finished = true; }, api.timeout, self) } api.resource( api.params, api.credentials, function( err, res ) { clearTimeout(self.timeout) delete self.timeout; if ( err ) { api.expires = ( now ); tout = _.isUndefined(cachedPart) ? {} : cachedPart; tout.cname = key; tout.expires = api.expires; tout.fromcache = true; tout.err = err; winston.error('Problem retrieving data for ' + bid + ' from ' + key + ': ' + JSON.stringify(err)); } else { winston.event('Get data for ' + bid + ' from ' + key + ', ' + res.size); // Perform cleanup function on API response if (_.has(api, 'cleanup')) { res = api.cleanup(res); } // Filter the response if (_.has(api, 'filter')) { filter ( res, api.filter ); } // Build the stored response api.expires = ( new Date() ).addSeconds( api.cacheduration ); bundle[key] = api; //client.set('bundle'+bid, JSON.stringify(bundle)); var tout = { expires: api.expires, result: res, iid: api.iid, cname: key }; // Save the API response to Redis client.set(bid+key, JSON.stringify(tout)); } manager.enqueue('finishRequest', tout ); self.finished = true; }); } }) manager.addJob('finishRequest', { work: function(apiResponse) { winston.info('manager:finishRequest'); queriesInThisBundle--; if (_.has(apiResponse, 'redirect')) { thisResponse["redirect"] = apiResponse.redirect; thisResponse["guid"] = apiResponse.guid || ''; thisResponse["authBundle"] = bid; thisResponse["authPart"] = apiResponse.cname; } thisResponse[apiResponse.cname] = apiResponse; if (queriesInThisBundle === 0) { manager.enqueue('composeResponse', bid); } this.finished = true; } }); manager.addJob('composeResponse', { work: function() { winston.info('manager:composeResponse'); // Update the expiration date on the bundle var tout = { expires: _.min( thisResponse, function( val ) { return val.expires } ).expires, lastModified: now }; if (_.has( thisResponse, 'redirect')) { tout.redirect = thisResponse.redirect, tout.guid = thisResponse.guid, tout.authBundle = thisResponse.authBundle, tout.authPart = thisResponse.authPart }; // Insert api responses into bundle _.each( thisResponse, function( val, idx ) { tout[val.cname] = val; }); // Perform cleanup function on bundle if (_.has(bundle, 'cleanup')) { tout = bundle.cleanup(tout); } // Determine the seconds left before expiry if ( 'expires' in tout && _.isDate(tout.expires) ) { tout.secleft = tout.expires.getSecondsBetween( now ) * -1; } else { tout.secleft = 3600; } // Save cached bundle in Redis client.set('bid'+bid, JSON.stringify(tout)); manager.enqueue('sendResponse', tout); this.finished = true; } }); manager.addJob('sendResponse', { work: function(doc) { winston.info('manager:sendResponse'); if (_.has(doc, 'redirect')) { if (_.has(doc, 'guid')) { GLOBAL.config.guids[doc.guid] = doc.authBundle+','+doc.authPart; myRes.setHeader("Set-Cookie", "authCode="+doc.guid); myRes.statusCode = 200; myRes.end('<p>Please authorize spas at <a href="'+doc.redirect+'">'+doc.redirect+'</a></p>'); this.finished = true; } else { myRes.statusCode = 302; myRes.setHeader("Location", doc.redirect); myRes.end(); this.finished = true; } } else { // Send the results sendResponse(doc, myRes, ip, bid, callback, gzip); } // Open the lock at the end of the chain GLOBAL.bundles[bid].locked = false; } }); manager.addJob('fulfillBundle', { work:function() { var parts = []; _.each( bundle, function( api, key ) { if (['cleanup', 'callback', 'expiration', 'locked'].indexOf(key) === -1) { if (_.isUndefined(api, 'credentials')) { api.credentials = {}; } manager.enqueue('fulfillPart', api, bid, key); } }); this.finished = true; } }); manager.enqueue('fulfillBundle'); } }
require('date-utils'); /* Connect to redis */ var client = redis.createClient(GLOBAL.config.redis.port, GLOBAL.config.redis.address); if (GLOBAL.config.redis.auth) { client.auth(GLOBAL.config.redis.auth, function (err) { if (err) { // handle err; } }); } var manager = new neuron.JobManager(); manager.addJob('finishAuth', { work: function( tout, cb, authParams ) { cb(tout, authParams); this.finished = true; } }); manager.addJob('getTemporaryCredentials', { work: function( api, bid, key, cb ) { winston.info ('getTemporaryCredentials called for ' + bid + ', ' + key); var oaData = GLOBAL.config.authentication[api.auth.provider]; var oa = new oauth(oaData.requestTemporaryCredentials,