Node.js рдореЗрдВ рдПрдХ рд▓рд╛рдЦ рд▓рд╛рдЗрдХреНрд╕ рдпрд╛ рдЯрд╛рд╕реНрдХ рдХрддрд╛рд░реЛрдВ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░реЗрдВ

рдкрд┐рдЫрд▓реЗ рд╣рдлреНрддреЗ рд╣рдордиреЗ рдПрдХ рджреМрд░ рдХреА рддрд╛рд░реАрдЦ рдордирд╛рдИ - рдПрдХ рдХрд░реЛрдбрд╝ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд▓рд╛рдЗрдХрд╕реНрдЯреЛрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдЬрдорд╛ рд╣реБрдП рдкрд╕рдВрдж рдХрд░рддреЗ рд╣реИрдВ, рди рддреЛ рдЕрдзрд┐рдХ рдФрд░ рди рд╣реА рдХрдоред

рд╣рдо рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рд╕рднреА рд╡рд░реНрддрдорд╛рди рд╕реЗрд╡рд╛рдПрдВ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ / рдиреЛрдб рдореЗрдВ рд▓рд┐рдЦреЗ рдЧрдП рд╣реИрдВред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдореБрдЭреЗ рд╣рдорд╛рд░реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ Node.js рдХреЗ рдЙрдкрдпреЛрдЧ рдХрд╛ рдХреЛрдИ рдЕрдлрд╕реЛрд╕ рдирд╣реАрдВ рд╣реИ, рдпрд╣ рдЦреБрдж рдХреЛ HTTP API рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдЙрдкрдХрд░рдг рд╕рд╛рдмрд┐рдд рд╣реБрдЖ рд╣реИред рд▓реЗрдХрд┐рди "рдкрд╕рдВрдж" рдЗрдХрдЯреНрдард╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдПрдХ daemon рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рд▓рдЧрд╛рддрд╛рд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред Node.js рдХреЗ рд▓рд┐рдП рд╕рдВрднрд╡рддрдГ рд╕рдмрд╕реЗ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдп рдирд╣реАрдВ рд╣реИ - рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рдмрд╛рд░реАрдХрд┐рдпреЛрдВ рдФрд░ рдХреБрдЫ рдиреБрдХрд╕рд╛рдиреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ, рд╣рдо рдЖрдЧреЗ рдкрдврд╝рддреЗ рд╣реИрдВред

Sollector


рдХрд▓реЗрдХреНрдЯрд░, рд▓рд┐рдХрд╕реНрдЯреЛрд░ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХрд╛ рдПрдХ рдкреНрд░рдореБрдЦ рдШрдЯрдХред рдпрд╣ рдЦреБрд▓реА рд╕реЗрд╡рд╛ рдПрдкреАрдЖрдИ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдбреЗрдЯрд╛ рдПрдХрддреНрд░ рдХрд░рддрд╛ рд╣реИ, рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдбреЗрдЯрд╛ рдФрд░ рдЗрд╕рдХреА рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрдЪрд╛рддрд╛ рд╣реИред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рдПрдХ "рдЕрдВрддрд╣реАрди рдЪрдХреНрд░" рд╣реИ рдЬреЛ рдкреНрд░рджрд░реНрд╢рди рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдХрд╛рд░реНрдпреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдмрдирд╛рддрд╛ рд╣реИ, рдЙрдиреНрд╣реЗрдВ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдмрд╛рдж рдкреНрд░рдХреНрд░рд┐рдпрд╛ рджреЛрд╣рд░рд╛рдИ рдЬрд╛рддреА рд╣реИред

рдЕрдзрд┐рдХрддрдо рджрдХреНрд╖рддрд╛ рдХреЗ рд▓рд┐рдП, рд╣рдо рдХрд▓реЗрдХреНрдЯрд░ рдХреЗ 2 рдЙрджрд╛рд╣рд░рдг рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рд╡рд┐рднрд┐рдиреНрди рдореЛрдб рдореЗрдВ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ: рдкреНрд░рд╛рд░рдВрднрд┐рдХ, рд╕рд╛рдорд╛рдиреНрдпред рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдореЛрдб рдореЗрдВ, рдХрд▓реЗрдХреНрдЯрд░ рдХреЗрд╡рд▓ рдирдП рдЬреБрдбрд╝реЗ рдиреЗрдЯрд╡рд░реНрдХ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдиреЗрдЯрд╡рд░реНрдХ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рдмрд╛рдж рдЬрд┐рддрдиреА рдЬрд▓реНрджреА рд╣реЛ рд╕рдХреЗ "рдкрд╕рдВрдж" рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИред рд╕рднреА "рдкрд╕рдВрдж" рдЕрдкрд▓реЛрдб рдХрд┐рдП рдЬрд╛рдиреЗ рдХреЗ рдмрд╛рдж, рдиреЗрдЯрд╡рд░реНрдХ рд╕рд╛рдорд╛рдиреНрдп рдореЛрдб рдореЗрдВ рдЬрд╛рддрд╛ рд╣реИ, рдПрдХ рдЕрдиреНрдп рдЙрджрд╛рд╣рд░рдг рджреНрд╡рд╛рд░рд╛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рд╢реБрд▓реНрдХ рдХреЗ рдмреАрдЪ рдХрд╛ рд╕рдордп рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╣реЛрддрд╛ рд╣реИред

 var argv = require('optimist').argv; var env = process.env.NODE_ENV = process.env.NODE_ENV || 'development'; var mode = process.env.COLLECTOR_MODE = process.env.COLLECTOR_MODE || argv.mode || 'normal'; var scheduler = require('./source/engine/scheduler'); scheduler(mode).run(); 

рд╕рдордпрдмрджреНрдзрдХ


рд╢реЗрдбреНрдпреВрд▓рд░ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ Node.js. рдХреЗ рд▓рд┐рдП рд▓рд┐рдЦреЗ рдЧрдП while(true) рдХреЗ рд╕рдорд╛рди рд╣реА рд╣реИ рд╕рдЪ рдХрд╣реВрдБ рддреЛ, "рд╕рд┐рдВрдХреНрд░реЛрдирд╕" рд╕реЗ "рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕" рдореЛрдб рдореЗрдВ рд╕реЛрдЪ рдХреЛ рдмрджрд▓рдирд╛ рдореЗрд░реЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдирд╣реАрдВ рдереАред Node.js рдореЗрдВ рдЕрдирдВрдд рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╢реБрд░реВ рдХрд░рдирд╛ рдПрдХ рдХрдард┐рди рдХрд╛рдо рдХреА рддрд░рд╣ рд▓рдЧ рд░рд╣рд╛ рдерд╛, рд╡рд┐рдЪрд╛рд░ рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдпрд╣ рдкреНрд░рд╢реНрди SO рдкрд░ рдкреИрджрд╛ рд╣реБрдЖ рдерд╛ред

рдПрдХ рд╡рд┐рдХрд▓реНрдк async.queue рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдерд╛ , рдЬреЛ рд╕реНрдкрд╖реНрдЯ рд▓рдЧ рд░рд╣рд╛ рдерд╛ рд▓реЗрдХрд┐рди рдЗрд╕ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдирд╣реАрдВ рдерд╛ред рдХрдИ рдкреНрд░рдпрд╛рд╕реЛрдВ рдХреЗ рдмрд╛рдж, рд╕реЗрдЯрдЯрд╛рдЗрдордЖрдЙрдЯ рдЕрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдХрд▓реНрдк рдмрди рдЧрдпрд╛, рдЬрдмрдХрд┐ (рд╕рдЪ)ред

 function scheduler (mode) { function schedulerLoop() { runCollectingTasks(restartScheduler); } function restartScheduler (err, results) { if (err) { logger.error(err); } // http://stackoverflow.com/questions/16072699/nodejs-settimeout-memory-leak var timeout = setTimeout(schedulerLoop, config.collector.schedulerRestart); } // ... return { run: function () { schedulerLoop(); } }; } 


рдпрд╣рд╛рдБ рдпрд╣ Node.js - рдореЗрдореЛрд░реА рд▓реАрдХ рдкрд░ рдбреЗрдорди рдХреЗ рдмрд╣реБрдд рдиреБрдХрд╕рд╛рди рдХреЛ рдиреЛрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдореИрдВрдиреЗ рджреЗрдЦрд╛ рдХрд┐ рдХрд▓реЗрдХреНрдЯрд░ рдХреЗ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЙрдиреНрд╣реЛрдВрдиреЗ рдЙрд╕ рд╕рдордп рдмрдбрд╝реА рдорд╛рддреНрд░рд╛ рдореЗрдВ рдореЗрдореЛрд░реА рдХрд╛ рдЙрдкрднреЛрдЧ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджрд┐рдпрд╛ рдФрд░ рд╕рдмрд╕реЗ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рдХреНрд╖рдг рдмрд╕ рд░реБрдХ рдЧрдпрд╛ред рдПрд╕рдУ рдкрд░ рд╕рд╡рд╛рд▓ рдХреЗ рд╕рд╛рде рдХреЛрдб рдореЗрдВ рдЯрд┐рдкреНрдкрдгреА рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ ред рдЬрдм рдореИрдВрдиреЗ var timeout = рдЬреЛрдбрд╝рд╛, рдЙрд╕рдХреЗ рдмрд╛рдж рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╕реБрдзрд╛рд░ рд╣реБрдЖ, рд▓реЗрдХрд┐рди рдореМрд▓рд┐рдХ рд░реВрдк рд╕реЗ рдирд╣реАрдВред

рдореЗрдореЛрд░реА рд▓реАрдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рдорд╣рд╛рдХрд╛рд╡реНрдп рдкреЛрд╕реНрдЯ рдФрд░ рдЬреЙрдпрдВрдЯ рдФрд░ рд╡реЙрд▓рдорд╛рд░реНрдЯ рдЗрдВрдЬреАрдирд┐рдпрд░реЛрдВ рджреНрд╡рд╛рд░рд╛ рдПрдХ рдЬрд╛рдВрдЪ рдХреЗ рдмрд╛рдж рдПрдХ рдФрд░ рдХрд╛рд░рдг рд╕рд╛рдордиреЗ рдЖрдпрд╛ред Node.js v0.10.22 рдХреЗ рд╕рдВрдХреНрд░рдордг рдХреЗ рд╕рд╛рде, рдХрд▓реЗрдХреНрдЯрд░ рдиреЗ рдФрд░ рднреА рдЕрдзрд┐рдХ рд╕реНрдерд┐рд░ рдХрд╛рдо рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджрд┐рдпрд╛ред рдлрд┐рд░ рднреА, рд╕реНрд╡рддрдГрд╕реНрдлреВрд░реНрдд рдард╣рд░рд╛рд╡ рд╣реЛрддрд╛ рд╣реИ, рдЗрд╕рдХрд╛ рдХрд╛рд░рдг рд╕рдордЭрдирд╛ рдЕрддреНрдпрдВрдд рдХрдард┐рди рд╣реИред

рдиреЗрдЯрд╡рд░реНрдХ рдФрд░ рд░рд╛рдЬреНрдп


рдЬрдм рдХреЛрдИ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдПрдХ рдирдпрд╛ рдиреЗрдЯрд╡рд░реНрдХ рдЬреЛрдбрд╝рддрд╛ рд╣реИ, рддреЛ рд╣рдо networks рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рдПрдХ рджрд╕реНрддрд╛рд╡реЗрдЬ рд░рдЦрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реЛрддрд╛ рд╣реИ: рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЖрдИрдбреА, рдПрдХреНрд╕реЗрд╕ рдЯреЛрдХрди рдФрд░ рдЕрдиреНрдп рд╕реЗрд╡рд╛ рдЬрд╛рдирдХрд╛рд░реАред рдЙрд╕реА рджрд╕реНрддрд╛рд╡реЗрдЬ рдореЗрдВ, рдХрд▓реЗрдХреНрдЯрд░ рдЕрдкрдиреА рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрддрд╛рддрд╛ рд╣реИ (рдпрд╣ рдХрд┐рд╕ рдореЛрдб рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдХреНрдпрд╛ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдереАрдВ, рдЙрдирдореЗрдВ рд╕реЗ рдХрд┐рддрдиреЗ рд╣реИрдВ, рдЬреЛ рд╡рд░реНрддрдорд╛рди рдбреЗрдЯрд╛ рдкреГрд╖реНрда рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ)ред рдпрд╛рдиреА рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рд╡рд╣реА рджрд╕реНрддрд╛рд╡реЗрдЬ рд╣реИ рдЬрд┐рд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдПрдХ рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рдХрд╛рд░реНрдп рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

 function runCollectingTasks(callback) { prepareCollectingTasks(function (err, tasks) { if (err) { return callback(err); } runTasks(tasks, 'collecting', callback); }); } function prepareCollectingTasks(callback) { networks.findByMode(mode, function (err, states) { if (err) { return callback({message: 'error during networks query', err: err}); } if (!states) { return callback({message: 'failed to read networks states'}); } callback(null, createCollectingTasks(states)); }); } 


рдХрд╛рд░реНрдп


рд░рд╛рдЬреНрдп рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рд╣рдо рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рдХрд╛рд░реНрдпреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдмрдирд╛рддреЗ рд╣реИрдВред рд▓реЛрдХрдкреНрд░рд┐рдп рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рд▓рдЧрднрдЧ рд╕рднреА рдЦреБрд▓реЗ рдПрдкреАрдЖрдИ рдореЗрдВ рд╕рдордп рдХреА рдЕрд╡рдзрд┐ рдХреЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдкрд░ рд╕реАрдорд╛рдПрдВ рд╣реИрдВред рдХрд▓реЗрдХреНрдЯрд░ рдХрд╛ рдХрд╛рд░реНрдп рд╕рдмрд╕реЗ рдкреНрд░рднрд╛рд╡реА рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░рдирд╛ рд╣реИ рдФрд░ рджрд░-рд╕реАрдорд╛ рддрдХ рдирд╣реАрдВ рдЬрд╛рдирд╛ рд╣реИред

рдХреЗрд╡рд▓ рдЙрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЬреЛ рд╡рд░реНрддрдорд╛рди рдмрд┐рдВрджреБ рдХреЗ рдмрд╛рдж рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдП рдЧрдП рдереЗ, рдЙрдиреНрд╣реЗрдВ рдЪрд▓рд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рд╣реИред

 function createCollectingTasks(states) { var tasks = states.map(function (state) { return allowedToExecute(state) ? collectingTask(state) : null; }).filter(function (task) { return task !== null; }); return tasks; } function allowedToExecute (state) { return moment().diff(state.scheduledTo) > 0; } function collectingTask(state) { return function (callback) { return executor(state, connectors, callback); }; } 


рдбреЗрдЯрд╛ рдХрд╛ рдПрдХ рд╕рд░рдгреА рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдПрдХ рд╕рд░рдгреА рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ runTasks рдЗрдирдкреБрдЯ рдкрд░ рдЬрд╛рддрд╛ рд╣реИред рдХреНрд░рдорд┐рдХ рд░реВрдк рд╕реЗ async.series рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИред

 function runTasks(tasks, type, callback) { async.series(tasks, function (err) { if (err) { // report error but continue execution to do not break execution chain.. logger.error(err); } callback(null, tasks.length); }); } 


рдирд┐рд░реНрд╡рд╛рд╣рдХ


рдПрдХ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдлрд╝рдВрдХреНрд╢рди рдЬреЛ рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рд▓реЗрддрд╛ рд╣реИ, рдореМрдЬреВрджрд╛ рдХрдиреЗрдХреНрдЯрд░реНрд╕ рдХреА рдПрдХ рд╕реВрдЪреА рдФрд░ рдПрдХ рдХреЙрд▓рдмреИрдХ рдлрд╝рдВрдХреНрд╢рди (рдореИрдВрдиреЗ рдЗрд╕рдХрд╛ рд╕рд╛рд░ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рднреА рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдФрд░ рд▓реЙрдЧрд┐рдВрдЧ рдХреЛ рд╣рдЯрд╛ рджрд┐рдпрд╛ рд╣реИ)ред

 function executor(state, connectors, callback) { var service = state.service; var connector = connectors[service]; var connectorStarted = moment(); connector(state, user, connectorExecuted); function connectorExecuted(err, updatedState, results) { saveConnectorState(state, connectorStateSaved); function saveConnectorState (state, callback) { // ... } function connectorStateSaved (err) { // ... saveConnectorResults(results, connectorResultsSaved); } function saveConnectorResults(results, callback) { // ... connectorResultsSaved(results, connectorResultsSaved); } function connectorResultsSaved (err, saveDuration) { // ... callback(null); } } } 


рдХрдиреЗрдХреНрдЯрд░реНрд╕


рдХрдиреЗрдХреНрдЯрд░ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬреЛ HTTP рдЕрдиреБрд░реЛрдз рдХреЛ рдПрдкреАрдЖрдИ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рдХреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдХрд╛рд░реНрдп рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИ (рдЕрдЧрд▓реЗ рд░рди рд╢реЗрдбреНрдпреВрд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛) рдФрд░ рдПрдХрддреНрд░ рдХрд┐рдП рдЧрдП рдбреЗрдЯрд╛ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдХрдиреЗрдХреНрдЯрд░ рд╣реИ рдЬреЛ "рдкрд╕рдВрдж" рдХрд╛ рд╕рдВрдЧреНрд░рд╣ рдХрд┐рд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╕реНрдерд┐рдд рд╣реИ, рдЗрд╕ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рдЕрдиреБрд░реЛрдз рдХрд░рддрд╛ рд╣реИ (рд╡рд╛рдВрдЫрд┐рдд рдЕрдиреБрд░реЛрдз рдпреВрдЖрд░рдЖрдИ рдмрдирд╛рддрд╛ рд╣реИ)ред

рдлрд┐рд▓рд╣рд╛рд▓, рд╣рдордиреЗ 9 рдХрдиреЗрдХреНрдЯрд░ рд▓рд╛рдЧреВ рдХрд┐рдП рд╣реИрдВ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдХреЛрдб рдХрдореЛрдмреЗрд╢ рд╕рдорд╛рди рд╣реИред рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ, рдореИрдВрдиреЗ рд╣рдореЗрд╢рд╛ рддреИрдпрд╛рд░ рдПрдкреАрдЖрдИ рдПрдХреНрд╕реЗрд╕ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреА рддрд▓рд╛рд╢ рдХреА, рд▓реЗрдХрд┐рди рдпрд╣ рдЧрд▓рдд рд░рдгрдиреАрддрд┐ рдмрди рдЧрдИ: рдЖрдкрдХреЛ рдХрдИ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдореЗрдВ рд╕реЗ рдЪреБрдирдирд╛ рд╣реЛрдЧрд╛, рд╡реЗ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рдпрд╛ рдЙрдирдХреЗ рдкрд╛рд╕ рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдирд╣реАрдВ рд╣реИ, рд╡реЗ рдПрдкреАрдЖрдИ рдХреЗ рд╡рд░реНрддрдорд╛рди рд╕рдВрд╕реНрдХрд░рдг рд╕реЗ рдкреАрдЫреЗ рд╣реИрдВ, рдЖрджрд┐ред рд╕рдмрд╕реЗ рд▓рдЪреАрд▓рд╛ рдФрд░ рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рд╕рдорд╛рдзрд╛рди рдЕрдиреБрд░реЛрдз рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдерд╛ (Node.js рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ HTTP рдХреНрд▓рд╛рдЗрдВрдЯ)ред

рдореИрдВ GitHub рдХреЗ рд▓рд┐рдП рдХреЛрдб рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджреВрдВрдЧрд╛ (рдлрд┐рд░, рдореИрдВ рд╕рд╛рд░ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╡рд░рдг рдХреЛ рдЫреЛрдЯрд╛ рдХрд░реВрдВрдЧрд╛)ред

 var API = 'https://api.github.com'; function connector(state, user, callback) { var accessToken = state.accessToken; if (!accessToken) { return callback('missing accessToken for user: ' + state.user); } initState(state); var uri = formatRequestUri(accessToken, state); var headers = { 'Content-Type': 'application/json', 'User-Agent': 'likeastore/collector'}; request({uri: uri, headers: headers, timeout: config.collector.request.timeout, json: true}, function (err, response, body) { if (err) { return handleUnexpected(response, body, state, err, function (err) { callback (err, state); }); } return handleResponse(response, body); }); function initState(state) { // intialize state fields (page, errors, mode etc.) ... } function formatRequestUri(accessToken, state) { // create request URI based on values from state ... } function handleResponse(response, body) { var rateLimit = +response.headers['x-ratelimit-remaining']; var stars = body.map(function (r) { return { // transforms response into likeastore item }; }); return callback(null, scheduleTo(updateState(state, stars, rateLimit, false)), stars); } function updateState(state, data, rateLimit, failed) { state.lastExecution = moment().toDate(); // update other state fields (next page, mode) ... return state; } } 


scheduleTo


рдЕрдВрдд рдореЗрдВ, рдЬрдм рдХрдиреЗрдХреНрдЯрд░ рдкреВрд░рд╛ рд╣реЛ рдЧрдпрд╛ рд╣реИ рдФрд░ рд╕реНрдерд┐рддрд┐ рдЕрдкрдбреЗрдЯ рд╣реЛ рдЧрдИ рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдЕрдЧрд▓реЗ рдкреНрд░рд╛рд░рдВрдн рд╕рдордп рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣ рдПрдкреАрдЖрдИ рд╕реАрдорд╛рдУрдВ рдФрд░ рдХрд▓реЗрдХреНрдЯрд░ рдСрдкрд░реЗрд╢рди рдореЛрдб рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдЧрдгрдирд╛ рдХреА рдЬрд╛рддреА рд╣реИ (рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдореЛрдб рдХреЗ рд▓рд┐рдП, рдард╣рд░рд╛рд╡ рдиреНрдпреВрдирддрдо рд╣реИ, рд╕рд╛рдорд╛рдиреНрдп рдореЛрдб рдХреЗ рд▓рд┐рдП рдпрд╣ рд╕рд╛рдорд╛рдиреНрдп рд╣реИ, рдЖрдорддреМрд░ рдкрд░ 15 рдорд┐рдирдЯ, рдпрджрд┐ рдХрдиреЗрдХреНрдЯрд░ рджрд░ рд╕реАрдорд╛ рдкрд░ рдЬрд╛рддрд╛ рд╣реИ рддреЛ рдард╣рд░рд╛рд╡ рдЕрдзрд┐рдХрддрдо рд╣реИ)ред

 function scheduleTo(state) { var currentMoment = moment(); var service = state.service; var scheduleForMode = { initial: config.collector.quotes[service].runAfter, normal: config.collector.nextNormalRunAfter, rateLimit: config.collector.nextRateLimitRunAfter }; var next = scheduleForMode[state.mode]; var scheduledTo = currentMoment.add(next, 'milliseconds'); state.scheduledTo = scheduledTo.toDate(); return state; } 


рдпрд╣рд╛рдВ рдРрд╕рд╛ рд╕реАрдзрд╛ рдХреЛрдб рд╣реИ рдЬреЛ рдкрд┐рдЫрд▓реЗ рд╕рд╛рд▓ рд╕рд┐рддрдВрдмрд░ рдХреЗ рдЖрд╕рдкрд╛рд╕ "рдмрд╕ рдЧрдпрд╛" рдФрд░ рд╣рдо рддрдм рд╕реЗ рд╕рднреА рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рдирдП рдХрдиреЗрдХреНрдЯрд░ рд╣реИрдВ, рдЗрдВрдЬрди рд╕реНрд╡рдпрдВ рдЕрдкрд░рд┐рд╡рд░реНрддрд┐рдд рд░рд╣рддрд╛ рд╣реИред рдореИрдВ Node.js рдореЗрдВ рдХрд╛рд░реНрдп рдХрддрд╛рд░ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдЖрд╡рдВрдЯрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪ рд░рд╣рд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдХрд╛рд░реНрдп рдХрд┐рддрдирд╛ рд╣реИред

рд╕рдордп рд╕рдорд╛рдкреНрдд рд╣реЛ рд░рд╣рд╛ рд╣реИ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдмрдврд╝ рд░рд╣реА рд╣реИ, рдФрд░ рдЗрд╕ рд╕рдордп, 3 рд╣рдЬрд╛рд░ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдореЗрдВ рд▓рдЧрднрдЧ 30 рдорд┐рдирдЯ рд▓рдЧрддреЗ рд╣реИрдВ, рдЬреЛ рдХрд╛рдлреА рд▓рдВрдмрд╛ рд╕рдордп рд╣реИ (рд╣рдо рдЪрдХреНрд░ рдХреЗ рд╕рдордп рдХреЛ 15 рдорд┐рдирдЯ рд╕реЗ рдЕрдзрд┐рдХ рдирд╣реАрдВ рд░рдЦрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ)ред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рднрд╡рд┐рд╖реНрдп рдореЗрдВ, рдХрд▓реЗрдХреНрдЯрд░ рдХреА рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рд╕рдВрджреЗрд╢ рдХрддрд╛рд░реЛрдВ рдХреА рджрд┐рд╢рд╛ рдореЗрдВ рдмрджрд▓ рдЬрд╛рдПрдЧреА рдФрд░ рдХрд▓реЗрдХреНрдЯрд░реЛрдВ рдХреЗ рдЕрд▓рдЧрд╛рд╡ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рдореЛрдб рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рдЖрд╕рд╛рди рдХреНрд╖реИрддрд┐рдЬ рд╕реНрдХреЗрд▓реЗрдмрд┐рд▓рд┐рдЯреА рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рдорд╛рдирджрдВрдб (рдиреЗрдЯрд╡рд░реНрдХ рдкреНрд░рдХрд╛рд░, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреНрд▓рд╕реНрдЯрд░) рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╣реЛрдЧрд╛ред

Source: https://habr.com/ru/post/In214781/


All Articles