Class: RestCore::Promise
- Inherits:
-
Object
- Object
- RestCore::Promise
- 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, REQUEST_URI, RESPONSE_BODY, RESPONSE_HEADERS, RESPONSE_KEY, RESPONSE_SOCKET, RESPONSE_STATUS, Simple, TIMER, Universal, VERSION
Class Method Summary collapse
- .backtrace ⇒ Object
- .claim(env, k = RC.id, body, status, headers) ⇒ Object
-
.set_backtrace(e) ⇒ Object
should never raise!.
Instance Method Summary collapse
-
#defer ⇒ Object
called in client thread.
-
#done? ⇒ Boolean
It’s considered done only if the HTTP request is done, and we’re not in asynchronous mode otherwise the callback should be called first.
-
#fulfill(body, status, headers, socket = nil) ⇒ Object
called in requesting thread after the request is done.
- #future_body ⇒ Object
- #future_failures ⇒ Object
- #future_headers ⇒ Object
- #future_response ⇒ Object
- #future_socket ⇒ Object
- #future_status ⇒ Object
-
#initialize(env, k = RC.id, immediate = false, &job) ⇒ Promise
constructor
A new instance of Promise.
- #inspect ⇒ Object
-
#reject(error) ⇒ Object
called in requesting thread if something goes wrong or timed out.
-
#then(&action) ⇒ Object
append your actions, which would be called when we’re calling back.
-
#wait ⇒ Object
called in client thread (client.wait).
-
#yield ⇒ Object
called in client thread (from the future (e.g. body)).
Methods included from RestCore
Constructor Details
#initialize(env, k = RC.id, immediate = false, &job) ⇒ Promise
Returns a new instance of Promise.
33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/rest-core/promise.rb', line 33 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, self.called = nil self.condv = ConditionVariable.new self.mutex = Mutex.new defer(&job) if job end |
Class Method Details
.backtrace ⇒ Object
24 25 26 |
# File 'lib/rest-core/promise.rb', line 24 def self.backtrace Thread.current[:backtrace] || [] end |
.claim(env, k = RC.id, body, status, headers) ⇒ Object
18 19 20 21 22 |
# File 'lib/rest-core/promise.rb', line 18 def self.claim env, k=RC.id, body, status, headers promise = new(env, k) promise.fulfill(body, status, headers) promise end |
.set_backtrace(e) ⇒ Object
should never raise!
29 30 31 |
# File 'lib/rest-core/promise.rb', line 29 def self.set_backtrace e e.set_backtrace((e.backtrace || caller) + backtrace) end |
Instance Method Details
#defer ⇒ Object
called in client thread
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/rest-core/promise.rb', line 66 def defer if pool_size < 0 # negative number for blocking call self.thread = Thread.current # set timeout after thread set, before yield (because yield is blocking) env[TIMER].on_timeout{ cancel_task } if env[TIMER] protected_yield{ yield } else backtrace = caller + self.class.backtrace if pool_size > 0 self.task = client_class.thread_pool.defer(mutex) do Thread.current[:backtrace] = backtrace protected_yield{ yield } end else self.thread = Thread.new do Thread.current[:backtrace] = backtrace protected_yield{ yield } end end # set timeout after thread/task set env[TIMER].on_timeout{ cancel_task } if env[TIMER] end end |
#done? ⇒ Boolean
It’s considered done only if the HTTP request is done, and we’re not in asynchronous mode otherwise the callback should be called first. For synchronous mode, since we’re waiting for the callback anyway, we don’t really have to check if it’s called.
124 125 126 |
# File 'lib/rest-core/promise.rb', line 124 def done? !!status && (!immediate || called) end |
#fulfill(body, status, headers, socket = nil) ⇒ Object
called in requesting thread after the request is done
103 104 105 106 |
# File 'lib/rest-core/promise.rb', line 103 def fulfill body, status, headers, socket=nil env[TIMER].cancel if env[TIMER] mutex.synchronize{ fulfilling(body, status, headers, socket) } end |
#future_body ⇒ Object
51 |
# File 'lib/rest-core/promise.rb', line 51 def future_body ; Future.new(self, RESPONSE_BODY ); end |
#future_failures ⇒ Object
55 |
# File 'lib/rest-core/promise.rb', line 55 def future_failures; Future.new(self, FAIL) ; end |
#future_headers ⇒ Object
53 |
# File 'lib/rest-core/promise.rb', line 53 def future_headers ; Future.new(self, RESPONSE_HEADERS); end |
#future_response ⇒ Object
56 57 58 59 60 61 62 63 |
# File 'lib/rest-core/promise.rb', line 56 def future_response env.merge(RESPONSE_BODY => future_body, RESPONSE_STATUS => future_status, RESPONSE_HEADERS => future_headers, RESPONSE_SOCKET => future_socket, FAIL => future_failures, PROMISE => self) end |
#future_socket ⇒ Object
54 |
# File 'lib/rest-core/promise.rb', line 54 def future_socket ; Future.new(self, RESPONSE_SOCKET ); end |
#future_status ⇒ Object
52 |
# File 'lib/rest-core/promise.rb', line 52 def future_status ; Future.new(self, RESPONSE_STATUS ); end |
#inspect ⇒ Object
47 48 49 |
# File 'lib/rest-core/promise.rb', line 47 def inspect "<#{self.class.name} for #{env[REQUEST_URI]}>" end |
#reject(error) ⇒ Object
called in requesting thread if something goes wrong or timed out
109 110 111 112 |
# File 'lib/rest-core/promise.rb', line 109 def reject error env[TIMER].cancel if env[TIMER] mutex.synchronize{ rejecting(error) } end |
#then(&action) ⇒ Object
append your actions, which would be called when we’re calling back
115 116 117 118 |
# File 'lib/rest-core/promise.rb', line 115 def then &action k << action self end |
#wait ⇒ Object
called in client thread (client.wait)
91 92 93 94 |
# File 'lib/rest-core/promise.rb', line 91 def wait # it might be awaken by some other futures! mutex.synchronize{ condv.wait(mutex) until done? } unless done? end |
#yield ⇒ Object
called in client thread (from the future (e.g. body))
97 98 99 100 |
# File 'lib/rest-core/promise.rb', line 97 def yield wait callback end |