Faraday: `рдорд┐рдбрд▓рд╡реЗрдпрд░_рдореНрдпреВрдЯреЗрдХреНрд╕` рд░реЗрд╕реА рд╣реИред

рдХреЛ рдирд┐рд░реНрдорд┐рдд 23 рдЕрдХреНрддреВре░ 2019  ┬╖  9рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: lostisland/faraday

#!/usr/bin/env ruby

# Taken from faraday internals
def middleware_mutex(&block)
    <strong i="5">@middleware_mutex</strong> ||= begin
        require 'monitor'
        puts "I'm making a monitor!"
        Monitor.new
    end
    puts @middleware_mutex.inspect
    @middleware_mutex.synchronize(&block)
end


threads = 10.times.collect do
    Thread.new do
        middleware_mutex do
            puts "I got the power!"
        end
    end
end

threads.each(&:join)

2.6 рдкрд░ рдЙрджрд╛рд╣рд░рдг рдЖрдЙрдЯрдкреБрдЯ рдпрд╣рд╛рдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:

koyoko% rvm use 2.6          
Using /home/samuel/.rvm/gems/ruby-2.6.3
^[[A%                                                                                                                                                         koyoko% ./middleware_mutex.rb
I'm making a monitor!
#<Monitor:0x000055fb2217ec60 @mon_mutex=#<Thread::Mutex:0x000055fb2217ec10>, @mon_mutex_owner_object_id=47268548572720, @mon_owner=nil, @mon_count=0>
I got the power!
#<Monitor:0x000055fb2217ec60 @mon_mutex=#<Thread::Mutex:0x000055fb2217ec10>, @mon_mutex_owner_object_id=47268548572720, @mon_owner=nil, @mon_count=0>
I got the power!
#<Monitor:0x000055fb2217ec60 @mon_mutex=#<Thread::Mutex:0x000055fb2217ec10>, @mon_mutex_owner_object_id=47268548572720, @mon_owner=nil, @mon_count=0>
I got the power!
#<Monitor:0x000055fb2217ec60 @mon_mutex=#<Thread::Mutex:0x000055fb2217ec10>, @mon_mutex_owner_object_id=47268548572720, @mon_owner=nil, @mon_count=0>
I got the power!
#<Monitor:0x000055fb2217ec60 @mon_mutex=#<Thread::Mutex:0x000055fb2217ec10>, @mon_mutex_owner_object_id=47268548572720, @mon_owner=nil, @mon_count=0>
I got the power!
#<Monitor:0x000055fb2217ec60 @mon_mutex=#<Thread::Mutex:0x000055fb2217ec10>, @mon_mutex_owner_object_id=47268548572720, @mon_owner=nil, @mon_count=0>
I got the power!
#<Monitor:0x000055fb2217ec60 @mon_mutex=#<Thread::Mutex:0x000055fb2217ec10>, @mon_mutex_owner_object_id=47268548572720, @mon_owner=nil, @mon_count=0>
I got the power!
#<Monitor:0x000055fb2217ec60 @mon_mutex=#<Thread::Mutex:0x000055fb2217ec10>, @mon_mutex_owner_object_id=47268548572720, @mon_owner=nil, @mon_count=0>
I got the power!
#<Monitor:0x000055fb2217ec60 @mon_mutex=#<Thread::Mutex:0x000055fb2217ec10>, @mon_mutex_owner_object_id=47268548572720, @mon_owner=nil, @mon_count=0>
I got the power!
#<Monitor:0x000055fb2217ec60 @mon_mutex=#<Thread::Mutex:0x000055fb2217ec10>, @mon_mutex_owner_object_id=47268548572720, @mon_owner=nil, @mon_count=0>
I got the power!
koyoko% ./middleware_mutex.rb
I'm making a monitor!
I'm making a monitor!
#<Monitor:0x000055f197e82388 @mon_mutex=#<Thread::Mutex:0x000055f197e82338>, @mon_mutex_owner_object_id=47248062026180, @mon_owner=nil, @mon_count=0>
I got the power!
I'm making a monitor!
#<Monitor:0x000055f197e81eb0 @mon_mutex=#<Thread::Mutex:0x000055f197e81e60>, @mon_mutex_owner_object_id=47248062025560, @mon_owner=nil, @mon_count=0>
I got the power!
I'm making a monitor!
#<Monitor:0x000055f197e81b90 @mon_mutex=#<Thread::Mutex:0x000055f197e81b40>, @mon_mutex_owner_object_id=47248062025160, @mon_owner=nil, @mon_count=0>
I got the power!
I'm making a monitor!
#<Monitor:0x000055f197e81938 @mon_mutex=#<Thread::Mutex:0x000055f197e818e8>, @mon_mutex_owner_object_id=47248062024860, @mon_owner=nil, @mon_count=0>
I got the power!
I'm making a monitor!
#<Monitor:0x000055f197e816e0 @mon_mutex=#<Thread::Mutex:0x000055f197e81690>, @mon_mutex_owner_object_id=47248062024560, @mon_owner=nil, @mon_count=0>
I got the power!
#<Monitor:0x000055f197e827c0 @mon_mutex=#<Thread::Mutex:0x000055f197e82590>, @mon_mutex_owner_object_id=47248062026720, @mon_owner=nil, @mon_count=0>
I got the power!
I'm making a monitor!
#<Monitor:0x000055f197e81438 @mon_mutex=#<Thread::Mutex:0x000055f197e813e8>, @mon_mutex_owner_object_id=47248062024220, @mon_owner=nil, @mon_count=0>
I got the power!
I'm making a monitor!
#<Monitor:0x000055f197e811e0 @mon_mutex=#<Thread::Mutex:0x000055f197e81190>, @mon_mutex_owner_object_id=47248062023920, @mon_owner=nil, @mon_count=0>
I got the power!
I'm making a monitor!
#<Monitor:0x000055f197e80f88 @mon_mutex=#<Thread::Mutex:0x000055f197e80f38>, @mon_mutex_owner_object_id=47248062023620, @mon_owner=nil, @mon_count=0>
I got the power!
I'm making a monitor!
#<Monitor:0x000055f197e80d30 @mon_mutex=#<Thread::Mutex:0x000055f197e80ce0>, @mon_mutex_owner_object_id=47248062023320, @mon_owner=nil, @mon_count=0>
I got the power!

рдЬрд░реНрдмреА рдкрд░ рдЙрджрд╛рд╣рд░рдг рдЖрдЙрдЯрдкреБрдЯ рдпрд╣рд╛рдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:

koyoko% rvm use jruby        
Using /home/samuel/.rvm/gems/jruby-9.2.6.0
koyoko% ./middleware_mutex.rb
I'm making a monitor!
I'm making a monitor!
I'm making a monitor!
#<Monitor:0x7ea668b0 @mon_mutex=#<Thread::Mutex:0x3027cbd3>, @mon_owner=nil, @mon_count=0>
I got the power!
I'm making a monitor!I'm making a monitor!#<Monitor:0x53ca91a5 @mon_mutex=#<Thread::Mutex:0x57f50f04>, @mon_owner=nil, @mon_count=0>I'm making a monitor!
#<Monitor:0x1b5e79ce @mon_mutex=#<Thread::Mutex:0x159994d5>, @mon_owner=nil, @mon_count=0>
I got the power!
#<Monitor:0x67589eb3 @mon_mutex=#<Thread::Mutex:0x63671680>, @mon_owner=nil, @mon_count=1>#<Monitor:0x1b5e79ce @mon_mutex=#<Thread::Mutex:0x159994d5>, @mon_owner=nil, @mon_count=0>
I got the power!
#<Monitor:0x67589eb3 @mon_mutex=#<Thread::Mutex:0x63671680>, @mon_owner=nil, @mon_count=0>
I got the power!

#<Monitor:0x49c2c95a @mon_mutex=#<Thread::Mutex:0xcc04e06>, @mon_owner=nil, @mon_count=0>
I got the power!

I'm making a monitor!#<Monitor:0x1b5e79ce @mon_mutex=#<Thread::Mutex:0x159994d5>, @mon_owner=nil, @mon_count=0>
#<Monitor:0x6fa38df1 @mon_mutex=#<Thread::Mutex:0x756e0d98>, @mon_owner=nil, @mon_count=0>
I got the power!
I got the power!

#<Monitor:0x4a9f0f52 @mon_mutex=#<Thread::Mutex:0x600dfde7>, @mon_owner=nil, @mon_count=0>

I got the power!

I got the power!
I got the power!

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

@ioquatix

$ xsel -b | ruby --dump=insns
...
== disasm: #<ISeq:middleware_mutex@-:1 (1,0)-(9,3)> (catch: FALSE)
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: 0, kw: -1@-1, kwrest: -1])
[ 1] block@0<Block>
0000 putnil                                                           (   2)[LiCa]
0001 defined                      instance-variable, :<strong i="7">@middleware_mutex</strong>, false
0005 branchunless                 14
0007 getinstancevariable          :<strong i="8">@middleware_mutex</strong>, <is:0>
0010 dup
0011 branchif                     42
0013 pop
0014 putself                                                          (   3)[Li]
0015 putstring                    "monitor"
0017 opt_send_without_block       <callinfo!mid:require, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0020 pop
0021 putself                                                          (   4)[Li]
0022 putstring                    "I'm making a monitor!"
0024 opt_send_without_block       <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0027 pop
0028 opt_getinlinecache           35, <is:1>                          (   5)[Li]
0031 getconstant                  :Monitor
0033 opt_setinlinecache           <is:1>
0035 opt_send_without_block       <callinfo!mid:new, argc:0, ARGS_SIMPLE>, <callcache>
0038 dup                                                              (   2)
0039 setinstancevariable          :<strong i="9">@middleware_mutex</strong>, <is:0>
0042 pop
0043 putself                                                          (   7)[Li]
0044 getinstancevariable          :<strong i="10">@middleware_mutex</strong>, <is:0>
0047 opt_send_without_block       <callinfo!mid:inspect, argc:0, ARGS_SIMPLE>, <callcache>
0050 opt_send_without_block       <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0053 pop
0054 getinstancevariable          :<strong i="11">@middleware_mutex</strong>, <is:0>          (   8)[Li]
0057 getblockparamproxy           block<strong i="12">@0</strong>, 0
0060 send                         <callinfo!mid:synchronize, argc:0, ARGS_BLOCKARG>, <callcache>, nil
0064 leave                                                            (   9)[Re]

рддреЛ ||= рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:

if defined?(@middleware_mutex)
  <strong i="17">@middleware_mutex</strong>
else
  <strong i="18">@middleware_mutex</strong> = expression
end

рдПрдордЖрд░рдЖрдИ рдореЗрдВ рдЗрд╕реЗ рдУрд╡рд░рд░рд╛рдЗрдб рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА:

if defined?(@middleware_mutex)
  <strong i="22">@middleware_mutex</strong>
else
  result = expression
  # special bytecode to do `<strong i="23">@middleware_mutex</strong> = result unless defined?(@middleware_mutex)` atomically
end

рдмреЗрд╢рдХ рдЗрд╕рдХреА рд▓рд╛рдЧрдд рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЕрд╕рд╛рдЗрди рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдЬрд╛рдВрдЪ рд╣реИред

рдФрд░ рдмреНрд▓реЙрдХ рдЕрднреА рднреА рдХрдИ рдмрд╛рд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрдЧрд╛, рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рдиреЗ рд╕реЗ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдбреЗрдбрд▓реЙрдХ рдФрд░ рдЙрдЪреНрдЪ рдУрд╡рд░рд╣реЗрдб рд╣реЛ рдЬрд╛рдПрдЧрд╛, рддрд╛рдХрд┐ рд╡рд╣ рд╣рд┐рд╕реНрд╕рд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛрдб рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдмрдЪрд╛ рд╣реЛред

рд╕рднреА 9 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдпрджрд┐ рдЖрдк рдЗрд╕реЗ JRuby рдкрд░ рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рддреЛ <strong i="5">@middleware_mutex</strong> ||= begin рдкрд░рдорд╛рдгреБ рдирд╣реАрдВ рд╣реИ рдФрд░ рдЖрдк рди рдХреЗрд╡рд▓ рдХрдИ рдмрд╛рд░ рдмреНрд▓реЙрдХ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реИрдВ, @middleware_mutex рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рдореЙрдирд┐рдЯрд░реЛрдВ рдкрд░ рдХрдИ рдмрд╛рд░ рд╕реЗрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ 2.6 рдХреЛ рднреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ puts рдмреНрд▓реЙрдХрд┐рдВрдЧ/рдереНрд░реЗрдб рд╕рдВрджрд░реНрдн рд╕реНрд╡рд┐рдЪ рдкреЗрд╢ рдХрд░ рд╕рдХрддрд╛ рд╣реИред

_рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж!_

рдпрд╣ рджреЗрдЦрдирд╛ рдХрд╛рдлреА рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ рдХрд┐ ||= рдПрдХрд▓ рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ рдХреА рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рджреЗрддрд╛, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ MRI рдкрд░ рднреАред

@eregon рд╣рд╛рдБ, рдореИрдВ рднреА рдЗрд╕рд╕реЗ рд╣реИрд░рд╛рди рдерд╛ред рдХреНрдпрд╛ рд╣рдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИ рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЛ рдбрдВрдк рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ?

@ioquatix

$ xsel -b | ruby --dump=insns
...
== disasm: #<ISeq:middleware_mutex@-:1 (1,0)-(9,3)> (catch: FALSE)
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: 0, kw: -1@-1, kwrest: -1])
[ 1] block@0<Block>
0000 putnil                                                           (   2)[LiCa]
0001 defined                      instance-variable, :<strong i="7">@middleware_mutex</strong>, false
0005 branchunless                 14
0007 getinstancevariable          :<strong i="8">@middleware_mutex</strong>, <is:0>
0010 dup
0011 branchif                     42
0013 pop
0014 putself                                                          (   3)[Li]
0015 putstring                    "monitor"
0017 opt_send_without_block       <callinfo!mid:require, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0020 pop
0021 putself                                                          (   4)[Li]
0022 putstring                    "I'm making a monitor!"
0024 opt_send_without_block       <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0027 pop
0028 opt_getinlinecache           35, <is:1>                          (   5)[Li]
0031 getconstant                  :Monitor
0033 opt_setinlinecache           <is:1>
0035 opt_send_without_block       <callinfo!mid:new, argc:0, ARGS_SIMPLE>, <callcache>
0038 dup                                                              (   2)
0039 setinstancevariable          :<strong i="9">@middleware_mutex</strong>, <is:0>
0042 pop
0043 putself                                                          (   7)[Li]
0044 getinstancevariable          :<strong i="10">@middleware_mutex</strong>, <is:0>
0047 opt_send_without_block       <callinfo!mid:inspect, argc:0, ARGS_SIMPLE>, <callcache>
0050 opt_send_without_block       <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0053 pop
0054 getinstancevariable          :<strong i="11">@middleware_mutex</strong>, <is:0>          (   8)[Li]
0057 getblockparamproxy           block<strong i="12">@0</strong>, 0
0060 send                         <callinfo!mid:synchronize, argc:0, ARGS_BLOCKARG>, <callcache>, nil
0064 leave                                                            (   9)[Re]

рддреЛ ||= рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:

if defined?(@middleware_mutex)
  <strong i="17">@middleware_mutex</strong>
else
  <strong i="18">@middleware_mutex</strong> = expression
end

рдПрдордЖрд░рдЖрдИ рдореЗрдВ рдЗрд╕реЗ рдУрд╡рд░рд░рд╛рдЗрдб рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА:

if defined?(@middleware_mutex)
  <strong i="22">@middleware_mutex</strong>
else
  result = expression
  # special bytecode to do `<strong i="23">@middleware_mutex</strong> = result unless defined?(@middleware_mutex)` atomically
end

рдмреЗрд╢рдХ рдЗрд╕рдХреА рд▓рд╛рдЧрдд рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЕрд╕рд╛рдЗрди рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдЬрд╛рдВрдЪ рд╣реИред

рдФрд░ рдмреНрд▓реЙрдХ рдЕрднреА рднреА рдХрдИ рдмрд╛рд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрдЧрд╛, рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рдиреЗ рд╕реЗ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдбреЗрдбрд▓реЙрдХ рдФрд░ рдЙрдЪреНрдЪ рдУрд╡рд░рд╣реЗрдб рд╣реЛ рдЬрд╛рдПрдЧрд╛, рддрд╛рдХрд┐ рд╡рд╣ рд╣рд┐рд╕реНрд╕рд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛрдб рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдмрдЪрд╛ рд╣реЛред

рдУрд╣, рдореИрдВ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рд╣рдордд рд╣реВрдВ рдХрд┐ рдпрд╣ рдРрд╕рд╛ рдХреБрдЫ рдирд╣реАрдВ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдареАрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдХреЛрдб рдереНрд░реЗрдб рд╕реБрд░рдХреНрд╖рд╛ рдХреЗ рдкреАрдУрд╡реА рд╕реЗ рдмреБрд░реА рддрд░рд╣ рдЯреВрдЯрд╛ рд╣реБрдЖ рд╣реИ рдФрд░ ||= рдкрд░рдорд╛рдгреБ рдЗрд╕реЗ рдареАрдХ рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред

рд╡рд╛рд╣ @ioquatix рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж рдФрд░ рдПрдХ рдмрд╛рд░ рдлрд┐рд░ рдЗрд╕ рд╡рд┐рд╖рдп рдкрд░ рдЖрдкрдХреА рд╡рд┐рд╢реЗрд╖рдЬреНрдЮрддрд╛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рджреЗрдЦреА рдЬрд╛ рд╕рдХрддреА рд╣реИред
рдпрд╣реА рд╣реИ, рдЬрд╣рд╛рдВ рддрдХ тАЛтАЛтАЛтАЛрдореБрдЭреЗ рдкрддрд╛ рд╣реИ, рдХреЛрдб рдХрд╛ рдПрдХ рдкреБрд░рд╛рдирд╛ рдЯреБрдХрдбрд╝рд╛ рдЬреЛ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЬреЗрдЖрд░рдмреА рдФрд░ рдЕрдиреНрдп рд╕рдорд╡рд░реНрддреА рд░реВрдмреА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреЗрд╢ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

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

рдореБрдЭреЗ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЗрд╕рд╕реЗ рдХреИрд╕реЗ рдирд┐рдкрдЯрд╛ рдЬрд╛рдП, рдЕрдЧрд░ рдЖрдк рдпрд╛ @eregon рд╣рдореЗрдВ рд╕рд╣реА рджрд┐рд╢рд╛ рдореЗрдВ рдЗрдВрдЧрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рддреЛ рдореБрдЭреЗ рдХреБрдЫ рдЬреНрдЮрд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдФрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓рдиреЗ рдореЗрдВ рдЦреБрд╢реА рд╣реЛрдЧреА

рдпрд╣ рдХреНрд░реВрдмреА рдкрд░ рднреА рдПрдХ рдмрдЧ рд╣реИред рдореИрдВ рдПрдХ рдкреАрдЖрд░ рдЬрдорд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВред

рдореИрдВрдиреЗ #1074 рдореЗрдВ рдПрдХ рд╕рдорд╛рдзрд╛рди рдХреА рдХреЛрд╢рд┐рд╢ рдХреАред рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдФрд░ рд╡рд┐рдЪрд╛рд░ рд╣реИ рдЬрд┐рд╕рдореЗрдВ MiddlewareRegistry рдореЙрдбреНрдпреВрд▓ рдХреЛ рдХрдХреНрд╖рд╛ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдирд╛ рд╢рд╛рдорд┐рд▓ рд╣реИред рддреЛ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп:

https://github.com/lostisland/faraday/blob/d51a6c6979363c820d81a9166847ab09d30fae2b/lib/faraday/response.rb#L26 -L28

рдпрд╣ рдХреБрдЫ рдРрд╕рд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ:

module Faraday
  class Response
    self.middleware_registry = MiddlewareRegistry.new(File.expand_path('response', __dir__),
      raise_error: [:RaiseError, 'raise_error'],
      logger: [:Logger, 'logger'],
    )

рдпрд╣ рд╡рд░реНрдЧ рдЬреАрд╡рдирдЪрдХреНрд░ рд╣реБрдХ рдкрд░ рдирд┐рд░реНрднрд░ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдмрд╣реБрдд рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рдЬрдм рд░реВрдмреА рдХреА рд╡реНрдпрд╛рдЦреНрдпрд╛ рдХреА рдЬрд╛ рд░рд╣реА рд╣реИ рддреЛ MiddlewareRegistry рдпрд╣рд╛рдВ рддрддреНрдХрд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИред

class MiddlewareRegistry
  def initialize
    <strong i="14">@mutex</strong> = Monitor.new
  end
end
рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕