# frozen_string_literal: true class SessionManager class Timeout < StandardError; end def initialize(blather, id_msg, timeout: 5, error_if: nil) @blather = blather @sessions = {} @id_msg = id_msg @timeout = timeout @error_if = error_if end def promise_for(stanza) id = "#{stanza.to.stripped}/#{stanza.public_send(@id_msg)}" @sessions.fetch(id) do @sessions[id] = EMPromise.new EM.add_timer(@timeout) do @sessions.delete(id)&.reject(Timeout.new) end @sessions[id] end end def write(stanza) promise = promise_for(stanza) @blather << stanza promise end def fulfill(stanza) id = "#{stanza.from.stripped}/#{stanza.public_send(@id_msg)}" if stanza.error? || @error_if&.call(stanza) @sessions.delete(id)&.reject(stanza) else @sessions.delete(id)&.fulfill(stanza) end end end