824882a1d8
Now it's configurable in the common settings.
73 lines
2.6 KiB
Python
73 lines
2.6 KiB
Python
from Queue import Queue, Empty
|
|
|
|
|
|
TIMEOUT_SECONDS = 10.0
|
|
|
|
|
|
def wait_for_update( function ):
|
|
"""
|
|
A decorator that passes a "queue" keyword arugment to its decorated function, calls the function,
|
|
and then blocks until an asynchronous response comes back via the Queue. When a response is
|
|
received, wait_for_update() returns it.
|
|
|
|
For this decorator to be useful, you should use it to decorate a function that fires off some
|
|
asynchronous action and then returns immediately. A typical way to accomplish this is by using
|
|
the @async decorator after the @wait_for_update decorator.
|
|
"""
|
|
def get_message( *args, **kwargs ):
|
|
queue = Queue()
|
|
|
|
kwargs[ "queue" ] = queue
|
|
function( *args, **kwargs )
|
|
|
|
# wait until a response is available in the queue, and then return that response
|
|
try:
|
|
return queue.get( block = True, timeout = TIMEOUT_SECONDS )
|
|
except Empty:
|
|
return { "error": u"A timeout occurred when processing your request. Please try again or contact support." }
|
|
|
|
return get_message
|
|
|
|
|
|
def update_client( function ):
|
|
"""
|
|
A decorator used to wrap a generator function so that its yielded values can be issued as
|
|
updates to the client. For this to work, the generator function must be invoked with a keyword
|
|
argument "queue" containing a Queue where the result can be put().
|
|
|
|
Also supports catching Validation_error exceptions and sending appropriate errors to the client.
|
|
|
|
Note that this decorator itself is a generator function and works by passing along next()/send()
|
|
calls to its decorated generator. Only yielded values that are dictionaries are sent to the
|
|
client via the provided queue. All other types of yielded values are in turn yielded by this
|
|
decorator itself.
|
|
"""
|
|
def put_message( *args, **kwargs ):
|
|
# look in the called function's kwargs for the queue where results should be sent
|
|
queue = kwargs.pop( "queue" )
|
|
|
|
try:
|
|
generator = function( *args, **kwargs )
|
|
message = None
|
|
|
|
while True:
|
|
result = generator.send( message )
|
|
|
|
if isinstance( result, dict ):
|
|
queue.put( result )
|
|
message = ( yield None )
|
|
else:
|
|
message = ( yield result )
|
|
except StopIteration:
|
|
return
|
|
except Exception, error:
|
|
# TODO: might be better to use view.Json instead of calling to_dict() manually
|
|
if hasattr( error, "to_dict" ):
|
|
result = error.to_dict()
|
|
queue.put( result )
|
|
else:
|
|
queue.put( { "error": u"An error occurred when processing your request. Please try again or contact support." } )
|
|
raise
|
|
|
|
return put_message
|