Home > OS >  It's possible wait for a variable in Ruby, (without sleep)?
It's possible wait for a variable in Ruby, (without sleep)?

Time:07-01

I’m trying to get data from an ssh server, but this action takes some time to run, so I need to wait for them, once I have them, I’ll use this data to send them through my Bot to Slack.

Here my code:

def sshPingRequest()
    Net::SSH.start('xxxx.xxxxx.xxxxx', 'root', :port => "3132") do |ssh|
        output = ssh.exec!("ansible -m ping c3")
        result = output.split("\n").select { |line| line.include?("SUCCESS") || line.include?("FAILURE") }
        puts "############## Done #############"
        return result
    end
end

SlackRubyBotServer::Events.configure do |config|
    data = sshPingRequest() # Help
    config.on :command, '/ans-ping' do |command|
        command.logger.info 'Received a ping, responding with pong.'
        { text: data }
    end 
end

Basically I need to wait for the "result" variable to be ready from the first function, and after sending it in the second function.

Thanks in advance.

CodePudding user response:

According to the documentation

Requests are sent from the client to the server, and are answered asynchronously. This gives great flexibility (since clients can have multiple requests pending at a time), but it also adds complexity. Net::SSH tries to manage this complexity by providing some simpler methods of synchronous communication (see Net::SSH::Connection::Session#exec!).

So,I think that you could call SlackRubyBotServer::Events.configure intro channel NET::SSH

def foo()
  SlackRubyBotServer::Events.configure do |config|
  data = sshPingRequest() # Help
  config.on :command, '/ans-ping' do |command|
    command.logger.info 'Received a ping, responding with pong.'
    { text: data }
  end 
end

def sshPingRequest()
  Net::SSH.start('xxxx.xxxxx.xxxxx', 'root', :port => "3132") do |ssh|
    output = ssh.exec!("ansible -m ping c3")
    result = output.split("\n").select { |line| line.include?("SUCCESS") 
      || line.include?("FAILURE") }
    puts "############## Done #############"

    foo() # while the channel is open

    return result
  end
end

CodePudding user response:

What about promises? Could it be what you are looking for?

https://ruby-concurrency.github.io/concurrent-ruby/1.1.5/Concurrent/Promise.html

From the docs:

Promises are similar to futures and share many of the same behaviours. Promises are far more robust, however. Promises can be chained in a tree structure where each promise may have zero or more children. Promises are chained using the then method. The result of a call to then is always another promise. Promises are resolved asynchronously (with respect to the main thread) but in a strict order: parents are guaranteed to be resolved before their children, children before their younger siblings. The then method takes two parameters: an optional block to be executed upon parent resolution and an optional callable to be executed upon parent failure. The result of each promise is passed to each of its children upon resolution. When a promise is rejected all its children will be summarily rejected and will receive the reason.

Also you can see this guide:

https://medium.com/@gauravbasti2006/lets-keep-our-promise-in-ruby-e45925182fdc

  • Related