EventMachine рдкреНрд░реЙрдХреНрд╕реА рдбреЗрдореЙрди

рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд┐ EventMachine рдЙрдЪреНрдЪ рдкреНрд░рджрд░реНрд╢рди рдФрд░ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд╕реНрдХреЗрд▓реЗрдмрд▓ рдиреЗрдЯрд╡рд░реНрдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрд╛рдлреА рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдврд╛рдВрдЪрд╛ рд╣реИ, рдЗрдВрдЯрд░рдиреЗрдЯ рдЗрд╕рдХреЗ рдЙрдкрдпреЛрдЧ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреА рдПрдХ рдмрд╣реБрддрд╛рдпрдд рдХреЗ рд╕рд╛рде рдХреГрдкрдпрд╛ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдФрд░ рд╡реЗ рдЙрджрд╛рд╣рд░рдг рдЬреЛ рдореМрдЬреВрдж рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рд╣рдм рдкрд░, рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рдбреЗрдЯрд╛ рдЯреНрд░рд╛рдВрд╕рдлрд░ рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рдирд╣реАрдВ рд░рдЦрддреЗ рд╣реИрдВ (рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рд╡реЗ рдЙрд╕ рдбреЗрдЯрд╛ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рдирд╣реАрдВ рд░рдЦрддреЗ рд╣реИрдВ, рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ, рднрд╛рдЧреЛрдВ рдореЗрдВ рдкреНрд░реЗрд╖рд┐рдд рд╣реЛрддрд╛ рд╣реИ)ред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рд▓реЗрдЦ рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рд╣реИ, рдЬрд┐рдиреНрд╣реЛрдВрдиреЗ EM рдХреЗ рдореВрд▓ рд╕рд┐рджреНрдзрд╛рдВрддреЛрдВ рд╕реЗ рдЦреБрдж рдХреЛ рдкрд░рд┐рдЪрд┐рдд рдХрд┐рдпрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд░реВрдмреА рдФрд░ EventMachine рд▓реЗрдЦ рдореЗрдВ , рдФрд░ рд╕реАрдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рдЗрд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХреБрдЫ рдФрд░ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдХреИрд╕реЗ рд▓рд┐рдЦрд╛ рдЬрд╛рдП рдФрд░ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдкреНрд░рд╛рдкреНрдд рдХреЛрдб рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХреИрд╕реЗ рдХрд░реЗрдВред

рд╣рд╛рд▓ рд╣реА рдореЗрдВ, рдЙрдиреНрд╣реЛрдВрдиреЗ рдореБрдЭреЗ рдПрдХ рдкрд░реАрдХреНрд╖рдг рдХрд╛рд░реНрдп рднреЗрдЬрд╛, рдЬрд┐рд╕рдХрд╛ рд╕рд╛рд░ рдИрдПрдо рдкрд░ рдПрдХ рдкреНрд░реЙрдХреНрд╕реА рдбреЗрдореЙрди рд▓рд┐рдЦрдирд╛ рдерд╛, рдЬреЛ рдХрд┐ рдпреВрдирд┐рдХреНрд╕ рдбреЛрдореЗрди рд╕реЙрдХреЗрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЧреНрд░рд╛рд╣рдХреЛрдВ рд╕реЗ рдХрдиреЗрдХреНрд╢рди рдХреЛ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░реЗрдЧрд╛, рдЙрдиреНрд╣реЗрдВ рдХрддрд╛рд░рдмрджреНрдз рдХрд░реЗрдЧрд╛ рдФрд░ рдЗрди рдЖрджреЗрд╢реЛрдВ рдХреЛ рдХреБрдЫ рд╕рд╛рд░ рдкреНрд░рдгрд╛рд▓реА рд╕реЗ рдЬреБрдбрд╝реЗ рд╕реЙрдХреЗрдЯ рдореЗрдВ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд░реЗрдЧрд╛, рдФрд░, рдкреНрд░рд╛рдкреНрдд рдХрд░ рд░рд╣рд╛ рд╣реИ рдЗрд╕ рдкреНрд░рдгрд╛рд▓реА рд╕реЗ рдПрдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдЙрдиреНрд╣реЗрдВ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЛ рд╡рд╛рдкрд╕ рднреЗрдЬ рджреЗрдЧреАред рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рдВрджреЗрд╢ рдХрд╛ рдкреНрд░рд╛рд░реВрдк {рдЖрдИрдбреА: 1, рдкрд╛рда: "req1"} рд╣реИ, рдЬрд┐рд╕реЗ рд╕рд░реНрд╡рд░ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП - {рдЖрдИрдбреА: 1, рдкрд╛рда: "рдЙрддреНрддрд░ 1"}ред

рдХрд╛рд░реНрдп рдХреЛ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рдЕрдореВрд░реНрдд рдкреНрд░рдгрд╛рд▓реА рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ EM рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рднреА рдЕрдиреБрдХрд░рдг рдХрд┐рдпрд╛ рд╣реИ, рдЬреЛ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдбреЗрдЯрд╛ рдЯреНрд░рд╛рдВрд╕рдлрд░ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ EM :: P :: ObjectProtocol рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬреЛ рдЗрд╕ рдмрд╛рдд рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддрд╛ рд╣реИ рдХрд┐ рдбреЗрдЯрд╛ рдХреЛ рд░рд┐рдПрдХреНрдЯрд░ рдХреЗ рдПрдХ рднреА рдЯрд┐рдХ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рд▓рд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдЯреНрд░рд╛рдВрд╕рдорд┐рд╢рди рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рдХреЛ рдХреНрд░рдордмрджреНрдз рднреА рдХрд░рддрд╛ рд╣реИред

рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛрдб рд▓рд┐рдЦрдХрд░ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред рдЬрдм рдХреЛрдИ рдХреНрд▓рд╛рдЗрдВрдЯ рдкреНрд░реЙрдХреНрд╕реА рдбреЗрдореЙрди рдХреЗ рд╕рд╛рде рд╕рдВрдмрдВрдз рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИ, рддреЛ рдкреЛрд╕реНрдЯ_рдЗрдирд┐рдЯ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ , рдЬрд┐рд╕рдореЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ send_object рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рд╣реИрд╢ рд╕рдВрджреЗрд╢ рднреЗрдЬрддрд╛ рд╣реИред
рдлрд┐рд░ рдпрд╣ рдбреЗрдореЙрди рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕реЗ рдХрдВрд╕реЛрд▓ рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ рдПрдХ рдмрд╛рд░ рдореЗрдВ рдХрдИ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЗ рдХрдиреЗрдХреНрд╢рди рдХрд╛ рдЕрдиреБрдХрд░рдг рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рдерд╛, рдЗрд╕рд▓рд┐рдП рдЪрд░ рдХреЛ рдЙрди рдХрдиреЗрдХреНрд╢рдиреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдФрд░ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдкрд░ рдбреЗрдЯрд╛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рдбреЗрдореЙрди рд╕реЗ рдХрд╛рдЯ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдХрдиреЗрдХреНрд╢рди рдХреА рдХреБрд▓ рд╕рдВрдЦреНрдпрд╛ рдирд┐рд░рдВрддрд░ TOTAL_CONNECTIONS рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХреА рдЬрд╛рддреА рд╣реИ, рдЬреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рд╢реБрд░реВ рд╣реЛрдиреЗ рдкрд░ рд╕реЗрдЯ рдХреА рдЬрд╛рддреА рд╣реИред рдЬрдм рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд░реНрд╡рд░ рд╕реЗ рдбрд┐рд╕реНрдХрдиреЗрдХреНрдЯ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдПрдХ рдЕрдирдмрд╛рдЗрдВрдб рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ред рдЬрдм рд╕рднреА рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЛ рдПрдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдорд┐рд▓рддреА рд╣реИ, рддреЛ рд░рд┐рдПрдХреНрдЯрд░ рдмрдВрдж рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред

module EMClient<br/> include EM::P::ObjectProtocol<br/> <br/> @@connection_number = 0 <br/> @@dissconnected = 0 <br/> <br/> #send request as the connection has been established <br/> def post_init <br/> @@connection_number += 1 <br/> send_object({ 'id' => rand ( 10 ), 'text' => "req#{@@connection_number}" })<br/> end <br/> <br/> <br/> def receive_object (obj)<br/> #display response from server <br/> p obj.inspect<br/> end <br/> <br/> def unbind <br/> @@dissconnected += 1 <br/> #stop reactor after all requests have been processed <br/> EM.stop if @@dissconnected == TOTAL_CONNECTIONS<br/> end <br/> end <br/>

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

module SocketServer<br/> include EM::P::ObjectProtocol<br/> <br/> def receive_object (obj)<br/> #emulation of job on server <br/> EM.add_timer( 1 + rand ( 5 )) do <br/> #validation of obj goes here)) <br/> obj[ 'text' ]. sub !(/req/, 'answ' )<br/> send_object(obj)<br/> end <br/> p "Server received object: #{obj.inspect}" <br/> end <br/> end <br/>

рдФрд░ рдЕрдм рдЪрд▓реЛ рдЕрдзрд┐рдХ рджрд┐рд▓рдЪрд╕реНрдк рднрд╛рдЧ рдкрд░ рдЪрд▓рддреЗ рд╣реИрдВ, рд╕рдВрджреЗрд╢реЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрджреЗрд╢ рдХрддрд╛рд░ рдФрд░ рдПрдХ рд╕рд╛рд░ рд╕рд░реНрд╡рд░ рдХреЗ рд╕рд╛рде рдПрдХ рдХрдиреЗрдХреНрд╢рди рдкреВрд▓ рдмрдирд╛рддреЗ рд╣реИрдВред рдЗрд╕рдХреЗ рд▓рд┐рдП, EM :: рдХрддрд╛рд░ рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЬрд┐рд╕рдореЗрдВ рджреЛ рд╡рд┐рдзрд┐рдпрд╛рдБ рдкреЙрдк (* a, & b) рдФрд░ рдкреБрд╢ (* рдЖрдЗрдЯрдо) рд╣реИрдВ рдЬреЛ рдЖрдкрдХреЛ рдХрддрд╛рд░ рдореЗрдВ рдЖрдЗрдЯрдо рдЬреЛрдбрд╝рдиреЗ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдЗрд╕рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд╛рд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИрдВред рдкреЙрдк рд╡рд┐рдзрд┐ рдЕрдВрддрд┐рдо рддрд░реНрдХ рдХреЛ рдХреЛрдб рдХреЗ рдПрдХ рдмреНрд▓реЙрдХ рдХреЗ рд░реВрдк рдореЗрдВ рд▓реЗрддреА рд╣реИ рдЬрд┐рд╕реЗ рдПрдХ рддрддреНрд╡ рдХрддрд╛рд░ рдореЗрдВ рдкреНрд░рдХрдЯ рд╣реЛрдиреЗ рдкрд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рд╕рд░реНрд╡рд░ рдХреЗ рд╕рд╛рде рд╕рдВрдмрдВрдз рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, EMConnection рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЬрд┐рд╕рдореЗрдВ send_request (obj, & block) рдкрджреНрдзрддрд┐ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЬрд┐рд╕рдХрд╛ рд╕рд╛рд░ рд╕рд░реНрд╡рд░ рд╕рдВрджреЗрд╢ рднреЗрдЬрдирд╛ рдерд╛ рдФрд░ рдПрдХ рдмреНрд▓реЙрдХ рдХреЛ рд╕рдВрдЪрд╛рд░рд┐рдд рдХрд░рдирд╛ рдерд╛ рдЬрд┐рд╕реЗ рд╕рд░реНрд╡рд░ рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдорд┐рд▓рдиреЗ рдкрд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рдХрдиреЗрдХреНрд╢рди рдкреВрд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП ConnectionPool рд╡рд░реНрдЧ рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред рдЬрдм рдЗрд╕реЗ рдкреНрд░рд╛рд░рдВрдн рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдкреВрд▓ рдХрд╛ рдЖрдХрд╛рд░ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдХрддрд╛рд░ рдХреЛ рдкреНрд░рд╛рд░рдВрдн рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдлрд┐рд░, рдХрдиреЗрдХреНрд╢рди рдХреА рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕рдВрдЦреНрдпрд╛ start_queue рд╡рд┐рдзрд┐ рдореЗрдВ рд╕реЗрдЯ рдХреА рдЧрдИ рд╣реИ, рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдХрдиреЗрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ ( queue_worker_loop ) рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬреЛ рдХрд┐ рдПрдХ рдЦрд░реАрдж рд╣реИ рдЬреЛ рдХрдиреЗрдХреНрд╢рди рдХреЛ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рд▓реЗрддрд╛ рд╣реИред рдЙрдирдХреЗ рдХрд╛рдо рдХрд╛ рд╕рд╛рд░ рдХрддрд╛рд░ рд╕реЗ рдПрдХ рддрддреНрд╡ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рддрддреНрд╡ рд╣реИ рдЬреЛ рд╕рд░реНрд╡рд░ рдХреЛ рднреЗрдЬрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдХреЛрдб рдХрд╛ рдПрдХ рдмреНрд▓реЙрдХ рдЬрд┐рд╕реЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдХреЛрдб рдХреЗ рдЗрд╕ рдмреНрд▓реЙрдХ рдХреЛ рдХреНрд░рд┐рдпрд╛рдиреНрд╡рд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╕реНрд╡рдпрдВ рдХреЙрд▓ рдХрд░реЗрдВ, рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЕрдирдВрдд рд▓реВрдк рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

module EMConnection<br/> include EM::P::ObjectProtocol<br/> <br/> def receive_object (obj)<br/> #calling callback on object receiving <br/> @callback. call (obj)<br/> end <br/> <br/> def send_request obj, &block<br/> #sending data to server and setting callback <br/> send_object obj<br/> @callback = block<br/> end <br/> <br/> end <br/> <br/> #simple connection pool using EM queue, default size 10 <br/> class ConnectionPool <br/> <br/> def initialize (conf)<br/> @pool_size = conf[:size] || 10 <br/> @connections = []<br/> @query_queue = EM:: Queue .new<br/> start_queue conf<br/> end <br/> <br/> def queue_worker_loop <br/> proc { |connection|<br/> @query_queue.pop do | request |<br/> connection. send_request ( request [:obj]) do |response|<br/> request [:callback].call response #if request[:callback] <br/> queue_worker_loop .call connection<br/> end <br/> end <br/> }<br/> end <br/> <br/> def start_queue (conf)<br/> @pool_size.times do <br/> connection = EM.connect( '0.0.0.0' , 8080 , EMConnection)<br/> @connections << connection<br/> queue_worker_loop .call connection<br/> end <br/> end <br/> <br/> def request (obj, &block)<br/> @query_queue.push :obj => obj, :callback => block<br/> end <br/> end <br/>

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

module DaemonServer<br/> include EM::P::ObjectProtocol<br/> <br/> def post_init <br/> @@connections_pool ||= ConnectionPool. new (:size => 5 )<br/> end <br/> <br/> def receive_object (obj)<br/> @@connections_pool.request obj do |response|<br/> send_object(response)<br/> close_connection_after_writing<br/> end <br/> end <br/> end <br/>

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

EventMachine.run {<br/> EventMachine.start_server "127.0.0.1" , 8080 , SocketServer<br/>} <br/>


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

tc = ARGV[ 0 ].to_i<br/>TOTAL_CONNECTIONS = tc > 0 ? tc : 25 <br/> <br/>file = File .expand_path( '../tmp/daemon.sock' , __FILE__ )<br/> p "Starting #{TOTAL_CONNECTIONS} client(s)" <br/>EventMachine::run {<br/> TOTAL_CONNECTIONS.times{ EM.connect_unix_domain(file, EMClient) }<br/>} <br/>

рдПрдХ рджрд╛рдирд╡ рдмрдирдиреЗ рдХреЗ рд▓рд┐рдП рдЫрджреНрдо рдХреЗ рд▓рд┐рдП, рдирд┐рд╕реНрд╕рдВрджреЗрд╣, рдЗрд╕реЗ рдирд┐рд╕реНрддрд╛рд░рд┐рдд (рдХрдкреНрддрд╛рди) рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рд▓рд┐рдП рдореИрдВрдиреЗ рдбреЗрдореЛрдВрд╕ рд░рддреНрди рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ред рдпрджрд┐ рд╕реНрдХреНрд░рд┐рдкреНрдЯ -d рд╕реНрд╡рд┐рдЪ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддреА рд╣реИ, рддреЛ рдЗрд╕реЗ рдЕрддрд┐рд░рд┐рдХреНрдд рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЗ рд╕рд╛рде Daemons.daemonize рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ рдбреАрдореЙрдиреЗрдЯрд╛рдЗрдЬ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рд▓реЙрдЧреНрд╕ рдХреЛ рдХреИрд╕реЗ рд╕реНрдЯреЛрд░ рдХрд░реЗрдВ рдФрд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдкреАрдЖрдИрдбреА тАЛтАЛрдпреБрдХреНрдд рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╣рдЯрд╛ рджреЗрдВ , рддрд╛рдХрд┐ рдбреЗрдореЙрди рдХреЛ рд░реЛрдХрд╛ рдЬрд╛ рд╕рдХреЗред

options = {<br/> :app_name => 'ProxyServer' ,<br/> :backtrace => true ,<br/> :log_output => true ,<br/> :dir_mode => :normal,<br/> :dir => File .expand_path( '../tmp' , __FILE__ )<br/>}<br/> <br/>file = File .expand_path( '../tmp/daemon.sock' , __FILE__ )<br/> File .unlink(file) if File .exists?(file)<br/> <br/>Daemons.daemonize(options) if ARGV.index( '-d' )<br/> <br/>EventMachine::run {<br/> EventMachine::start_unix_domain_server(file, DaemonServer)<br/>} <br/>

рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рдмрд┐рдирд╛ рд▓рдЧрднрдЧ рдХрд┐рд╕реА рднреА рдХреЛрдб рдХреА рд▓рд╛рдЧрдд рдмрд╣реБрдд рдХрдо рд╣реЛрддреА рд╣реИ, рднрд▓реЗ рд╣реА рдпрд╣ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реЛ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реА рд╕рдорд╕реНрдпрд╛рдУрдВ рдФрд░ рд╕рд┐рд░рджрд░реНрдж рдкреИрджрд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рдЗрд╕реЗ рд▓рд┐рдЦрд╛ рдерд╛ рдФрд░ рдЬрд┐рдиреНрд╣реЗрдВ рдЗрд╕реЗ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

EM - EMSpec рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдмрдирд╛рдП рдЧрдП рдкрд░реАрдХреНрд╖рдг рдХрд╛рд░реНрдпрдХреНрд░рдореЛрдВ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╕рдорд╛рдзрд╛рди рд╣реИред рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛, рдФрд░ рдЗрд╕рд▓рд┐рдП рдореИрдВ рдпрд╣ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░реВрдВрдЧрд╛ рдХрд┐ рдмрд┐рдирд╛ rspec рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рдПред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рдЖрдкрдХреЛ рдЯреЗрд╕реНрдЯ рдХреНрд▓рд╛рдЗрдВрдЯ рдмрдирд╛рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИред рдЗрд╕рдореЗрдВ, рд╣рдо send_request (obj, & block) рд╡рд┐рдзрд┐ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдбреЗрдореЙрди рдХреЛ рдкреНрд░реЙрдХреНрд╕реА рдЕрдиреБрд░реЛрдз рднреЗрдЬрдиреЗ рдФрд░ рдХреЙрд▓рдмреИрдХ рдХреЛ рдХреЛрдб рдХреЗ рдПрдХ рдмреНрд▓реЙрдХ рдХреЗ рд░реВрдк рдореЗрдВ рд╕реЗрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдХреНрд▓рд╛рдЗрдВрдЯ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдорд┐рд▓рдиреЗ рдкрд░ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рд╣рдо onclose = (proc) рд╡рд┐рдзрд┐ рднреА рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬреЛ рдХрдиреЗрдХреНрд╢рди рдмрдВрдж рд╣реЛрдиреЗ рдкрд░ рдХреЙрд▓рдмреИрдХ рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░реЗрдЧрд╛ред

module TestClient<br/> include EM::P::ObjectProtocol<br/> <br/> #on object received callback <br/> def receive_object (obj)<br/> @onresponse. call (obj)<br/> p "Client received object: #{obj.inspect}" <br/> end <br/> <br/> def send_request obj, &block<br/> @onresponse = block<br/> send_object obj<br/> end <br/> <br/> # on disconnect callback <br/> def onclose =( proc )<br/> @onclosed = proc <br/> end <br/> <br/> def unbind <br/> @onclosed.call<br/> end <br/> <br/> end <br/>

рдЕрдм рд╣рдо рдЙрди рддрд░реАрдХреЛрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рд╣рдореЗрдВ рд▓рд┐рдЦрд┐рдд рдХреЛрдб рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВред рдкрд╣рд▓рд╛ рддрд░реАрдХрд╛ start_serv рд╕рд░реНрд╡рд░, рдЯреЗрд╕реНрдЯ рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рдкреНрд░реЙрдХреНрд╕реА рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИ, рдФрд░ рдпрд╣ рдПрдХ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдмреНрд▓реЙрдХ рд▓реЗрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдкрд╛рд╕ рдЗрд╕рдХреЗ рдирд┐рдкрдЯрд╛рди рдореЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ рдЪрд░ рд╣реЛрдЧрд╛, рдЬреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд╣реЗрд░рдлреЗрд░ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдпрджрд┐ рдХреБрдЫ рдЧрд▓рдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд╕рд░реНрд╡рд░ рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдирд╣реАрдВ рдорд┐рд▓рддреА рд╣реИ, рддреЛ рдЯрд╛рдЗрдорд░ рд╡рд┐рдзрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдлрд┐рд░ rspec рджрд┐рдЦрд╛рдПрдЧрд╛ рдХрд┐ рдкрд░реАрдХреНрд╖рдг рд╡рд┐рдлрд▓ рд╣реЛ рдЧрдпрд╛, рдФрд░ рди рдХреЗрд╡рд▓ рдЬрдорд╛ рд╣реБрдЖред рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдЖрдзрд╛рд░ рд╕рд░реНрд╡рд░_рдЯреЗрд╕реНрдЯ рд╡рд┐рдзрд┐ рд╣реЛрдЧреА, рдЬреЛ рд╕рд░реНрд╡рд░, рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рдкреНрд░реЙрдХреНрд╕реА рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрд░реЛрдХреНрдд рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИ, рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреА рд╣реИ рдХрд┐ рдЬрдм рдХрдиреЗрдХреНрд╢рди рдмрдВрдж рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд░рд┐рдПрдХреНрдЯрд░ рдХреЛ рд░реЛрдХ рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рджреНрд╡рд╛рд░рд╛ рд╕рд░реНрд╡рд░ рдХреЛ рднреЗрдЬреЗ рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рддрд░реНрдХ рднреА рд▓реЗрддрд╛ рд╣реИред

module HelperMethods<br/> def start_serv <br/> File .unlink(SOCK_FILE) if File .exists?(SOCK_FILE)<br/> EM.run {<br/> EventMachine.start_server "127.0.0.1" , 8080 , SocketServer<br/> EventMachine.start_unix_domain_server(SOCK_FILE, DaemonServer)<br/> client = EM.connect_unix_domain(SOCK_FILE, TestClient)<br/> yield client<br/> }<br/> end <br/> <br/> # if request takes to long it will show fail <br/> def timer start<br/> timeout = 6 <br/> EM.add_timer(timeout){<br/> ( Time .now-start).should be_within( 0 ).of(timeout)<br/> EM.stop<br/> }<br/> end <br/> <br/> #main wrapper for test starts server daemon and client <br/> def server_test request<br/> time = Time .now<br/> start_serv do |client|<br/> client.send_request request do |response|<br/> yield response<br/> end <br/> client.onclose= lambda {EM.stop}<br/> timer (time)<br/> end <br/> end <br/> end <br/>

рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдореИрдВ рдкрд░реАрдХреНрд╖рдг рдХреА рдЬрд╛рдВрдЪ рдХрд░реВрдВрдЧрд╛ рдХрд┐ рдпрд╣ рдХрд╛рд░реНрдп рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

describe "on sending test request" do <br/> include HelperMethods<br/> it "should responsend with right answer" do <br/> server_test({ 'id' => 0 , 'text' => "req1" }) do |response|<br/> response[ 'text' ].should == "answ1" <br/> response[ 'id' ].should == 0 <br/> end <br/> end <br/> end <br/>

рдпрд╣ рд╕рдм, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдореБрдЭреЗ рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдпрд╣ рд▓реЗрдЦ рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ред рд╕рднреА рдХреЛрдб github рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИред

PS рдпрд╣ рдмрд╣реБрдд рдкрд╛рда рдирд┐рдХрд▓рд╛, рдЬрд┐рд╕рдиреЗ рдЕрдВрдд рддрдХ рдкрдврд╝рдиреЗ рдореЗрдВ рдорд╣рд╛рд░рдд рд╣рд╛рд╕рд┐рд▓ рдХреА, рдзрдиреНрдпрд╡рд╛рджред

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


All Articles