RELAY Consumer

View as Markdown

A RELAY Consumer is a simple object that runs in its own process along side your application to handle calling and messaging events in realtime. RELAY Consumers abstract all the setup of connecting to RELAY and automatically dispatch workers to handle requests. Consumers will receive requests and delegate them to their own worker thread, allowing you to focus on your business logic without having to worry about multi-threading or blocking, everything just works. Think of RELAY Consumers like a background worker system for all your calling and messaging needs.

Authenticating a consumer

Authentication requires a SignalWire project ID and a token. You can generate one from your dashboard.

The values can be passed in either as the project and token parameters to the constructor, or by setting the SIGNALWIRE_PROJECT_KEY and SIGNALWIRE_TOKEN environment variables.

An example using constructor parameters:

1class MyConsumer < Signalwire::Relay::Consumer
2 contexts ['incoming']
3
4 def on_incoming_call(call)
5 call.answer
6 call.play_tts 'this consumer uses constructor parameters'
7
8 call.hangup
9 end
10end
11
12MyConsumer.new(project: 'your-project-key', token: 'your-project-token').run

Consumer Contexts

A RELAY Consumer is a simple object, customized by specifying contexts and event handlers to respond to incoming events.

A consumer usually requires at least one contexts for incoming events. Contexts are a list of contexts you want this Consumer to listen for. Learn more about Contexts.

1class MyConsumer < Signalwire::Relay::Consumer
2 contexts ['incoming']
3
4 def on_incoming_call(call)
5 call.answer
6 call.play_tts 'the quick brown fox jumps over the lazy dog'
7
8 call.hangup
9 end
10end
11
12MyConsumer.new.run

Initializing Consumers

You can optionally define a setup method if you need to do any initialization work before processing messages. This is useful to do any one-off work that you wouldn’t want to do for each and every event, such as setting up logging or connecting to a datastore.

1class MyConsumer < Signalwire::Relay::Consumer
2 contexts ['incoming']
3
4 def setup
5 SomeDatabase.connect
6 end
7
8 def on_incoming_call(call)
9 call.answer
10 call.play_tts 'the quick brown fox jumps over the lazy dog'
11
12 call.hangup
13 end
14end
15
16MyConsumer.new.run

Event Handlers

Event handlers are where you will write most of your code. They are executed when your consumer receives a matching event for the contexts specified by your Consumer.

on_incoming_call

Executed when you receive an inbound call, passes in the inbound Call object.

1class MyConsumer < Signalwire::Relay::Consumer
2 contexts ['incoming']
3
4 def on_incoming_call(call)
5 call.answer
6 call.play_tts 'the quick brown fox jumps over the lazy dog'
7
8 call.hangup
9 end
10end
11
12MyConsumer.new.run

ready

This method is executed when the Consumer has connected and is ready to make RELAY requests.

1require 'signalwire'
2
3class MyConsumer < Signalwire::Relay::Consumer
4 def ready
5 logger.debug "The consumer is ready to execute actions now"
6 # Send an SMS on ready
7 result = client.messaging.send(from: "+1XXXXXXXXXX", to: "+1YYYYYYYYYY", context: 'incoming', body: 'Hello from SignalWire!')
8 logger.debug "message id #{result.message_id} was successfully sent" if result.successful
9 end
10end
11
12MyConsumer.new.run

on_task

Receives your message sent through a Relay::Task.

1require 'signalwire'
2
3class MyConsumer < Signalwire::Relay::Consumer
4 contexts ['incoming']
5
6 def on_task(task)
7 logger.debug "Received #{task.message}"
8 end
9end
10
11MyConsumer.new.run

on_incoming_message

This method is executed when the consumer receives an inbound text message on one of the subscribed contexts. Receives a Message object as a parameter.

1class MessageReceiveConsumer < Signalwire::Relay::Consumer
2 contexts ['office']
3
4 def on_incoming_message(message)
5 logger.info "Received message from #{message.from}: #{message.body}"
6 end
7end
8
9MessageReceiveConsumer.new.run

on_message_state_change

Executed when a message state changes in a context the consumer is subscribed to. Receives a Message object as a parameter.

1class MessageSendConsumer < Signalwire::Relay::Consumer
2 def on_message_state_change(message)
3 logger.debug "message id #{message.id} now has state #{message.state}"
4 end
5end
6
7MessageSendConsumer.new.run

Cleaning Up on Exit

When a RELAY Consumer shuts down, you have the opportunity to clean up any resources held by the consumer. For example, you could close any open files, network connections, or send a notification to your monitoring service.

Just implement a teardown method in your consumer and it will be called during the shutdown procedure.

1class MyConsumer < Signalwire::Relay::Consumer
2 contexts ['incoming']
3
4 def teardown
5 SomeDatabase.disconnect
6 end
7
8 def on_incoming_call(call)
9 call.answer
10 call.play_tts 'the quick brown fox jumps over the lazy dog'
11
12 call.hangup
13 end
14end
15
16MyConsumer.new.run

Running Consumers

Running a consumer is just like running any Ruby script, simply execute the script as a separate process and call run to start it. The process will stay up until you shut it down.

Shutting Down Consumers

In order to gracefully shut down a RELAY consumer process, send it the SIGTERM signal. Most process supervisors such as Runit, Docker and Kubernetes send this signal when shutting down a process.