def test_should_get_scheduled_runs_for_contact(self): runnable = DeliveryNodeFactory(contact_person_id=2) contact_person_id = 2 self.assertEqual(Run.has_scheduled_run(contact_person_id), False) run = RunFactory(runnable=runnable) self.assertEqual(Run.has_scheduled_run(contact_person_id), True) run.status = Run.STATUS.completed run.save() self.assertEqual(Run.has_scheduled_run(contact_person_id), False)
def schedule_run_directly_for(runnable, run_delay): if Run.has_scheduled_run(runnable.contact_person_id): RunQueue.enqueue(runnable, run_delay) elif settings.RAPIDPRO_LIVE: task = _schedule_run.apply_async(args=[runnable.id], countdown=run_delay) Run.objects.create(scheduled_message_task_id=task.id, runnable=runnable, status=Run.STATUS.scheduled, phone=runnable.contact.phone)
def _calculate_delay(runnable, run_delay): expected_delivery_date = datetime.datetime.combine( runnable.delivery_date, datetime.datetime.min.time()) when_to_send_message = expected_delivery_date + datetime.timedelta( days=settings.DELIVERY_STATUS_CHECK_DELAY, hours=HOUR_TO_SEND_SMS) delay_delta_in_seconds = (when_to_send_message - datetime.datetime.now()).total_seconds() run_delay = run_delay if run_delay > 0 else settings.DELIVERY_BUFFER_IN_SECONDS standard_delay = delay_delta_in_seconds if delay_delta_in_seconds > 0 else run_delay completed_run = Run.last_temp_completed_run(runnable.contact_person_id) temp_delay = 0 if completed_run: last_answer = completed_run.last_answer() if last_answer: flow = completed_run.runnable.flow() logger.info("flow=%s completed run id=%s,question=%s, answer=%s" % (flow, completed_run.id, last_answer.question.label, last_answer.format())) if flow.is_temp_ended(last_answer): temp_delay = (last_answer.modified - datetime.datetime.now( )).total_seconds() + settings.TEMP_DELIVERY_BUFFER_IN_SECONDS logger.info("temp_delay=%s" % temp_delay) return standard_delay if standard_delay > temp_delay else temp_delay
def _calculate_delay(runnable, run_delay): expected_delivery_date = datetime.datetime.combine(runnable.delivery_date, datetime.datetime.min.time()) when_to_send_message = expected_delivery_date + datetime.timedelta(days=settings.DELIVERY_STATUS_CHECK_DELAY, hours=HOUR_TO_SEND_SMS) delay_delta_in_seconds = (when_to_send_message - datetime.datetime.now()).total_seconds() run_delay = run_delay if run_delay > 0 else settings.DELIVERY_BUFFER_IN_SECONDS standard_delay = delay_delta_in_seconds if delay_delta_in_seconds > 0 else run_delay completed_run = Run.last_temp_completed_run(runnable.contact_person_id) temp_delay = 0 if completed_run: last_answer = completed_run.last_answer() if last_answer: flow = completed_run.runnable.flow() logger.info("flow=%s completed run id=%s,question=%s, answer=%s" % ( flow, completed_run.id, last_answer.question.label, last_answer.format())) if flow.is_temp_ended(last_answer): temp_delay = ( last_answer.modified - datetime.datetime.now()).total_seconds() + settings.TEMP_DELIVERY_BUFFER_IN_SECONDS logger.info("temp_delay=%s" % temp_delay) return standard_delay if standard_delay > temp_delay else temp_delay
def expire_overdue_runs(): overdue_runs = Run.overdue_runs() for overdue_run in overdue_runs: overdue_run.update_status(Run.STATUS.expired) next_run = RunQueue.dequeue(overdue_run.runnable.contact_person_id) if next_run: schedule_run_for(next_run.runnable) next_run.update_status(RunQueue.STATUS.started)
def schedule_run_directly_for(runnable, run_delay): if Run.has_scheduled_run(runnable.contact_person_id): RunQueue.enqueue(runnable, settings.DELIVERY_STATUS_CHECK_DELAY) elif settings.RAPIDPRO_LIVE: logger.info("schedule_run_directly_for:: run_delay=%s" % run_delay) task = _schedule_run.apply_async(args=[runnable.id], countdown=run_delay) Run.objects.create(scheduled_message_task_id=task.id, runnable=runnable, status=Run.STATUS.not_started, phone=runnable.contact.phone)
def _schedule_run_for(self, runnable): if runnable.completed_run() is None: if Run.has_scheduled_run(runnable.contact_person_id): RunQueue.enqueue(runnable, 0) else: contact = runnable.build_contact() task = '231x31231231' Run.objects.create(scheduled_message_task_id=task, runnable=runnable, status=Run.STATUS.scheduled, phone=contact['phone'] if contact else None)
def expire_overdue_runs(): overdue_runs = Run.overdue_runs() for overdue_run in overdue_runs: overdue_run.status = Run.STATUS.expired overdue_run.save() next_run = RunQueue.dequeue(overdue_run.node.contact_person_id) if next_run: schedule_run_for(next_run.node) next_run.status = RunQueue.STATUS.started next_run.save()
def schedule_run_for(node): current_run = node.current_run() if current_run: _cancel_run(current_run) run_delay = _calculate_delay(node) if Run.current_run_for_node(node): RunQueue.enqueue(node, run_delay) else: contact = node.build_contact() task = _schedule_run.apply_async(args=[node.id], countdown=run_delay) Run.objects.create(scheduled_message_task_id=task.id, node=node, status=Run.STATUS.scheduled, phone=contact['phone'])
def test_should_not_get_completed_expired_or_cancelled_runs_when_getting_expired_runs(self): expired_run_date = datetime.date(1990, 1, 1) RunFactory(status=Run.STATUS.completed, node=DistributionPlanNodeFactory( delivery_date=expired_run_date)) RunFactory(status=Run.STATUS.expired, node=DistributionPlanNodeFactory( delivery_date=expired_run_date)) RunFactory(status=Run.STATUS.cancelled, node=DistributionPlanNodeFactory( delivery_date=expired_run_date)) overdue_runs = Run.overdue_runs() self.assertEqual(len(overdue_runs), 0)
def test_should_not_get_completed_expired_or_cancelled_runs_when_getting_expired_runs( self): expired_run_date = datetime.date(1990, 1, 1) RunFactory( status=Run.STATUS.completed, runnable=DeliveryNodeFactory(delivery_date=expired_run_date)) RunFactory( status=Run.STATUS.expired, runnable=DeliveryNodeFactory(delivery_date=expired_run_date)) RunFactory( status=Run.STATUS.cancelled, runnable=DeliveryNodeFactory(delivery_date=expired_run_date)) overdue_runs = Run.overdue_runs() self.assertEqual(len(overdue_runs), 0)
def test_should_get_over_due_runs(self): delivery_status_check_delay = datetime.timedelta(days=settings.DELIVERY_STATUS_CHECK_DELAY) max_allowed_reply_period = datetime.timedelta(days=settings.MAX_ALLOWED_REPLY_PERIOD) one_day = datetime.timedelta(days=1) today = datetime.datetime.combine(datetime.date.today(), datetime.datetime.min.time()) expired_run_date = today - delivery_status_check_delay - max_allowed_reply_period - one_day valid_run_date = today - delivery_status_check_delay - max_allowed_reply_period + one_day expired_run = RunFactory(status=Run.STATUS.scheduled, node=DistributionPlanNodeFactory( delivery_date=expired_run_date)) RunFactory(status=Run.STATUS.scheduled, node=DistributionPlanNodeFactory( delivery_date=valid_run_date)) overdue_runs = Run.overdue_runs() self.assertEqual(len(overdue_runs), 1) self.assertEqual(overdue_runs[0], expired_run)
def test_should_get_over_due_runs(self): delivery_status_check_delay = datetime.timedelta( days=settings.DELIVERY_STATUS_CHECK_DELAY) max_allowed_reply_period = datetime.timedelta( days=settings.MAX_ALLOWED_REPLY_PERIOD) one_day = datetime.timedelta(days=1) today = datetime.datetime.combine(datetime.date.today(), datetime.datetime.min.time()) expired_run_date = today - delivery_status_check_delay - max_allowed_reply_period - one_day valid_run_date = today - delivery_status_check_delay - max_allowed_reply_period + one_day expired_run = RunFactory( status=Run.STATUS.scheduled, runnable=DeliveryNodeFactory(delivery_date=expired_run_date)) RunFactory(status=Run.STATUS.scheduled, runnable=DeliveryNodeFactory(delivery_date=valid_run_date)) overdue_runs = Run.overdue_runs() self.assertEqual(len(overdue_runs), 1) self.assertEqual(overdue_runs[0], expired_run)
def test_should_get_none_when_current_run_is_called_for_a_consignee_with_no_runs_scheduled(self): RunFactory(node=self.node, status=Run.STATUS.expired) RunFactory(node=self.node, status=Run.STATUS.completed) self.assertEqual(Run.current_run_for_node(self.node), None)
def test_should_get_current_run_for_consignee_with_run_with_status_scheduled(self): run = RunFactory(node=self.node) self.assertEqual(Run.current_run_for_node(self.node), run)