Calling the authentication service

If you remember the initial use case, CCM wants to interact with the authentication service from the Ruby-on-Rails back office application. Therefore, you will implement the client in Ruby. The code you came up with is reproduced as follows:

channel  = AMQP::Channel.new(connection)

channel.on_error do |ch, channel_close|
  connection.close { EventMachine.stop }
  raise "Channel error: #{channel_close.inspect()}"
end

channel.headers(
       'internal-services',
       :durable     => true,
       :auto_delete => false,
       :passive     => true) do |exchange|

  channel.queue('',
    :exclusive => true,
    :durable => false,
    :auto_delete => true) do |response_queue|

    response_queue.subscribe do |metadata, payload|
      handle_response(metadata.content_type, payload)
    end

    puts "Response queue created: #{response_queue.name}"
    message_id = SecureRandom.uuid
    message_json = JSON.generate({
       :username => user_name,
       :password => password})

    exchange.publish(
       message_json,
       :content_type     => 'application/vnd.ccm.login.req.v1+json',
       :content_encoding => 'UTF-8',
       :message_id       => message_id,
       :correlation_id   => message_id,
       :reply_to         => response_queue.name,
       :headers          => { :request_type => 'login',
                              :request_version => 'v1' })
  end

  EventMachine.add_timer(3) do
    puts 'No response after 3 seconds'
    connection.close { EventMachine.stop }
  end
end

There are several interesting bits in this code. Observe that first, a passive declaration of the internal-services headers exchange is performed. What does this mean? Basically, it is a declaration attempt that just checks the existence of the exchange, the expected routing type, and the durability configuration. If you remember our discussion about check then act strategies in Chapter 2, Creating an Application Inbox, you're probably thinking "Ah hah! You're doing the opposite of what you preached." Actually, in this case, it's okay if the exchange gets deleted after the check and the subsequent publish operation fails; the failure will be dealt with by the channel error handler (at the top of the code snippet). This passive declaration saves you the effort of creating a temporary queue for no reason if it's clear that the publish operation will fail anyway.

With this in place, the next step consists of creating the exclusive autodelete response queue. Did you spot that an empty string is used for its name? This means that it will be up to RabbitMQ to generate a unique name for the queue, which is what you want since you're using short-lived response queues. Then, the response handler gets subscribed to the queue, which makes sense because we want to do this before sending the request. Otherwise, we may not be ready to receive the response if it comes back very quickly.

After this, the login message is created and published to the exchange with the necessary reply_to property and the request_type and request_version headers. For good measure, a correlation_id property is also provided, though it's not used since a temporary queue is used for the response (instead of a permanent one).

Note

You can learn more about EventMachine and how it enables Ruby to execute a code in a nonblocking fashion at http://rubyeventmachine.com.

Finally, a time-out is set in order to deal with a case where no service response comes back. This is crucial if you do not want to block the client application threads forever in case there is an issue with the service, a blocking that could eventually make the whole application unusable.

Tip

Reasonable time-outs is one of the secret sauces of distributed systems that degrade gracefully when things go haywire. Another ingredient of the secret sauce is retries with exponential back-offs and a capped number of attempts.

You're done with the authentication service client. If you glance at the management console while a service request is underway, you will see the temporary reply queue right above the authentication-service queue, as illustrated in the following screenshot. The name of the management console starts with amq.gen- to make it clear that it's a name that has been generated by RabbitMQ. Observe that the queue is exclusively accessible to its owner:

Calling the authentication service

A transient reply queue and the authentication service queue involved in a request-response interaction

At this point, you've built a solid message-oriented SOA foundation that you build upon to roll out new services or new versions of existing services as the need arises.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.222.185