Imagine that you're writing a program to roll dice. This should not be difficult. For reasons that evade me at the moment, it seems that shortly after dicovering rand(), almost every programmer has decided that they want to write simulate rolling dice. Perhaps it's because so many coders are also gamers, (or gamers are also coders, who can say?) but the reasons are unimportant. You want to reinvent the "Hello, world!" of randomization.
Stung by the implication that your dice roller will be just another reinvention of tired code, you are spurred to make it something more. You need to justify using a computer rather than 6 ounces of plastic to produce your random numbers, maybe. Fair enough. What don't dice do? Well, they don't keep track your old rolls, and they can't compare themselves to other rolls automatically. They can't match themselves up to a Yatzee board or the Tipped Candle Table (Underground, Non-combat) and return the results for you. But most importantly, you realize, they can't be shown to someone across the world while you're playing Yatzee in IRC.
Of course, you've decided to program this in Ruby, so you need a way to have the dice roller itself running, and have little worker drones suplicate themselves to it in order to get answers.
After a little reading, or maybe coffee with a Ruby guru, you discover the magic of DRb. "Aha!" you think, "Just what I need!" Until you've coded on your increasing un-simple dice roller for a while and discover that there are certain concurrency issues. It is, of course, unacceptable for both players to enter a Triple Yahtzee at the same time. So you sigh and resign yourself to learning concurrent programming.
Except, halfway through understand what Mutex is for, you stumble upon a wonderful package called Rinda and everything is suddenly sweetness and light. Not only do you no longer have to pass clunky druby:// URIs around on the command line, you don't have to worry about the dreaded Double Triple Yahtzee issue.
Of course, now you need to do a bunch of message passing, in weird little arrays, inexplicably called Tuple, and then there's the gotcha of needing not only to name each client, but also every message, and keep track of it all.
This is where RingService comes in. RingService is an abstraction of RingServer (by ). In basic terms, you create a RingService object with a class, and (for niceness sake) a human readable name. Then you tell the RingService to start_daemonized with a block that will process requests. It'll return immediately from your request, and spin off in it's own little daemon process, dancing merrily in the background. It'll even start it's own RingServer if there isn't one running.
Now you can create RingClient classes, and tell them to put requests to the server, and get the answers. Easy as that. The Server will process them, and the answers will be ready for the clients. You can handle your own batches of requests, if you want, but if you always get the answers to each question as you put them, you don't really need to worry about it.
What you can do, now, is have your Yatzhee game set up in a RingServer, and then all the worshipful client programs put their requests for rolls and for scoring and for inspecting the sneaky rolls of the opponents and get the responses from the increasingly OS-like Yahtzee server.
And for (almost) free, you get the power and wonder of distributed programming. You could set the Yahtzee server up on the monolithic PDP-11 you nabbed from two jobs ago, and then play Yahtzee on your laptop over your wireless network against your dog on his K-9 Luggable.
(Of course, you might also use it to handle seperate sessions in a web server or something mundane like that. Sigh.)
In the future, you'll be able to give a ProxyRingService a class, and be able to create a ProxyRingClient with the same class. Then you'll be able to use the ProxyRingClient as if it were a member of that class local to your program, even though it might be in a computer running across the room, or under your bed or something.
Further musing on the future include a Tenacious server, that would refuse to be unlisted until it terminates itself. At present, any class with a little Rinda savvy could just take it's registration from the main RingServer, and then no one would be able to find it. This is probably not what you want. (Incidentally, for all it's godlike power, the RingService server will quietly expire should anyone put a request to :terminate.)
Another possible future plan is Multi-Servers - sort of like a hydra, they'd have many heads to do their work with. Some kind of manager would keep them in line, killing any that got to fat or rowdy, and starting new ones if there's more work than the current stable can handle.