Class: RestCore::Promise

Inherits:
Object
  • Object
show all
Includes:
RestCore
Defined in:
lib/rest-core/promise.rb

Defined Under Namespace

Classes: Future

Constant Summary

Constants included from RestCore

ASYNC, CLIENT, DRY, FAIL, HIJACK, LOG, PROMISE, REQUEST_HEADERS, REQUEST_METHOD, REQUEST_PATH, REQUEST_PAYLOAD, REQUEST_QUERY, RESPONSE_BODY, RESPONSE_HEADERS, RESPONSE_SOCKET, RESPONSE_STATUS, Simple, TIMER, Universal, VERSION

Instance Method Summary collapse

Methods included from RestCore

eagerload, id

Constructor Details

#initialize(env, k = RC.id, immediate = false, &job) ⇒ Promise

Returns a new instance of Promise.



18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/rest-core/promise.rb', line 18

def initialize env, k=RC.id, immediate=false, &job
  self.env       = env
  self.k         = k
  self.immediate = immediate

  self.body, self.status, self.headers,
    self.socket, self.response, self.error, = nil

  self.condv     = ConditionVariable.new
  self.mutex     = Mutex.new

  defer(&job) if job
end

Instance Method Details

#defer(&job) ⇒ Object

called in client thread



43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/rest-core/promise.rb', line 43

def defer &job
  if pool_size < 0 # negative number for blocking call
    job.call
  elsif pool_size > 0
    self.task = client_class.thread_pool.defer do
      synchronized_yield{ job.call }
    end
  else
    Thread.new{ synchronized_yield{ job.call } }
  end
  env[TIMER].on_timeout{ reject(env[TIMER].error) } if env[TIMER]
end

#fulfill(body, status, headers, socket = nil) ⇒ Object

called in requesting thread after the request is done



69
70
71
72
73
74
75
76
# File 'lib/rest-core/promise.rb', line 69

def fulfill body, status, headers, socket=nil
  env[TIMER].cancel if env[TIMER]
  self.body, self.status, self.headers, self.socket =
    body, status, headers, socket
  # under ASYNC callback, should call immediately
  callback_in_async if immediate
  condv.broadcast # client or response might be waiting
end

#future_bodyObject



36
# File 'lib/rest-core/promise.rb', line 36

def future_body    ; Future.new(self, RESPONSE_BODY   ); end

#future_failuresObject



40
# File 'lib/rest-core/promise.rb', line 40

def future_failures; Future.new(self, FAIL)            ; end

#future_headersObject



38
# File 'lib/rest-core/promise.rb', line 38

def future_headers ; Future.new(self, RESPONSE_HEADERS); end

#future_socketObject



39
# File 'lib/rest-core/promise.rb', line 39

def future_socket  ; Future.new(self, RESPONSE_SOCKET ); end

#future_statusObject



37
# File 'lib/rest-core/promise.rb', line 37

def future_status  ; Future.new(self, RESPONSE_STATUS ); end

#inspectObject



32
33
34
# File 'lib/rest-core/promise.rb', line 32

def inspect
  "<#{self.class.name} for #{env[REQUEST_PATH]}>"
end

#reject(error) ⇒ Object

called in requesting thread if something goes wrong or timed out



79
80
81
82
83
84
85
86
87
88
# File 'lib/rest-core/promise.rb', line 79

def reject error
  task.cancel if task

  self.error = if error.kind_of?(Exception)
                 error
               else
                 Error.new(error || 'unknown')
               end
  fulfill('', 0, {})
end

#waitObject

called in client thread (client.wait)



57
58
59
60
# File 'lib/rest-core/promise.rb', line 57

def wait
  # it might be awaken by some other futures!
  mutex.synchronize{ condv.wait(mutex) until !!status } unless !!status
end

#yieldObject

called in client thread (from the future (e.g. body))



63
64
65
66
# File 'lib/rest-core/promise.rb', line 63

def yield
  wait
  callback
end