New Features: Undelivered Emails, MP3 URLs, & Cancel API
We’ve added some new features to messagepub recently.
Undelivered Emails
We’ve now added an Errors page on your account. From this page, you can keep track of emails you’ve sent via messagepub that have not been delivered. This can help you clean up your mailing list and remove the email addresses that are not valid.
MP3 URLs
If you send a phone message, you can get a reply in the form of an mp3 file. Before, you could only listen to that MP3 from one of our web pages. We’ve now added a URL from which you can fetch that MP3 file, giving you the option to download that MP3 and use it however you want to.
The mp3Url parameter is present on the Replies REST API and also on the HTTP postbacks as a parameter. See our documentation on replies for more info.
API Method to Cancel Notifications
You can now cancel a notification that you have sent via messagepub. When you do that, all messages (or recipients) that were scheduled to be delivered in the future will be cancelled. This only makes sense if you want to cancel a notification you had scheduled for the future or if you have an escalation schedule that is still in progress.
For more information on the cancel API, see our documentation.
Questions/Feedback/Comments
If you have any questions regarding our API or if you want to give us your feedback, let us know by emailing us at info [at] messagepub [dot] com or by posting a message in our support forum.
Project Spotlight: Rinda
Rinda is a built-in Ruby library to implement the Linda distributed computing paradigm in Ruby. According to Wikipedia: “Linda is a model of coordination and communication among several parallel processes operating upon objects stored in and retrieved from shared, virtual, associative memory.”
In this blog post, we will describe Rinda and show you how to use Rinda’s TupleSpaces and RingServers.
Intro to DRb
Distributed Ruby (aka DRb) is a library to allow communication between Ruby processes. The processes can be located on the same machine or over a network. Using DRB, one Ruby process can use a remote object located in another Ruby process as if it was local. One of the best introduction to DRb that you will find online can be found at segment7.net. I recommend reading this before proceeding with this post.
Basics of Rinda
Rinda implements a tuple space: a repository of tuples that can be accessed concurrently. Think of a tuple as a Ruby array. For example: [:add, 2, 5]
There are 5 basic operations that can be executed on a tuple space:
- write: write a tuple to the tuple space. This take an optional timeout parameter. After that timeout expires, the tuple is automatically deleted from the space.
- take: read and delete a tuple from the tuple space atomically.
- read: simply read the tuple, leaving it on the tuple space.
- read_all: read all the matching tuples from the tuple space without removing them.
- notify: register for notifications of events such as ‘write’, ‘take’, or ‘delete’ (a delete occurs when a timeout expires)
For the read/write/read_all operations, you have to pass a template to the tuple space, which will be matched with the tuples present in the space. You can use nil as a wildcard when matching. Below are some examples of matches and non-matches:
- [:add, 1, 2] matches [:add, 1, 2]
- [:token, "gyuioasdg567890knhu"] matches [:token, nil]
- [1,2,3,4,5] matches [nil,nil,nil,nil,nil]
- [:token, :good, :friday] does not match [:token]
- [:add, 4, 5] does not match [:add, 4, 5, 6]
- [:renew] matches [nil]
The Rinda library has a Tuple class which is basically a thin wrapper around an array or a hash:
require 'rinda/rinda'
tuple1 = Rinda::Tuple.new([:add, 2, 4, 5])
puts "We created a tuple of size: #{tuple1.size}"
tuple2 = Rinda::Tuple.new({'a' => 'b', 'c' => 'd'})
puts "We created a tuple of size: #{tuple2.size}"
The library also ships with a Template class that you can use to match tuples:
Template.new([:foo, 5]).match Tuple.new([:foo, 5]) # => true Template.new([:foo, nil]).match Tuple.new([:foo, 5]) # => true Template.new([String]).match Tuple.new(['hello']) # => true Template.new([:foo]).match Tuple.new([:foo, 5]) # => false Template.new([:foo, 6]).match Tuple.new([:foo, 5]) # => false Template.new([:foo, nil]).match Tuple.new([:foo]) # => false Template.new([:foo, 6]).match Tuple.new([:foo]) # => false
The library also ships with a TupleEntry class and a TemplateEntry class. These two classes add expiry and cancellation data to the basic Tuple and Template classes and are used by the Tuple Space implementation of Rinda.
Note that you will never have to use the Tuple, Template, TupleEntry, TemplateEntry classes when using Rinda. These are used internally by the library. I just wanted to cover these so that you have an idea of how Rinda is written. The code for Rinda is really simple and it can be foung in three files in the ruby source code: rinda/rinda.rb, rinda/tuplespace.rb, and rinda/ring.rb.
The TupleSpace class
When using Rinda, the one class that you will deal with is the TupleSpace class. It implements the 5 methods we talked about earlier: write, take, read, read_all, and notify.
It is very easy to use:
require 'rinda/tuplespace'
ts = Rinda::TupleSpace.new
DRb.start_service('druby://localhost:1234', ts)
DRb.thread.join
It really takes only 4 lines of code! On the second line, we are creating the tuple space. On the third line, we start the DRb service and put our tuple space at the following drb url: ‘druby://localhost:1234′. Finally, the last line joins the thread. Save these 4 lines of code in tuplespace.rb, just run it with: ruby tuplespace.rb. Now you can start writing agents that write or read to the tuple space that you are hosting at port 1234.
require 'rinda/tuplespace'
DRb.start_service
ts = Rinda::TupleSpaceProxy.new(DRbObject.new_with_uri('druby://localhost:1234'))
ts.write([:add, 1, 2])
ts.write([:add, 2, 3])
all = ts.read_all([:add, nil,nil])
puts all.size # => 2
tuple = ts.take([:add, nil, nil])
puts tuple.inspect # => [:add, 1, 2]
tuple = ts.take([:add, nil, nil])
puts tuple.inspect # => [:add, 2, 3]
all = ts.read_all([:add, nil,nil])
puts all.size # => 0
Save this code in a file called agent.rb and run it with ruby agent.rb. You should get the following output:
2 [:add, 1, 2] [:add, 2, 3] 0
RingServer
Rinda also ships with an implementation of a ring server (which can be found in rinda/ring.rb in the ruby source). A RingServer allows a Rinda::TupleSpace to be located via UDP broadcasts. It allows DRb services (such as Tuple Spaces) to be found automatically by clients or agents.
If we want our TupleSpace to be found automatically using a RingServer, a better way to start it is using the following code:
require 'rinda/ring' require 'rinda/tuplespace' DRb.start_service ts = Rinda::TupleSpace.new Rinda::RingServer.new ts DRb.thread.join
If you compare this code, to the code we wrote earlier to start the tuple space, you will notice that we did not have to provide a DRb URI. We use a RingServer instead. That way, when agents wants to connect to the tuple space, they can locate the tuple space using a UDP broadcast message. Of course, all of this is hidden from you and all you have to write to start using this tuple space is:
require 'rinda/ring' DRb.start_service ts = Rinda::RingFinger.primary ts.write([:add, 1,2])
While you can use the primary tuple space directly to do your work. It is generally used to hold a tuple space that will serve as a name server to advertise DRb services. Other tuple spaces can register with this ring server to advertise their services and clients can ask the ring server which services are available.
To register itself as a service, a client writes a tuple to the tuple space that maches the format: [:name, class, the DRBObject to register, a description of the service]. For example, a tuple space would register by writing the following tuple on the Ring Server: [:name, :TupleSpace, tuplespace_object, 'Tuple Space'].
Rinda comes with a RingProvider class which makes it easy to provider a service and register with the ring server:
require 'rinda/ring' require 'rinda/tuplespace' DRb.start_service ts = Rinda::TupleSpace.new provider = Rinda::RingProvider.new :TupleSpace, ts, 'Tuple Space used to do math' provider.provide DRb.thread.join
To find services, a client/agent simply has to look at the tuples in the ring server:
require 'rinda/ring'
DRb.start_service
ring_server = Rinda::RingFinger.primary
all_services = ring_server.read_all([:name, nil,nil,nil])
puts "Found #{all_services.size} services."
all_services.each do |svc|
puts "\nService Name: #{svc[1]} \nService Description: #{svc[3]}"
end
As you can see, Rinda makes it easy to create tuple spaces and advertise them using a ring server. Keep in mind that you can register any DRb service on the ring server, not just tuple spaces.
Conclusion
Rinda provides an interesting paradigm to distributed computing which is becoming more important because chip manufacturers have stopped increasing the speed of their processors and are instead shipping chips with many cores. This will require a shift in the way we write software. Software developers will need to write applications that can easily be distributed across many cores if they want to take advantage of these new chips. For an interesting paper on the subject, check out ‘The free lunch is over’ by Herb Sutter.
Send Twitter, IM, Email, or SMS messages from Erlang
Are you writing the next killer application in Erlang? Are you finding it hard to send messages on different communication channels due to a lack of supported libraries? In this tutorial, we will show you how you can use erlang and messagepub to send messages on email, IM, Google Chat, Twitter, or SMS. You can even make phone calls from erlang in one line of code.
I’ve written a small gen_server node to interact with the messagepub API. In order to use this code, you will need to sign up for messagepub and obtain an API key.
Once you have your API Key, it’s almost too easy:
- Get the messagepub.erl file from the messagepub-erlang project on github.
- Start an erlang shell and compile the messagepub module: c(messagepub).
- Start the gen_server with your API Key: messagepub:start_link(“API KEY”).
- Send messages as you please:
messagepub:send("email","joe@example.com", "hello joe").
messagepub:send("twitter", "the_real_shaq", "hi shaq!").
messagepub:send("gchat", "example@gmail.com", "Hello friend").
messagepub:send("aim", "username", "Saying hi from erlang").
messagepub:send("sms", "1234567890", "Hi my SMS friend").
messagepub:send("phone", "1234567890", "Hello on the phone").
That’s it. Now go write that killer application!
Rate Limit Increase
Today, we’ve increased our rate limit from 50 requests per hour to 100 requests per hour.
Enjoy!
Litmus uses messagepub for IM notifications
Litmus is a web application that makes cross-browser compatibility testing easier by showing you exactly how your designs look on every platform, across every popular web browser.

Starting this week, Litmus started sending alert notifications to their users when their tests have completed. They are using messagepub to send their Gtalk and AIM alerts.
This is what they had to say about messagepub on their blog:
If you’re building your own web applications, you might be interested to know that we’re using MessagePub for our Gtalk and AIM notifications. They have a great API that makes it easy to start sending custom IM alerts without needing to maintain your own bots.
We’ve deployed custom bots for Litmus so that they can use their own username on Gtalk and AIM to notify their users. If you are interested in having custom-bots for your application, send us an email at info [at] messagepub dot com.
New-Feature: Use your own Twitter username
Up until now, when you used messagepub to send out Twitter messages, the messages were sent out from the @messagepub user on Twitter. We’ve just released a new feature that lets you send Twitter messages from your own account on Twitter.
To enable this feature on your account, login to messagepub and go to your account settings page. There, you should find an option to link your twitter account with messagepub.
This is done via Twitter’s new OAuth API so you do not have to give us your username and password. When you click on the ‘Link your Twitter Account’ link. You will be redirected to a web page on Twitter.com asking you to authorize messagepub to send messages on your behalf. Make sure you login to Twitter with the username that you want to link to the messagepub account.
Once you’ve authorized access to messagepub, you will be redirected to messagepub.com and from then on every-time you use the messagepub API to send out messages, they will be sent from the twitter username you linked to your account.
This is available to both Paid and Free accounts.
How-To: Rack Middleware for API Throttling
I will show you a technique to impose a rate limit (aka API Throttling) on a Ruby Web Service. I will be using Rack middleware so you can use this no matter what Ruby Web Framework you are using, as long as it is Rack-compliant.
Introduction to Rack
There are plenty of great resources to learn the basic of Rack so I will not be explaining how Rack works here but you will need to understand it in order to follow this post. I highly recommend watching the three Rack screencasts from Remi to get started with Rack.
Basic Rack Application
First, make sure you have the thin webserver installed.
sudo gem install thin
We are going to use the following ‘Hello World’ Rack application to test our API Throttling middleware.
use Rack::ShowExceptions
use Rack::Lint
run lambda {|env| [200, { 'Content-Type' => 'text/plain', 'Content-Length' => '12' }, ["Hello World!"] ] }
Save this code in a file called config.ru and then you can run it with the thin webserver, using the following command:
thin --rackup config.ru start
Now you can open another terminal window (or a browser) to test that this is working as expected:
curl -i http://localhost:3000
The -i option tells curl to include the HTTP-header in the output so you should see the following:
$ curl -i http://localhost:3000 HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 12 Connection: keep-alive Server: thin 1.0.0 codename That's What She Said Hello World!
At this point, we have a basic rack application that we can use to test our rack middleware. Now let’s get started.
Redis
We need a way to memorize the number of requests that users are making to our web service if we want to limit the rate at which they can use the API. Every time they make a request, we want to check if they’ve gone past their rate limit before we respond to the request. We also want to store the fact that they’ve just made a request. Since every call to our web service requires this check and memorization process, we would like this to be done as fast as possible.
This is where Redis comes in. Redis is a super-fast key-value database that we’ve highlighted in a previous blog post. It can do about 110,000 SETs per second, about 81,000 GETs per second. That’s the kind of performance that we are looking for since we would not like our ‘rate limiting’ middleware to reduce the performance of our web service.
Our Rack Middleware
We are assuming that the web service is using HTTP Basic Authentication. You could use another type of authentication and adapt the code to fit your model.
Our rack middleware will do the following:
- For every request received, increment a key in our database. The key string will consists of the authenticated username followed by a timestamp for the current hour. For example, for a user called joe, the key would be: joe_2009-05-01-12
- If the value of that key is less than our ‘maximum requests per hour limit’, then return an HTTP Response with a status code of 503, indicating that the user has gone over his rate limit.
- If the value of the key is less than the maximum requests per hour limit, then allow the user’s request to go through.
Redis has an atomic INCR command that is the perfect fit for our use case. It increments the key value by one. If the key does not exist, it sets the key to the value of “0″ and then increments it. Awesome! We don’t even need to write our own logic to check if the key exists before incrementing it, Redis takes care of that for us.
r = Redis.new
key = "#{auth.username}_#{Time.now.strftime("%Y-%m-%d-%H")}"
r.incr(key)
return over_rate_limit if r[key].to_i > @options[:requests_per_hour]
If our redis-server is not running, rather than throwing an error affecting all our users, we will let all the requests pass through by catching the exception and doing nothing. That means that if your redis-server goes down, you are no longer throttling the use of your web service so you need to make sure it’s always running (using monit or god, for example).
Finally, we want anyone who might use this Rack middleware to be able to set their limit via the requests_per_hour option.
The full code for our middleware is below. You can also find it at github.com/dambalah/api-throttling.
require 'rubygems'
require 'rack'
require 'redis'
class ApiThrottling
def initialize(app, options={})
@app = app
@options = {:requests_per_hour => 60}.merge(options)
end
def call(env, options={})
auth = Rack::Auth::Basic::Request.new(env)
if auth.provided?
return bad_request unless auth.basic?
begin
r = Redis.new
key = "#{auth.username}_#{Time.now.strftime("%Y-%m-%d-%H")}"
r.incr(key)
return over_rate_limit if r[key].to_i > @options[:requests_per_hour]
rescue Errno::ECONNREFUSED
# If Redis-server is not running, instead of throwing an error, we simply do not throttle the API
# It's better if your service is up and running but not throttling API, then to have it throw errors for all users
# Make sure you monitor your redis-server so that it's never down. monit is a great tool for that.
end
end
@app.call(env)
end
def bad_request
body_text = "Bad Request"
[ 400, { 'Content-Type' => 'text/plain', 'Content-Length' => body_text.size.to_s }, [body_text] ]
end
def over_rate_limit
body_text = "Over Rate Limit"
[ 503, { 'Content-Type' => 'text/plain', 'Content-Length' => body_text.size.to_s }, [body_text] ]
end
end
To use it on our ‘Hello World’ rack application, simply add it with the use keyword and the :requests_per_hour option:
require 'api_throttling'
use Rack::Lint
use Rack::ShowExceptions
use ApiThrottling, :requests_per_hour => 3
run lambda {|env| [200, {'Content-Type' => 'text/plain', 'Content-Length' => '12'}, ["Hello World!"] ] }
That’s it! Make sure your redis-server is running on port 6379 and try making calls to your api with curl. The first 3 calls will be succesful but the next ones will block because you’ve reached the limit that we’ve set:
$ curl -i http://joe@localhost:3000 HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 12 Connection: keep-alive Server: thin 1.0.0 codename That's What She Said Hello World! $ curl -i http://joe@localhost:3000 HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 12 Connection: keep-alive Server: thin 1.0.0 codename That's What She Said Hello World! $ curl -i http://joe@localhost:3000 HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 12 Connection: keep-alive Server: thin 1.0.0 codename That's What She Said Hello World! $ curl -i http://joe@localhost:3000 HTTP/1.1 503 Service Unavailable Content-Type: text/plain Content-Length: 15 Connection: keep-alive Server: thin 1.0.0 codename That's What She Said Over Rate Limit
The code is up on github if you want to use it.
New: C# Helper Library
C# Developers, we’ve got you covered now!
You can now start sending multichannel messages on AIM, Google Chat, Email, Phone, SMS, and Twitter with one simple API.
We wrote a helper library for C# that makes it very easy to start using the messagepub API from your C# programs. The following video is a quick demo on how to use the library:
If you want to take a look at the source code, it is open-source and hosted on github: github.com/dambalah/messagepub-csharp. You can download the DLL for the library from our documentation page. Please report any issues you might have with the library on our Google group.
Leave a Comment


