Module: Delayer::Deferred::Tools

Included in:
Promise
Defined in:
lib/delayer/deferred/tools.rb

Instance Method Summary collapse

Instance Method Details

#fail(value) ⇒ Object

実行中のDeferredを失敗させる。raiseと違って、Exception以外のオブジェクトをtrap()に渡すことができる。 Deferredのnextとtrapの中でだけ呼び出すことができる。

Args

value

trap()に渡す値

Throw

:__deferredable_fail をthrowする


18
19
# File 'lib/delayer/deferred/tools.rb', line 18

def fail(value)
throw(:__deferredable_fail, value) end

#next(&proc) ⇒ Object


6
7
# File 'lib/delayer/deferred/tools.rb', line 6

def next(&proc)
new.next(&proc) end

#passObject

実行中のDeferredを、Delayerのタイムリミットが来ている場合に限り一旦中断する。 長期に渡る可能性のある処理で、必要に応じて他のタスクを先に実行してもよい場合に呼び出す。


23
24
25
# File 'lib/delayer/deferred/tools.rb', line 23

def pass
  Fiber.yield(Request::PASS) if delayer.expire?
end

#sleep(sec) ⇒ Object

sec 秒後にsuccessとなるPromiseを返す

Args

sec

待つ秒数

Return

Deferred


73
74
75
76
77
78
79
80
# File 'lib/delayer/deferred/tools.rb', line 73

def sleep(sec)
  # pp [sec]
  delayer.Promise.new(true).tap do |promise|
    delayer.new(delay: sec) do
      promise.call()
    end
  end
end

#system(*args) ⇒ Object

Kernel#systemを呼び出して、コマンドが成功たら成功するDeferredを返す。 失敗した場合、trap{}ブロックには $? の値(Process::Status)か、例外が発生した場合それが渡される

Args

*args

Kernel#spawn の引数

Return

Deferred


57
58
59
60
61
62
63
64
65
66
# File 'lib/delayer/deferred/tools.rb', line 57

def system(*args)
  delayer.Deferred.Thread.new {
    Process.waitpid2(Kernel.spawn(*args))
  }.next{|_pid, status|
    if status && status.success?
      status
    else
      raise ForeignCommandAborted.new("command aborted: #{args.join(' ')}", process: status) end
  }
end

#trap(&proc) ⇒ Object


9
10
# File 'lib/delayer/deferred/tools.rb', line 9

def trap(&proc)
new.trap(&proc) end

#when(*args) ⇒ Object

複数のdeferredを引数に取って、それら全ての実行が終了したら、 その結果を引数の順番通りに格納したArrayを引数に呼ばれるDeferredを返す。 引数のDeferredが一つでも失敗するとこのメソッドの返すDeferredも失敗する。

Args

*args

終了を待つDeferredオブジェクト

Return

Deferred


34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/delayer/deferred/tools.rb', line 34

def when(*args)
  args = args.flatten
  return self.next{ [].freeze } if args.empty?
  args.each_with_index{|d, index|
    unless d.is_a?(Deferredable::Chainable) || d.is_a?(Deferredable::Awaitable)
      raise TypeError, "Argument #{index} of Deferred.when must be #{Deferredable::Chainable}, but given #{d.class}"
    end
    if d.respond_to?(:has_child?) && d.has_child?
      raise "Already assigned child for argument #{index}"
    end
  }
  defer, *follow = *args
  defer.next{|res|
    [res, *follow.map{|d| +d }]
  }
end