class ImmediateManager(object): __slots__ = ('transport', ) def __init__(self, config, Transport): """Initialize the immediate delivery manager.""" # Create a transport pool; this will encapsulate the recycling logic. self.transport = TransportPool(Transport) super(ImmediateManager, self).__init__() def startup(self): """Perform startup actions. This just chains down to the transport layer. """ log.info("Immediate delivery manager starting.") log.debug("Initializing transport queue.") self.transport.startup() log.info("Immediate delivery manager started.") def deliver(self, message): result = None while True: with self.transport() as transport: try: result = transport.deliver(message) except MessageFailedException: e = sys.exc_info()[1] raise DeliveryFailedException(message, e.args[0] if e.args else "No reason given.") except TransportFailedException: # The transport has suffered an internal error or has otherwise # requested to not be recycled. Delivery should be attempted # again. transport.ephemeral = True continue except TransportExhaustedException: # The transport sent the message, but pre-emptively # informed us that future attempts will not be successful. transport.ephemeral = True break return message, result def shutdown(self): log.info("Immediate delivery manager stopping.") log.debug("Draining transport queue.") self.transport.shutdown() log.info("Immediate delivery manager stopped.")
class DynamicManager(object): __slots__ = ('workers', 'divisor', 'timeout', 'executor', 'transport') name = "Dynamic" Executor = ScalingPoolExecutor def __init__(self, config, transport): self.workers = config.get('workers', 10) # Maximum number of threads to create. self.divisor = config.get( 'divisor', 10 ) # Estimate the number of required threads by dividing the queue size by this. self.timeout = config.get('timeout', 60) # Seconds before starvation. self.executor = None self.transport = TransportPool(transport) super(DynamicManager, self).__init__() def startup(self): log.info("%s manager starting up.", self.name) log.debug("Initializing transport queue.") self.transport.startup() workers = self.workers log.debug("Starting thread pool with %d workers." % (workers, )) self.executor = self.Executor(workers, self.divisor, self.timeout) log.info("%s manager ready.", self.name) def deliver(self, message): # Return the Future object so the application can register callbacks. # We pass the message so the executor can do what it needs to to make # the message thread-local. return self.executor.submit(partial(worker, self.transport), message) def shutdown(self, wait=True): log.info("%s manager stopping.", self.name) log.debug("Stopping thread pool.") self.executor.shutdown(wait=wait) log.debug("Draining transport queue.") self.transport.shutdown() log.info("%s manager stopped.", self.name)
class DynamicManager(object): __slots__ = ('workers', 'divisor', 'timeout', 'executor', 'transport') name = "Dynamic" Executor = ScalingPoolExecutor def __init__(self, config, transport): self.workers = config.get('workers', 10) # Maximum number of threads to create. self.divisor = config.get('divisor', 10) # Estimate the number of required threads by dividing the queue size by this. self.timeout = config.get('timeout', 60) # Seconds before starvation. self.executor = None self.transport = TransportPool(transport) super(DynamicManager, self).__init__() def startup(self): log.info("%s manager starting up.", self.name) log.debug("Initializing transport queue.") self.transport.startup() workers = self.workers log.debug("Starting thread pool with %d workers." % (workers, )) self.executor = self.Executor(workers, self.divisor, self.timeout) log.info("%s manager ready.", self.name) def deliver(self, message): # Return the Future object so the application can register callbacks. # We pass the message so the executor can do what it needs to to make # the message thread-local. return self.executor.submit(partial(worker, self.transport), message) def shutdown(self, wait=True): log.info("%s manager stopping.", self.name) log.debug("Stopping thread pool.") self.executor.shutdown(wait=wait) log.debug("Draining transport queue.") self.transport.shutdown() log.info("%s manager stopped.", self.name)
class FuturesManager(object): __slots__ = ('workers', 'executor', 'transport') def __init__(self, config, transport): self.workers = config.get('workers', 1) self.executor = None self.transport = TransportPool(transport) super(FuturesManager, self).__init__() def startup(self): log.info("Futures delivery manager starting.") log.debug("Initializing transport queue.") self.transport.startup() workers = self.workers log.debug("Starting thread pool with %d workers." % (workers, )) self.executor = futures.ThreadPoolExecutor(workers) log.info("Futures delivery manager ready.") def deliver(self, message): # Return the Future object so the application can register callbacks. # We pass the message so the executor can do what it needs to to make # the message thread-local. return self.executor.submit(partial(worker, self.transport), message) def shutdown(self, wait=True): log.info("Futures delivery manager stopping.") log.debug("Stopping thread pool.") self.executor.shutdown(wait=wait) log.debug("Draining transport queue.") self.transport.shutdown() log.info("Futures delivery manager stopped.")