witten
/
luminotes
Archived
1
0
Fork 0
This repository has been archived on 2023-12-16. You can view files and clone it, but cannot push or open issues or pull requests.
luminotes/controller/Updater.py

73 lines
2.6 KiB
Python
Raw Normal View History

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
2007-08-09 19:44:26 +00:00
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