Jim Suchy recently laid down some basics of Rinda in his blog Rinda
101. I would like to build on that and talk a little about the
architecture. A rindlet
is some
process that is listening to the rindlet
tuplespace
, waiting to
read or take messages.
When a tuple
is written to the tuplespace
,
the rindlet
will look at the message and determine if this
is a tuple
of interest to it. If it is, then the engines
warm up and the tuple
gets processed by the logic in the
rindlet
. Otherwise, the rindlet
will take a
pass, and wait for another message to be written to the
tuplespace
.
These rindlets
are autonomous and asynchronous pieces of
business logic that are messaging across many systems, or across many
modules of the same system. We deploy them as daemon processes.
As a proof of concept, Jim and I built a trivia game, with two different interfaces. One will be a rich client, developed using a Ruby framework called Limelight, and one will be a command line Ruby client.
Lets look at the code in the rich client application which updates the question on a screen for all the trivia participants to answer.
1require 'rinda_client'
2
3module CurrentQuestion
4
5 def start_update_question
6 Thread.new(self) do |current_question|
7 while true
8 update_question(current_question)
9 sleep 1
10 end
11 end
12 end
13
14 def question_update(current_question)
15 client = Rinda::RindaClient.new
16 tuple = client.read ["questioner", "response", "current question"], 1
17
18 unless tuple.nil?
19 current_question.text = tuple[3]
20 current_question.update
21 end
22
23 end
24
25end
This code spawns a thread to sit and listen to the rinda
server to see if there are any new questions. The questioner
rindlet
will post a tuple
called “current
question” every 30 seconds to change the question. After we create a
rinda
client, we set up the match criteria for the
tuples
we are interested in.
1tuple = client.read ["questioner", "response", "current question"], 1
We want to read all tuples
that match the fourth parameter,
which is the question text to display on the screen:
1["questioner", "response", "current question"]
2current_question.text = tuple[3]
This example shows you can integrate your application with rinda. Your
application can listen to the tuplespace
to get messages
that are relevant only to it.
If you are writing a rails application, then you would have to use the view helper periodically call remote, since rails is single threaded, it isn’t as easy as firing a thread and moving on.
Lets start with some rindlet
code.
1require "rindlet"
2
3class Questionerrindlet < Rinda::rindlet
4
5 def run
6 with_standard_tuple("questioner", "next question") do |tuple|
7 game = Game.active_game
8
9 question_text = nil
10 if game.nil?
11 question_text = "No active game!"
12 else
13 question = game.next_question
14 question_text = question.nil? ? "No more questions!" : question.text
15 end
16
17 @rinda_client.write(["questioner", "response", "current question", "#{question_text}"])
18 end
19 end
20
21end
First, the with_standard_tuple
method is a standard
wrapper to match elements and take the tuple
if it matches and
pass it into the block. Alternatively, you could do:
1tuple = client.take [“questioner”, “request”, “next question”]
The rindlet
itself then gets the next question from the
game, and writes a tuple
back to the
tuplespace
with a response, containing the question text.
Notice the code in this rindlet
feels like
MVC controller code.
Since rinda
is a technology and notation of communication,
it will just call the business logic in the models and respond to the
actions performed if needed. rindlets
often behave as
system level controllers, not specific to any one application.
I have had lots of fun getting rindlets
to work, and they
have been an interesting tool for decoupling business logic from any
specific application.
Happy coding!