def check_flow_timeouts_task(): """ See if any flow runs have timed out """ # find any runs that should have timed out runs = FlowRun.objects.filter(is_active=True, timeout_on__lte=timezone.now()) runs = runs.only('id', 'org', 'timeout_on') queued_timeouts = QueueRecord( 'flow_timeouts', lambda r: '%d:%d' % (r.id, datetime_to_epoch(r.timeout_on))) for run in runs: # ignore any run which was locked by previous calls to this task if not queued_timeouts.is_queued(run): try: task_payload = dict(type=TIMEOUT_EVENT, run=run.id, timeout_on=run.timeout_on) push_task(run.org_id, HANDLER_QUEUE, HANDLE_EVENT_TASK, task_payload) queued_timeouts.set_queued([run]) except Exception: # pragma: no cover logger.error("Error queuing timeout task for run #%d" % run.id, exc_info=True)
def check_campaigns_task(): """ See if any event fires need to be triggered """ from temba.flows.models import Flow unfired = EventFire.objects.filter(fired=None, scheduled__lte=timezone.now()) unfired = unfired.values('id', 'event__flow_id') # group fire events by flow so they can be batched fire_ids_by_flow_id = defaultdict(list) for fire in unfired: fire_ids_by_flow_id[fire['event__flow_id']].append(fire['id']) # fetch the flows used by all these event fires flows_by_id = { flow.id: flow for flow in Flow.objects.filter(id__in=fire_ids_by_flow_id.keys()) } queued_fires = QueueRecord('queued_event_fires') # create queued tasks for flow_id, fire_ids in six.iteritems(fire_ids_by_flow_id): flow = flows_by_id[flow_id] # create sub-batches no no single task is too big for fire_id_batch in chunk_list(fire_ids, 500): # ignore any fires which were queued by previous calls to this task but haven't yet been marked as fired queued_fire_ids = queued_fires.filter_unqueued(fire_id_batch) if queued_fire_ids: try: push_task(flow.org_id, HANDLER_QUEUE, HANDLE_EVENT_TASK, dict(type=FIRE_EVENT, fires=queued_fire_ids)) queued_fires.set_queued(queued_fire_ids) except Exception: # pragma: no cover fire_ids_str = ','.join( six.text_type(f) for f in queued_fire_ids) logger.error("Error queuing campaign event fires: %s" % fire_ids_str, exc_info=True)
def check_campaigns_task(): """ See if any event fires need to be triggered """ from temba.flows.models import Flow unfired = EventFire.objects.filter( fired=None, scheduled__lte=timezone.now(), event__flow__flow_server_enabled=False ).select_related("event") unfired = unfired.values("id", "event_id", "event__flow_id") # group fire events by event so they can be batched fire_ids_by_event_id = defaultdict(list) event_flow_map = dict() for fire in unfired: event_flow_map[fire["event_id"]] = fire["event__flow_id"] fire_ids_by_event_id[fire["event_id"]].append(fire["id"]) # fetch the flows used by all these event fires flows_by_id = {flow.id: flow for flow in Flow.objects.filter(id__in=event_flow_map.values())} queued_fires = QueueRecord("queued_event_fires") # create queued tasks for ev_id, fire_ids in fire_ids_by_event_id.items(): flow_id = event_flow_map[ev_id] flow = flows_by_id[flow_id] # create sub-batches no no single task is too big for fire_id_batch in chunk_list(fire_ids, 500): # ignore any fires which were queued by previous calls to this task but haven't yet been marked as fired queued_fire_ids = queued_fires.filter_unqueued(fire_id_batch) if queued_fire_ids: try: push_task( flow.org_id, Queue.HANDLER, HANDLE_EVENT_TASK, dict(type=FIRE_EVENT, fires=queued_fire_ids) ) queued_fires.set_queued(queued_fire_ids) except Exception: # pragma: no cover fire_ids_str = ",".join(str(f) for f in queued_fire_ids) logger.error("Error queuing campaign event fires: %s" % fire_ids_str, exc_info=True)