= gossamer

A microframework to spin websites out of distributed, lightweight, ephemeral resources.

Home page: http://gossamer.rubyforge.com


== Description

Gossamer is a web framework that emphasizes the use of distributed, independent resources. With Gossamer, you construct websites out of a network of lightweight objects that manage particular resources. Resources can utilize other resources through fault-tolerant, loosely coupled RESTful[http://en.wikipedia.org/wiki/Representational_State_Transfer] communications. Resource brokers manage the resource objects, storing them in a distributed cache (eg, <tt>memcache</tt>). Resources can easily serve their content in multiple formats, such as HTML, Atom, and RDF.

Gossamer is intended to be a useful platform for aggregators, mashups, web services, implementing the semantic web, and other applications that depend on external network resources rather than internal databases.


== Features

* Object-oriented "resource" view of data encourages encapsulation, and maps nicely to the semantic/programmable web.

* Loosely-coupled connections between resources encourages both cooperation and error correction.

* Resources can be updated automatically.

* Resources are stored (frozen) in a distributed cache, accessible by multiple processes on the same machine or multiple machines.


== Overview

Instead of implementing models, controllers, views, and server scripts, you implement <em>resources, brokers</em>, and <em>servers.</em>

A server creates a broker, and a broker manages one or more resources. Each resource is fully responsible for creating, updating, and rendering its data.

A small site may have only one server and a few resources; a large site may have many servers, each responsible for a set of resources.


=== Resources

<em>Resources</em> are independent entities that encapsulate the initialization, updating, and rendering of some kind of information. The implementation of a resource depends on its complexity and the data it represents.

Some examples of resources:

* The copyright terms for a site. This would be static text, perhaps with some links to contacts at an organization.

* A report based on a query of a local database.

* The presence information for a particular user, using several APIs to fetch that information from various services.

* The aggregation of several blogs.

Each resource has three parts, or phases:

initialize:: The resource configures itself, and any data that is static and quickly generated is stored in instance variables.

update:: The resource performs any long-running tasks, like complex queries or accessing remote data. If the resource has set its <tt>update_frequency</tt> and implemented an <tt>#update</tt> method, this updating phase will be performed again at that frequency.

render:: The resource renders itself in the requested format. Often this is HTML, but it could be Atom, XML, or other formats. A resource "publishes" its formats simply by implementing the appropriate method: <tt>#to_html</tt> for HTML, <tt>#to_atom</tt> for Atom, and so on. If a resource doesn't implement any rendering methods, it is only visible to other resources, not to web servers.

A resource may use other resources. For example, a resource that represents the presence info of a person may depend on other resources that represent particular presence services, such as AIM, Skype, and Twitter. The general presence resource will make requests of the individual presence services, combining that data into a single resource.

A website may implement all its "pages" as Gossamer resources, each of which may depend on other resources to gather and render the final HTML.

Here is a small example resource that simply creates and renders a static string:

class MyResource < Gossamer::Resource

def update
@text = "Some information about something."
end

def to_html
@text
end

end


=== Brokers

A <em>broker</em> is the go-between for resources. A broker can be asked to store a resource at a particular path (a local URI) for later access by that broker or another broker who is configured similarly. Once the resource is stored in the distributed cache, it is "frozen" and inactive. When a broker is asked for a resource, the resource is thawed out, and either returned to the caller as an object or rendered in a particular format (eg, HTML, Atom, XML).

There can be multiple brokers, and even brokers on different machines. Any broker using the same cache configuration can access any resource saved into the cache by any broker.

If a broker is asked to store a resource that wants to be updated, the resource is scheduled for updates according to its configured frequency. When the update time comes, the resource is pulled out of the cache, its update method is called, and the resource is put back into the cache. (There is currently no notification mechanism, so a resource that depends on another updating resource will have to update itself slightly after the first resource has updated.)

Here is a simple broker:

class MyBroker < Gossamer::Broker

def initialize
super(:cache_address => "localhost:11211", :cache_namespace => "text")
end

end


=== Servers

A server isn't an actual object class in Gossamer, but just a convention of how to create a broker and resources, and, optionally, hook in a Rack application. Here's a simple server that uses the resource and broker examples above, and connects a Mongrel web server into the broker.

broker = MyBroker.new
broker["/info"] = MyResource.new
app = Rack::Builder.new { run broker }.to_app
Rack::Handler::Mongrel.run(app, :Port => 3000)

When this example is run, a HTTP request for "http://localhost:3000/info" will show the sample text.


== Limitations & problems

* Data flows only one way: from a resource to the user or into another resource. There is currently no facility for submitting forms or modifying data inside resources. Nor are there any sort of notifications. This means most resources will work on a polling model, which is suboptimal.

* Performance is undetermined. It might be fast enough for you. It might be really slow.

* Because Gossamer was built as a research experiment and not a specified, production system, there are no unit or functional tests.

* Gossamer is not a full-stack framework. It knows nothing of databases, configuration, or templating systems.


== Synopsis

See the <tt>examples/</tt> directory for some sample servers and resources.


== Requirements

* ruby 1.8.6 or higher
* Rack[http://rack.rubyforge.org]
* a Rack-compatible web server
* memcached[http://blog.evanweaver.com/files/doc/fauna/memcached/] (which requires libmemcached[http://tangent.org/552/libmemcached.html] and memcached[http://danga.com/memcached])
* Scheduler (<tt>sudo gem install scheduler</tt>)

If you install from the Gossamer gem, you'll get all these for free, except for <tt>libmemcached</tt>.


== Installation

sudo gem install gossamer


== Author

John Labovitz

[email protected]


== License

(The BSD License)

Copyright (c) 2008, John Labovitz. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY JOHN LABOVITZ "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL JOHN LABOVITZ BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.