1# frozen_string_literal: true
2
3class SessionManager
4 class Timeout < StandardError; end
5
6 def initialize(blather, id_msg, timeout: 10, error_if: nil)
7 @blather = blather
8 @sessions = {}
9 @id_msg = id_msg
10 @timeout = timeout
11 @error_if = error_if
12 end
13
14 def promise_for(stanza, timeout: @timeout)
15 begin; raise Timeout, "Timeout"; rescue Timeout; timeout_exception = $!; end
16 id = "#{stanza.to.stripped}/#{stanza.public_send(@id_msg)}"
17 @sessions.fetch(id) do
18 @sessions[id] = EMPromise.new
19 EM.add_timer(timeout) do
20 @sessions.delete(id)&.reject(timeout_exception)
21 end
22 @sessions[id]
23 end
24 end
25
26 def write(stanza, timeout: @timeout)
27 promise = promise_for(stanza, timeout: timeout)
28 @blather << stanza
29 promise
30 end
31
32 def fulfill(stanza)
33 id = "#{stanza.from.stripped}/#{stanza.public_send(@id_msg)}"
34 if stanza.error? || @error_if&.call(stanza)
35 @sessions.delete(id)&.reject(stanza)
36 else
37 @sessions.delete(id)&.fulfill(stanza)
38 end
39 end
40end