Для чего нужен Thread.current в примере DCI в Ruby?

Что такое Thread.current в этом коде? Я смотрю на этот пример использования DCI в приложении Rails. В lib/context.rb есть это:

module Context
  include ContextAccessor

  def context=(ctx)
    Thread.current[:context] = ctx
  end

  def in_context
    old_context = self.context
    self.context = self
    res = yield
    self.context = old_context
    res
  end
end

который используется в различных контекстах в приложении / контекстах, например:

def bid
  in_context do
    validator.validate
    biddable.create_bid
  end
  #...
end

В чем преимущество запуска кода в in_context заблокировать и установить пару ключ-значение в текущем потоке?

2 ответа

Решение

Как правило, внутри блока у вас нет доступа к контексту вызывающего (кроме переменных закрытия).

▶ class A
▷   attr_accessor :a
▷   def test
▷     yield if block_given?
▷   end  
▷ end  
#⇒ :test
▶ inst = A.new
#⇒ #<A:0x00000006f41e28>
▶ inst.a = 'Test'
#⇒ "Test"
▶ inst.test do 
▷   puts self
▷   # here you do not have an access to inst at all
▷   # this would raise an exception: puts self.a
▷ end
#⇒ main

Но с контекстом у вас все еще может быть доступ к inst изнутри блока:

▶ in_context do 
▷   puts self.context.a
▷ end
#⇒ 'Test'

Итак, можно представить proc (рассмотреть оба A а также B иметь Context в комплекте):

▶ pr = ->() { puts self.context }
▶ A.new.in_context &pr
#⇒ #<A:0x00000006f41e28>
▶ B.new.in_context &pr
#⇒ #<B:0x00000006f41eff>

Сейчас внешний procpr имеет практически полный доступ к своему абоненту.

Thread.current требуется для поддержки многопоточного приложения, где каждый поток имеет свой собственный контекст.

Существует также ContextAccessor модуль включен, где каждый получает контекст. Соединение их просто дает более четкую картину:

# context.rb
def context=(ctx)
  Thread.current[:context] = ctx
end

# context_accessor.rb
def context
  Thread.current[:context]
end

in_context Метод предназначен для безопасного изменения контекста внутри своего блока. Какими бы ни были изменения, старый контекст восстанавливается, когда блок заканчивает выполнение.

Другие вопросы по тегам