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