"""Function for creating status-based task runner.""" from garcon import runner from garcon_contrib.dynamo_feed_status import garcon_feed_status def create(feed_name): """Create a feed status dependent task runner. The helper method simplifies the creation of a StatusRunner. It allows flows to define a create method that will reuse the feed's status name in all subsequent StatusRunner's it generates. Args: feed_name (str): Name of feed. Return: callable: Function when called returns StatusRunner object. """ def create_runner(runner_type, *args, **kwargs): """Generate a StatusRunner. The helper method simplifies the creation of a StatusRunner that is inherited from a Runner. Args: runner_type (str): Name of the base task runner (currently only 'Sync' or 'Aync') Return: StatusRunner: StatusRunner object whose base Runner class is either garcon.runner.Sync or garcon.runner.Async """ if runner_type == 'Sync': base_runner_class = runner.Sync else: base_runner_class = runner.Async class StatusRunner(base_runner_class): """A Garcon task Runner whose task execution is status dependent. A StatusRunner behaves exactly as the runner it is inheriting from, except it only executes its tasks dependent on a feed's status. Optionally, after the tasks have executed, the feed's status can be updated to a new value. Args: base_runner_class (runner.BaseRunner): Name of the runner class (currently only runner.Sync or runner.Async) Return: StatusRunner: StatusRunner object whose base Runner class is either garcon.runner.Sync or garcon.runner.Async """ def __init__( self, requisite_status=None, *args, complete_status=None, date_key='date'): """Garcon task Runner whose task execution is based on status. Args: requisite_status (str): status that a feed should be in order for a Runner to execute its tasks. If the feed has any other status for the date it is being run, it will not execute its tasks. complete_status (str): If set, the feed's status will be updated to this value after its tasks have executed. date_key (str): The key in the context whose value is the date of the workflow being executed. """ super(StatusRunner, self).__init__(*args) self.requisite_status = requisite_status self.complete_status = complete_status self.date_key = date_key def execute(self, activity, context): """Execute tasks depending on feed's status. Args: activity (Activity): Activity executing the task runner. context (dict): Flow's current context. """ result = dict() date = context[self.date_key] current_status = garcon_feed_status.get_overall_status( feed_name, date) if current_status == self.requisite_status: activity.logger.info( '{feed_name} on {date}: status matches ' '{requisite_status}. Running tasks for ' '{activity_name}.'.format( feed_name=feed_name, date=date, requisite_status=self.requisite_status, activity_name=activity.name)) result = super(StatusRunner, self).execute( activity, context) if self.complete_status: activity.logger.info( '{feed_name} on {date}: Updating overall status ' 'to {complete_status}.'.format( feed_name=feed_name, date=date, complete_status=self.complete_status)) garcon_feed_status.set_overall_status( feed_name, date, self.complete_status) else: activity.logger.info( '{feed_name} on {date}: status is currently ' '{current_status}, not {requisite_status}. Skipping ' 'tasks for {activity_name}.'.format( feed_name=feed_name, date=date, current_status=current_status, requisite_status=self.requisite_status, activity_name=activity.name)) return result return StatusRunner(*args, **kwargs) return create_runner