Package lamson :: Module routing
[hide private]
[frames] | no frames]

Module routing

source code

The meat of Lamson, doing all the work that actually takes an email and makes sure that your code gets it.

The three most important parts for a programmer are the Router variable, the StateStorage base class, and the @route, @route_like, and @stateless decorators.

The lamson.routing.Router variable (it's not a class, just named like one) is how the whole system gets to the Router. It is an instance of RoutingBase and there's usually only one.

The lamson.routing.StateStorage is what you need to implement if you want Lamson to store the state in a different way. By default the lamson.routing.Router object just uses a default MemoryStorage to do its job. If you want to use a custom storage, then in your config/boot.py (or config/testing.py) you would set lamson.routing.Router.STATE_STORE to what you want to use.

Finally, when you write a state handler, it has functions that act as state functions for dealing with each state. To tell the Router what function should handle what email you use a @route decorator. To tell the Route that one function routes the same as another use @route_like. In the case where a state function should run on every matching email, just use the @stateless decorator after a @route or @route_like.

If at any time you need to debug your routing setup just use the lamson routes command.

Routing Control

To control routing there are a set of decorators that you apply to your functions.

* @route -- The main routing function that determines what addresses you are interested in. * @route_like -- Says that this function routes like another one. * @stateless -- Indicates this function always runs on each route encountered, and no state is maintained. * @nolocking -- Use this if you want this handler to run parallel without any locking around Lamson internals. SUPER DANGEROUS, add @stateless as well. * @state_key_generator -- Used on a function that knows how to make your state keys for the module, for example if module_name + message.route_to is needed to maintain state.

It's best to put @route or @route_like as the first decorator, then the others after that.

The @state_key_generator is different since it's not intended to go on a handler but instead on a simple function, so it shouldn't be combined with the others.

Classes [hide private]
  StateStorage
The base storage class you need to implement for a custom storage system.
  MemoryStorage
The default simplified storage for the Router to hold the states.
  ShelveStorage
Uses Python's shelve to store the state of the Routers to disk rather than in memory like with MemoryStorage.
  RoutingBase
The self is a globally accessible class that is actually more like a glorified module.
  route
The @route decorator is attached to state handlers to configure them in the Router so they handle messages for them.
  route_like
Many times you want your state handler to just accept mail like another handler.
Functions [hide private]
 
DEFAULT_STATE_KEY(mod, msg) source code
 
lamson_setting(func, key)
Simple way to get the lamson setting off the function, or None.
source code
 
has_lamson_settings(func) source code
 
assert_lamson_settings(func)
Used to make sure that the func has been setup by a routing decorator.
source code
 
attach_lamson_settings(func)
Use this to setup the _lamson_settings if they aren't already there.
source code
 
stateless(func)
This simple decorator is attached to a handler to indicate to the Router.deliver() method that it does NOT maintain state or care about it.
source code
 
nolocking(func)
Normally lamson.routing.Router has a lock around each call to all handlers to prevent them from stepping on eachother.
source code
 
state_key_generator(func)
Used to indicate that a function in your handlers should be used to determine what they key is for state storage.
source code
Variables [hide private]
  ROUTE_FIRST_STATE = 'START'
  LOG = logging.getLogger("routing")
  Router = RoutingBase()
  __package__ = 'lamson'
Function Details [hide private]

DEFAULT_STATE_KEY(mod, msg)

source code 

lamson_setting(func, key)

source code 

Simple way to get the lamson setting off the function, or None.

has_lamson_settings(func)

source code 

assert_lamson_settings(func)

source code 

Used to make sure that the func has been setup by a routing decorator.

attach_lamson_settings(func)

source code 

Use this to setup the _lamson_settings if they aren't already there.

stateless(func)

source code 

This simple decorator is attached to a handler to indicate to the Router.deliver() method that it does NOT maintain state or care about it. This is how you create a handler that processes all messages matching the given format+captures in a @route.

Another way to think about a @stateless handler is that it is a passthrough handler that does its processing and then passes the results on to others.

Stateless handlers are NOT guaranteed to run before the handler with state.

nolocking(func)

source code 

Normally lamson.routing.Router has a lock around each call to all handlers to prevent them from stepping on eachother. It's assumed that 95% of the time this is what you want, so it's the default. You probably want everything to go in order and not step on other things going off from other threads in the system.

However, sometimes you know better what you are doing and this is where @nolocking comes in. Put this decorator on your state functions that you don't care about threading issues or that you have found a need to manually tune, and it will run it without any locks.

state_key_generator(func)

source code 

Used to indicate that a function in your handlers should be used to determine what they key is for state storage. It should be a function that takes the module_name and message being worked on and returns a string.


Variables Details [hide private]

ROUTE_FIRST_STATE

Value:
'START'

LOG

Value:
logging.getLogger("routing")

Router

Value:
RoutingBase()

__package__

Value:
'lamson'