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		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