Akara is specialized for delivering data services, and to a particular set of architectural best practices for doing so. Two of the key points are:
- RESTful principles (to maximize the utility, reuseability and integration of resources)
- Service composition, and its corollary, divide-and-conquer.
In "the akara way", complex services are combinations of simpler services, which might in turn be combinations of even simpler services, all the way down to the unit transform, which is a simple, independent (i.e. not coupled to other services), highly cohesive conversion from a simple data input to a simple data output.
These combinations of simpler services in Akara are called "Pipelines".
Pipelines
A pipeline is a feature that coordinates the action of services. A pipeline is a combination of stages, and there are several types of stages.
Synchronous pipe
A series of transforms which are all invoked in order, with one input and one output. For example, the following illustrates a synchronous pipe combining two services into a single, logical service:
request ---> service1 ---> service2 ---> response
Sample use-cases:
- Chained data transforms (e.g. converting from a spreadsheet to CSV and then from CSV to a CALS table)
- Validation (e.g. service1 generates XML, which is validated by service2; service 2 is identity transform if valid, and issues 500 code + error report if not)
Asynchronous tee
A construct in which the service that handles the request also invokes another request ansynchronously (i.e. such that it's not required to complete the service and generate the response). The following illustrates an example:
request ---> service1 ---> response
|
|
|
v
service2service2 must be an HTTP POST (in almost every case the point of an asynchronous tee is for the side-effect, so Akara enforces this as a POST operation; PUT, DELETE and other non-idempotent methods were considered and rejected)
For now the only case supported is that sevice2 is invoked after completion of service 1. The service1 response body becomes the HTTP POST body to service2. The service1 response code becomes a new header X-AKARA-ASYNC-RESPONSE-STATUS. All headers from the service1 response become headers to the service2 request after they've been prepended with X-AKARA-ASYNC-RESPONSE-. The service2 request also contains a cumulative header X-AKARA-ASYNC-STACK, appended with service1's ID. Akara will forbid an asynchronous target service invocation if its ID already appears on this stack.
Sample use-cases:
- Updating an index (e.g. service1 is a document repository update and service2 is an index update)
Specifying pipelines
- You can specify a synchronous pipeline in config, through input headers or output headers.
- Configuration: you specify a service (the succeeding) to operate on the output of another service (the preceding)
- Input headers: the user's request can specify in the request headers a sequence of succeeding service to operate on the input of the preceding service
- Input headers: the preceding service can add in the response headers a sequence of succeeding service to operate on the response
request ---> service1 ---> service2 ---> service3 ---> response
- service1 is the preceding for service2 and service3. service1 is the immediately preceding for service2.
Implementation example (non-normative; purely for discussion)
Registering a simple pipeline stage:
@simple_pipeline_stage(service_id, listen_for=[preceding_id1, preceding_id2]) #the listen_for list is an an or of the list items
func(environ, body):
return response_obj #includes headers & new body
Background info: Web triggers
Asynchronous tees are basically "Web triggers". Web triggers (AKA Web hooks) are a translation of the idea behind database triggers to the Web. A Web trigger is a declaration that when one HTTP interaction occurs (the triggering event or Web stimulus), another automatically follows (the Web response). In its purest form Web trigger architecture excludes consideration of what actual mechanism detects the stimulus and makes the response invocation. It's an abstraction that can be expressed with some useful formality, while covering many actual approaches to implementation. In this abstract form Web triggers are a very powerful way to describe the interactions of advanced applications of the Web, going beyond the typical browser request->Web server response. Web triggers are a way to describe the richer interactions of the social Web, cloud computing, and many other buzzwords.
OK, but really, how do they work
Abstractions only carry so far, so this is a likely general expression of a Web trigger mechanism. The abstract idea comes from the DBMS world (triggers), but in most cases the implementation would owe more to the programming world, in the form of the [http://en.wikipedia.org/wiki/Observer_design_pattern Observer design pattern].
The trigger would be managed by a control point (the dispatcher), generally as a module in a Web server. Other control points (e.g. plug-in code or remote Web services) are registered with the dispatcher. The registration information includes:
- The URL pattern for the triggers to which they subscribe
- The HTTP POST URL to be used by the dispatcher upon a triggering event
- (optional) a transform from the triggering event's POST body to the response POST body
question: what about communicating the triggering event's header info to the response end-point?
The triggering event is is an HTTP message (usually using the HTTP POST method) to the dispatcher. The dispatcher checks its registrations for any patterns matching the triggering event URL. For any matches, it applies the corresponding transforms (if any) and sends an HTTP POST to the corresponding response end-point URL.
Note: it probably makes sense to support triggers upon other triggering events, but the REST semantics re easier to think about for POST. Let's nail that down then expand
The environment for Web triggers
Web triggers operate on the information space represented by the World-Wide Web. They operate on any implementation or architectural system compatible with such an information space, including:
- RESTful Web services
- RDF or Semantic Web space
- Web 2.0 social/collaborative networks
- integrated enterprise applications wrapped with RESTful end-points
Use cases
A Web trigger is a generalization of the idea that one RESTful request can trigger another request. This covers everything from simple redirection to an operation in server code that invokes other URIs. Here are some sample use cases.
Web triggers can be used to implement plug-in systems for Web frameworks. For example, rather than having a proprietary API in Python or PHP or Java for a Weblog system plug-ins, you could use Web hooks. For example, the Weblog engine wants to invoke plug-ins when a new entry is made, in order to invoke ping-backs, update some index, etc. The Weblog engine could post a "new entry" stimulus, and these other activities would be implemented as responses. Even a plug-in could define its own triggers. For example a comment plug-in might invoke a "new comment" Web trigger, so that anti-spam and other plug-ins can be invoked.
See also
"Bright Content Design Document: Web Triggers" -- a bit dated
"Boulder Vice Versa", a proposal for a general-purpose Web query language that incorporates the ides of Web triggers
