def testSyncRequest_processError(self, mock_queue, mock_process):
        request_sync_monitor.Monitor(REQUEST_ID)
        sync_key = request_sync_monitor.GetRequestSyncStatusKey(REQUEST_ID)
        sync_status = sync_key.get()
        sync_status.has_new_command_events = True
        sync_status.put()

        mock_process.side_effect = RuntimeError
        datastore_test_util.CreateRequest(request_id=REQUEST_ID,
                                          user='******',
                                          command_infos=[
                                              datastore_entities.CommandInfo(
                                                  command_line='command_line2',
                                                  cluster='cluster',
                                                  run_target='run_target')
                                          ],
                                          state=common.RequestState.QUEUED)

        with self.assertRaises(RuntimeError):
            request_sync_monitor.SyncRequest(REQUEST_ID)

        mock_process.assert_called_once_with(REQUEST_ID)
        mock_queue.assert_called_once_with(REQUEST_ID)  # Call from Monitor()

        sync_status = sync_key.get()
        self.assertTrue(sync_status.has_new_command_events)
    def testProcessCommandEvents_singleEvent(self, mock_process):
        request_sync_monitor.Monitor(REQUEST_ID)
        event = _AddCommandEvent()
        _AddCommandEvent(request_id='another_request')

        request_sync_monitor._ProcessCommandEvents(REQUEST_ID)

        raw_events = datastore_entities.RawCommandEvent.query(
            namespace=common.NAMESPACE).fetch()
        self.assertLen(raw_events,
                       1)  # only another_request event should remain
        mock_process.assert_called_once_with(event)
    def testMonitor(self):
        request_sync_monitor.Monitor(REQUEST_ID)

        tasks = self.mock_task_scheduler.GetTasks(
            queue_names=(request_sync_monitor.REQUEST_SYNC_QUEUE, ))
        self.assertLen(tasks, 1)
        task = json.loads(tasks[0].payload)
        self.assertEqual(REQUEST_ID, task[request_sync_monitor.REQUEST_ID_KEY])

        sync_key = request_sync_monitor.GetRequestSyncStatusKey(REQUEST_ID)
        sync_status = sync_key.get()
        self.assertEqual(REQUEST_ID, sync_status.request_id)
    def testStoreCommandEvent(self):
        request_sync_monitor.Monitor(REQUEST_ID)
        event = _AddCommandEvent()

        raw_events = datastore_entities.RawCommandEvent.query(
            datastore_entities.RawCommandEvent.request_id == REQUEST_ID,
            namespace=common.NAMESPACE).fetch()
        self.assertLen(raw_events, 1)
        self.assertEqual(event.event_dict, raw_events[0].payload)

        sync_key = request_sync_monitor.GetRequestSyncStatusKey(REQUEST_ID)
        self.assertTrue(sync_key.get().has_new_command_events)
    def testUpdateSyncStatus_force(self, mock_now):
        now = datetime.datetime.utcnow()
        mock_now.return_value = now

        request_sync_monitor.Monitor(REQUEST_ID)
        sync_key = request_sync_monitor.GetRequestSyncStatusKey(REQUEST_ID)
        sync_status = sync_key.get()
        sync_status.last_sync_time = now - datetime.timedelta(minutes=2)
        sync_status.put()

        self.assertTrue(request_sync_monitor._UpdateSyncStatus(REQUEST_ID))
        sync_status = sync_key.get()
        self.assertEqual(now, sync_status.last_sync_time)
    def testUpdateSyncStatus_noSyncTime(self, mock_now):
        now = datetime.datetime.utcnow()
        mock_now.return_value = now

        request_sync_monitor.Monitor(REQUEST_ID)
        sync_key = request_sync_monitor.GetRequestSyncStatusKey(REQUEST_ID)
        sync_status = sync_key.get()
        sync_status.has_new_command_events = False
        sync_status.put()

        self.assertTrue(request_sync_monitor._UpdateSyncStatus(REQUEST_ID))
        sync_status = sync_key.get()
        self.assertFalse(sync_status.has_new_command_events)
        self.assertEqual(now, sync_status.last_sync_time)
    def BackfillRequestSyncs(self, request):
        logging.info("Backfilling non final requests to sync queue.")

        for state in (common.RequestState.UNKNOWN, common.RequestState.QUEUED,
                      common.RequestState.RUNNING):
            requests = datastore_entities.Request.query(
                datastore_entities.Request.state == state,
                namespace=common.NAMESPACE)
            for request in requests:
                logging.info(
                    "Backfilling request sync for request %s (state=%s)",
                    request.key.id(), request.state)
                request_sync_monitor.Monitor(request.key.id())

        return message_types.VoidMessage()
    def testUpdateSyncStatus_noEvents(self, mock_now):
        last_sync = datetime.datetime(2021, 1, 1)  # last synced 1 second ago
        now = datetime.datetime(2021, 1, 1, 0, 0, 1)
        mock_now.return_value = now

        request_sync_monitor.Monitor(REQUEST_ID)
        sync_key = request_sync_monitor.GetRequestSyncStatusKey(REQUEST_ID)
        sync_status = sync_key.get()
        sync_status.has_new_command_events = False
        sync_status.last_sync_time = last_sync
        sync_status.put()

        self.assertFalse(request_sync_monitor._UpdateSyncStatus(REQUEST_ID))
        sync_status = sync_key.get()
        self.assertEqual(last_sync, sync_status.last_sync_time)