README.textile in hayeah-ASS-0.0.1 vs README.textile in hayeah-ASS-0.0.2
- old
+ new
@@ -1,161 +1,323 @@
\ No newline at end of file
+
+Asynchronous Service Stages (ASS) is a way to
+organize distributed services by decoupling the
+what and how of computation from the when and
+where. Built on top of RabbitMQ (an implementation
+of AMQP), ASS helps you to build robust and
+scalable distributed applications.
+
+End of project pimping, let's get started.
+
+h1. Install
+
+You need
+
+(1) Erlang
+(2) RabbitMQ
+(3) AMQP gem
+
+Thread.new { EM.run }
+AMQP.start
+
+^C to exit
+
+
+h1. The Basics
+
+A service component is a ruby script that
+communicates with RabbitMQ. You need to define the
+AMQP server your ASS depends on. Something like this,
+
+
+require 'rubygems'
+require 'ass'
+AMQP.start(:host => 'localhost',
+ #:vhost => "/ass-test",
+ :logging => false) do
+ # ASS definition
+end
+
+
+To start a server
+
+server = ASS.new("echo")
+# => #<ASS::Server echo>
+
+But it doesn't do anything yet. You define the
+behaviour of the server by setting its
+callback. The callback can be a class, so that for
+each client request an object is created from the
+class to process the request. Like so,
+
+
+server.react(SomeReactorClass)
+
+
+However, often you just want something simple. The
+react method can take a block and construct an
+anonymous callback class from which the server
+creates an callback object for each request. Here
+we ask the server to react to @foo@ or @bar@.
+
+
+server.react {
+ def foo(input)
+ [:server,:foo,input]
+ end
+
+ def oof(input)
+ [:server,:oof,input]
+ end
+}
+
+
+The react method accepts for the callback either
+a Class, a Module, a block, or any object. When an
+object is used, it's considered a singleton, which
+is used to process all the requests.
+
+Now that we have a server, we need to get a client
+so to call the server. Because the call is
+asynchronous (the client doesn't wait for the
+result), to process the result when it gets back,
+we need to define callback for the client (just as
+we did for the server). For each call to the
+remote server, the result is processed at the
+client side by a method of the same name,
+
+
+client = server.client.react {
+ def foo(output)
+ p [:client,:foo,output]
+ end
+ def oof(output)
+ p [:client,:oof,output]
+ end
+}
+
+c.call(:foo,42)
+c.call(:oof,24)
+
+# [:client,:foo,[:server,:foo,42]]
+# [:client,:foo,[:server,:foo,24]]
+
+
+> ruby server.rb
+> ruby client.rb
+
+> ruby server.rb
+^C
+
+While the server is down, the requests the client
+is making is queued by the underlying message
+middleware (RabbitMQ), so in some future time when
+we restart the server, we wouldn't lose any
+request. Let's restart the server.
+
+> ruby server.rb
+
+See that the server caught up with all the pending
+requests. To increase service capacity, we can
+just increase the number of server instances.
+
+> ruby server.rb
+
+Now the load is distributed between these two
+instances. We can also start more clients to
+handle more load.
+
+> ruby client.rb
+
+You can see requests coming in from two clients.
+
+
+h1. Service Configuration
+
+-how the name of a service map to AMQP entities.
+-various options for different functional characteristics.
+
+-using routing_key
+-using reply_to
+
+
+rabbitmqctl list_exchanges
+rabbitmqctl list_queues
+
+
+h1. RPC service
+
+The RPC client provides a synchronous API to the
+asynchronous services. This is so the users of an
+ASS application don't have to bother with the
+difficulties of asynchronous programming style
+with callbacks.
+
+The RPC client is intended to be used as the
+gateway into some reliable internal
+services. While the internal services coordinated
+with ASS needs to be robust to component failures,
+there's no such requirements for gateways. It is
+ok for a gateway to fail, and fail in delivering a
+response, as long as the internal services carry
+out the task without a hitch.