module NostrManager class FetchEvent < NostrManagerService TIMEOUT = 1 def initialize(filter:, relay_url:) @filter = filter @relay = new_relay(relay_url) @client = Nostr::Client.new end def call filter, client, relay = @filter, @client, @relay event = nil mutex = Mutex.new received_event = ConditionVariable.new log_prefix = "[nostr][#{@relay.name}]" thread = Thread.new do client.on :connect do client.subscribe(filter: filter) end client.on :error do |e| Rails.logger.info "#{log_prefix} Error: #{e}" Thread.current.exit end client.on :message do |m| msg = JSON.parse(m) rescue nil if msg && msg[0] == "EVENT" && msg[2] puts "#{log_prefix} Event received: #{msg[2]["id"]}" mutex.synchronize do event = msg[2] received_event.signal end elsif msg && msg[0] == "EOSE" Thread.current.exit end end client.connect relay end begin Timeout.timeout(TIMEOUT) do mutex.synchronize do received_event.wait(mutex) if event.nil? end end rescue Timeout::Error puts "#{log_prefix} Timeout: No event received within #{TIMEOUT} seconds" ensure thread.exit end event end end end