def cron_action(self, app_context, global_state): per_course_jobs = [ students.StudentCounter(app_context), enrollment.StudentEnrollmentEventCounter(app_context), ] for job in per_course_jobs: if job.is_active(): job.cancel() job.submit()
def _submit_jobs(cls): for course_context in sites.get_all_courses(): per_course_jobs = [ students.StudentCounter(course_context), enrollment.StudentEnrollmentEventCounter(course_context), ] for job in per_course_jobs: if job.is_active(): job.cancel() job.submit()
def test_enrollment_map_reduce_job(self): self.maxDiff = None MOCK_NOW = 1427247511 COURSE = 'xyzzy' NAMESPACE = 'ns_xyzzy' MIN_TIMESTAMP = (MOCK_NOW - (MOCK_NOW % enrollment.SECONDS_PER_HOUR) - enrollment.StudentEnrollmentEventCounter.MAX_AGE) # Insert some bogus StudentEnrollmentEventEntity for the M/R job # to count or delete. very_old_enroll = enrollment.StudentEnrollmentEventDTO(None, {}) very_old_enroll.timestamp = 0 very_old_enroll.metric = messaging.Message.METRIC_ENROLLED very_old_unenroll = enrollment.StudentEnrollmentEventDTO(None, {}) very_old_unenroll.timestamp = 0 very_old_unenroll.metric = messaging.Message.METRIC_UNENROLLED just_too_old_enroll = enrollment.StudentEnrollmentEventDTO(None, {}) just_too_old_enroll.timestamp = MIN_TIMESTAMP - 1 just_too_old_enroll.metric = messaging.Message.METRIC_ENROLLED just_too_old_unenroll = enrollment.StudentEnrollmentEventDTO(None, {}) just_too_old_unenroll.timestamp = MIN_TIMESTAMP - 1 just_too_old_unenroll.metric = messaging.Message.METRIC_UNENROLLED young_enough_enroll = enrollment.StudentEnrollmentEventDTO(None, {}) young_enough_enroll.timestamp = MIN_TIMESTAMP young_enough_enroll.metric = messaging.Message.METRIC_ENROLLED young_enough_unenroll = enrollment.StudentEnrollmentEventDTO(None, {}) young_enough_unenroll.timestamp = MIN_TIMESTAMP young_enough_unenroll.metric = messaging.Message.METRIC_UNENROLLED now_enroll = enrollment.StudentEnrollmentEventDTO(None, {}) now_enroll.timestamp = MOCK_NOW now_enroll.metric = messaging.Message.METRIC_ENROLLED now_unenroll = enrollment.StudentEnrollmentEventDTO(None, {}) now_unenroll.timestamp = MOCK_NOW now_unenroll.metric = messaging.Message.METRIC_UNENROLLED dtos = [ very_old_enroll, very_old_unenroll, just_too_old_enroll, just_too_old_unenroll, young_enough_enroll, young_enough_unenroll, now_enroll, now_unenroll, ] app_context = actions.simple_add_course(COURSE, ADMIN_EMAIL, 'Test') with common_utils.Namespace(NAMESPACE): enrollment.StudentEnrollmentEventDAO.save_all(dtos) # Run map/reduce job with a setup function replaced so that it will # always choose the same timestamp as the start time. job_class = enrollment.StudentEnrollmentEventCounter save_b_a_m_p = job_class.build_additional_mapper_params try: def fixed_time_b_a_m_p(self, app_context): return {self.MIN_TIMESTAMP: MIN_TIMESTAMP} job_class.build_additional_mapper_params = fixed_time_b_a_m_p # Actually run the job. enrollment.StudentEnrollmentEventCounter(app_context).submit() self.execute_all_deferred_tasks() finally: job_class.build_additional_mapper_params = save_b_a_m_p # Verify that the DTOs older than the cutoff have been removed from # the datastore. with common_utils.Namespace(NAMESPACE): dtos = enrollment.StudentEnrollmentEventDAO.get_all() dtos.sort(key=lambda dto: (dto.timestamp, dto.metric)) self.assertEqual([ young_enough_enroll.dict, young_enough_unenroll.dict, now_enroll.dict, now_unenroll.dict ], [d.dict for d in dtos]) # Verify that we have messages for the new-enough items, and no # messages for the older items. messages = MockSender.get_sent() messages.sort(key=lambda m: (m['timestamp'], m['metric'])) MOCK_NOW_HOUR = MOCK_NOW - (MOCK_NOW % enrollment.SECONDS_PER_HOUR) expected = [{ messaging.Message._INSTALLATION: FAKE_INSTALLATION_ID, messaging.Message._COURSE: FAKE_COURSE_ID, messaging.Message._TIMESTAMP: MIN_TIMESTAMP, messaging.Message._VERSION: os.environ['GCB_PRODUCT_VERSION'], messaging.Message._METRIC: messaging.Message.METRIC_ENROLLED, messaging.Message._VALUE: 1, }, { messaging.Message._INSTALLATION: FAKE_INSTALLATION_ID, messaging.Message._COURSE: FAKE_COURSE_ID, messaging.Message._TIMESTAMP: MIN_TIMESTAMP, messaging.Message._VERSION: os.environ['GCB_PRODUCT_VERSION'], messaging.Message._METRIC: messaging.Message.METRIC_UNENROLLED, messaging.Message._VALUE: 1, }, { messaging.Message._INSTALLATION: FAKE_INSTALLATION_ID, messaging.Message._COURSE: FAKE_COURSE_ID, messaging.Message._TIMESTAMP: MOCK_NOW_HOUR, messaging.Message._VERSION: os.environ['GCB_PRODUCT_VERSION'], messaging.Message._METRIC: messaging.Message.METRIC_ENROLLED, messaging.Message._VALUE: 1, }, { messaging.Message._INSTALLATION: FAKE_INSTALLATION_ID, messaging.Message._COURSE: FAKE_COURSE_ID, messaging.Message._TIMESTAMP: MOCK_NOW_HOUR, messaging.Message._VERSION: os.environ['GCB_PRODUCT_VERSION'], messaging.Message._METRIC: messaging.Message.METRIC_UNENROLLED, messaging.Message._VALUE: 1, }] self.assertEquals(expected, messages) sites.reset_courses()