Class: OMF::SFA::Util::Promise

Inherits:
Base::LObject
  • Object
show all
Defined in:
lib/omf-sfa/util/promise.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name = nil) ⇒ Promise

Returns a new instance of Promise.



263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/omf-sfa/util/promise.rb', line 263

def initialize(name = nil)
  @pretty_name = name
  @name = "p#{hash()}"
  @name += "-#{name}" if name
  @status = :pending
  @resolved_handlers = []
  @rejected_handlers = []
  @always_handlers = []
  @progress = []
  @progress_handlers = nil
  progress "#{@pretty_name} started" if @pretty_name
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



261
262
263
# File 'lib/omf-sfa/util/promise.rb', line 261

def name
  @name
end

Class Method Details

.all(*promises) ⇒ Object

Returns a promise which fires when all dependencies



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/omf-sfa/util/promise.rb', line 37

def self.all(*promises)
  count = promises.length
  results = []
  new_promise = self.new()
  if count == 0
    new_promise.resolve(results)
  else
    already_rejected = false
    promises.each_with_index do |p, i|
      p.on_success do |v|
        results[i] = v
        if (count -= 1) <= 0
          new_promise.resolve(results)
        end
      end
      p.on_error do |err_code, msg|
        unless already_rejected
          already_rejected = true
          new_promise.reject(err_code, msg)
        end
      end
    end
  end
  new_promise
end

Instance Method Details

#error_code(exception_on_unresolved = PromiseUnresolvedException) ⇒ Object



81
82
83
84
85
86
87
88
# File 'lib/omf-sfa/util/promise.rb', line 81

def error_code(exception_on_unresolved = PromiseUnresolvedException)
  if @status == :rejected
    @err_code
  else
    ex = exception_on_unresolved
    raise ex.is_a?(PromiseException) ? ex.new(self) : ex
  end
end

#error_msg(exception_on_unresolved = PromiseUnresolvedException) ⇒ Object



72
73
74
75
76
77
78
79
# File 'lib/omf-sfa/util/promise.rb', line 72

def error_msg(exception_on_unresolved = PromiseUnresolvedException)
  if @status == :rejected
    @value
  else
    ex = exception_on_unresolved
    raise ex.is_a?(PromiseException) ? ex.new(self) : ex
  end
end

#filter(&block) ⇒ Object

Call block to allow modifications to the ‘resolve’ value



129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/omf-sfa/util/promise.rb', line 129

def filter(&block)
  if @filter_block
    raise "Can only define one filter block - previous #{@filter_block}"
  end
  @filter_block = block
  if @status == :resolved
    unless @resolved_handlers.empty?
      warn "Attached filter after promise was already resolved and reported to 'on_success'"
    end
    _resolve(@value)
  end
  self
end

#on_always(&block) ⇒ Object

Register block to call whenever this promise transitions out of ‘pending’.



193
194
195
196
197
198
199
200
# File 'lib/omf-sfa/util/promise.rb', line 193

def on_always(&block)
  if @status == :pending
    @always_handlers << block
  else
    _call('on_always', [block], nil, false)
  end
  self
end

#on_error(other_promise = nil, &block) ⇒ Object

Register block to call on error, or other promise to ‘upcall’ on error.



177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/omf-sfa/util/promise.rb', line 177

def on_error(other_promise = nil, &block)
  if other_promise
    raise "can't have block as well" if block
    block = lambda {|c, m| other_promise.reject(c, m) }
  end
  if @status == :rejected
    _call('on_error', [block], [@err_code, @value])
  else
    @rejected_handlers << block
  end
  self
end

#on_progress(other_promise = nil, prefix = nil, &block) ⇒ Object

Register block to call whenever a new progress message is being reported



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/omf-sfa/util/promise.rb', line 204

def on_progress(other_promise = nil, prefix = nil, &block)
  if other_promise
    raise "can't have block as well" if block
    block = lambda do |ts, m|
      m = "  #{prefix ? "[#{prefix}]  " : ''}#{m}"
      other_promise.progress(m, ts)
    end
  end
  @progress.each do |ts, m|
    #_call('on_progress', [block], [ts, "  #{prefix ? "#{prefix}: " : ''}#{m}"], false)
    _call('on_progress', [block], [ts, m], false)
  end
  (@progress_handlers ||= []) << block
  self
end

#on_success(other_promise = nil, &block) ⇒ Object

Register block to call on success, or other promise to ‘upcall’ on success.



161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/omf-sfa/util/promise.rb', line 161

def on_success(other_promise = nil, &block)
  if other_promise
    raise "can't have block as well" if block
    block = lambda {|v| other_promise.resolve(v) }
  end
  if @status == :resolved
    _call('on_success', [block], [@value])
  else
    @resolved_handlers << block
  end
  self
end

#pending?Boolean

Returns:

  • (Boolean)


224
225
226
# File 'lib/omf-sfa/util/promise.rb', line 224

def pending?
  (@status == :proxy) ? @proxy.pending? : (@status == :pending)
end

#progress(msg = nil, timestamp = nil) ⇒ Object

To track the progress towards resolving or rejecting the promise the various tasks can report on their progress through this method. Calling it with an empty message will return an array of progress messages



148
149
150
151
152
153
154
155
156
# File 'lib/omf-sfa/util/promise.rb', line 148

def progress(msg = nil, timestamp = nil)
  if msg
    @progress << [timestamp ||= Time.now, msg]
    if @progress_handlers
      _call('on_progress', @progress_handlers, [timestamp, "  #{msg}"], false)
    end
  end
  @progress
end

#reject(err_code, msg = nil) ⇒ Object

Resolve the promise.

Parameters:

  • Reject (Object)

    message



113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/omf-sfa/util/promise.rb', line 113

def reject(err_code, msg = nil)
  unless msg
    # no error code
    msg = err_code
    err_code = 999
  end
  unless @status == :pending
    warn "No longer pending - #{self.inspect} - #{@value}"
    raise PromiseAlreadySetException.new(self)
  end
  _reject(err_code, msg)
  self
end

#resolve(value) ⇒ Object

Resolve the promise.

Parameters:

  • value (Object)

    of promise

Raises:



94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/omf-sfa/util/promise.rb', line 94

def resolve(value)
  raise PromiseAlreadySetException.new(self) unless @status == :pending

  #puts "--------RESOLVE-#{@name}-#{@status}(#{@resolved_handlers.inspect}>>> "
  if value.is_a? self.class
    @status = :proxy
    @proxy = value
    @proxy.on_success {|v| _resolve(v)}
    @proxy.on_error {|e, m| _reject(e, m)}
  else
    _resolve(value)
  end
  self
end

#resolved?Boolean

Returns:

  • (Boolean)


220
221
222
# File 'lib/omf-sfa/util/promise.rb', line 220

def resolved?
  (@status == :proxy) ? @proxy.resolved? : (@status == :resolved)
end

#statusObject



228
229
230
# File 'lib/omf-sfa/util/promise.rb', line 228

def status
  (@status == :proxy) ? @proxy.status : @status
end

#to_htmlObject



232
233
234
235
236
237
238
239
240
241
# File 'lib/omf-sfa/util/promise.rb', line 232

def to_html
  case @status
  when :pending
    '.... pending'
  when :resolved
    @value.to_s
  else
    "ERROR(#{@err_code}: #{@value}"
  end
end

#to_json(*a) ⇒ Object

def to_json(*a)

to_str().to_json(*a)

end



247
248
249
250
251
252
253
254
# File 'lib/omf-sfa/util/promise.rb', line 247

def to_json(*a)
  puts ">>> JSONIFY PROMISE - #{self.to_s} - #{@value}"
  if @status == :resolved
    @value.to_json(*a)
  else
    raise PromiseUnresolvedException.new(self)
  end
end

#to_sObject



256
257
258
# File 'lib/omf-sfa/util/promise.rb', line 256

def to_s
  "#<#{self.class}:#{@name}-#{@status}>"
end

#value(exception_on_unresolved = PromiseUnresolvedException) ⇒ Object



63
64
65
66
67
68
69
70
# File 'lib/omf-sfa/util/promise.rb', line 63

def value(exception_on_unresolved = PromiseUnresolvedException)
  if @status == :resolved
    @value
  else
    ex = exception_on_unresolved
    raise ex.is_a?(PromiseException) ? ex.new(self) : ex
  end
end