"""Apple Music Demographics Insights pre-aggregation workflow.""" from garcon import runner from garcon.contrib.dynamo_feed_status import \ feed_status_ingestion as feed_status from garcon.param import StaticParam from analytics_aggregation.flows import base from analytics_aggregation.flows.apple_music_demographics import config from analytics_aggregation.flows.apple_music_demographics import tasks from analytics_aggregation.tasks import overall_status_tasks class Flow(base.FlowBase): """Class representing a workflow.""" timeout = 3 * 60 * 60 # 3 hours def __init__(self): """Initialize flow object.""" super(Flow, self).__init__(feed_name=config.FEED_NAME, version='1.0') def decider(self, schedule, context=None): """Activity decider. Arg: schedule (callable): The scheduler method. context (dict): Initial context of workflow. """ bootstrap = schedule( 'bootstrap', self.bootstrap) # Stop flow if feed already ingested if bootstrap.result.get('bootstrap.stop'): return populate_fact_demographics = schedule( 'populate_fact_demographics', self.populate_fact_demographics, requires=[bootstrap]) schedule( 'set_status_to_ingested', self.set_status_to_ingested, requires=[populate_fact_demographics]) def workflow_id(self, initial_context): """Generate workflow id. To avoid two flow execute simultaneously we should create all flows with the same workflow_id. Args: initial_context (dict): The initial context for the flow. Returns: str: Flow identifier in the forms of ''. """ return self.name @property def bootstrap(self): """Bootstrap the configuration.""" return self.create( name='bootstrap', tasks=runner.Sync( tasks.bootstrap.fill( namespace='bootstrap', feed_name=StaticParam(self.feed_name), context_date_range='context_date_range', reload='reload'))) @property def populate_fact_demographics(self): """Clean up and populate fact_demographics.""" return self.create( name='populate_fact_demographics', tasks=runner.Sync( tasks.populate_fact_demographics.fill( namespace='populate_fact_demographics', date_range='bootstrap.date_range'))) @property def set_status_to_ingested(self): """Set flow's final status.""" return self.create( name='set_status_to_ingested', tasks=runner.Sync( overall_status_tasks.set_overall_status.fill( namespace='set_status_to_ingested', feed_name=StaticParam(self.feed_name), date_range='bootstrap.date_range_as_str', status=StaticParam(feed_status.STATUS_INGESTED))))