def user_in(self, data=None, conn=None): """ Interpret the message that is received by the server """ try: new_task_dict = eval(data) good_data = True except: conn.send('Bad Command: %s' % data) good_data = False logging.info('Bad Command: {}'.format(data)) if good_data is True: for key, value in new_task_dict.iteritems(): task_id = int(time.time() * 1000000) try: db_use = value.pop('db_use') except: db_use = False new_task = Task(name=key, task_id=task_id, db_use=db_use, from_user=True, **value) logging.info('Task added to Queue: {}'.format(str(new_task))) if new_task.loop is True: conn.send('Received looping task. Closing connection...') conn.close() else: self.connections[task_id] = conn self.queue += [new_task]
def shutdown(self): """ Shuts down the server allowing currently running tasks to finish """ self.stop_server = True self.stop() logging.info('ShakeCast Server Stopped...') return {'status': 'finished', 'message': 'Stopping server...'}
def check_task(self, task=Task()): """ Check the output from a finished task and determines whether the task should be removed from the queue """ if task.output and type(task.output) is not dict: task.output = task.output.__dict__ if task.loop is False: out_str = '' server_log = '' if task.output.get('status') == 'finished': out_str = task.output.get('message') server_log = 'Task: %s :: finished' elif task.output.get('status') == 'force_stop': out_str = task.output.get('message', 'No Message') server_log = 'Task: %s :: force stopped' elif task.output.get('status') == 'failed': out_str = "FAILED: %s" % task.output.get('message') server_log = 'Task: %s :: failed to finish' elif task.status == 'failed': out_str = '{} failed to run... \n{}: {}'.format(task.name, type(task.error), task.error) server_log = 'Task: {} :: failed to run \n{}: {}'.format(task.name, type(task.error), task.error) int_time = int(time.time()) self.messages[int_time] = out_str if task.id in self.connections.keys(): conn = self.connections[task.id] conn.send(str(self.messages)) conn.close() task.status = 'complete' else: task.status = 'stopped' # only log results from failed normal tasks or abnormal tasks if ((task.name not in self.debug_only) or task.error or (task.output and task.output.get('error'))): logging.info('{}: \n\tSTATUS: {} \n\tOUTPUT: {}'.format(task.name, task.status, task.output)) else: # if we're debugging, log everything logging.debug('{}: \n\tSTATUS: {} \n\tOUTPUT: {}'.format(task.name, task.status, task.output)) if task.db_use is True: self.db_open = True
def socket_setup(self): """ Connects the server to a specific socket """ connected = False attempts = 0 while connected is False and attempts < 60: try: self.socket.bind(('', self.port)) self.socket.listen(5) connected = True except: logging.info('Failed to get port for server: {}'.format(self.port)) time.sleep(2) attempts += 1
def queue_check(self): """ Check for tasks that are ready to be run and finished tasks that can be removed """ timestamp = time.time() sc = SC() for i,task in enumerate(self.queue): # run tasks if it's their time and they aren't already running # and the db is available if ((task.next_run < timestamp and task.status == 'stopped') and (task.db_use is False or self.db_open is True or (sc.dict['DBConnection']['type'] != 'sqlite' and task.from_user is True))): if task.db_use is True: self.db_open = False self.last_task = time.time() if ((task.name not in self.debug_only)): logging.info('Running task: {}'.format(task.name)) else: logging.debug('Running task: {}'.format(task.name)) task_thread = NewThread(func=task.run) task_thread.start() # move task to the end of the list self.queue.pop(i) self.queue += [task] elif task.status == 'finished' or task.status == 'failed': self.check_task(task=task)
def start_shakecast(self): logging.info('Starting ShakeCast Server... ') try: status = '' message = '' task_names = [task.name for task in self.queue] if 'fast_geo_json' not in task_names: task = Task() task.id = int(time.time() * 1000000) task.func = f.geo_json task.loop = True task.interval = 60 task.db_use = True task.name = 'fast_geo_json' task.args_in = {'query_period': 'hour'} self.queue += [task] message += 'Started monitoring earthquake feed \n' if 'check_new' not in task_names: task = Task() task.id = int(time.time() * 1000000) task.func = f.check_new task.loop = True task.interval = 3 task.db_use = True task.name = 'check_new' self.queue += [task] message += "Waiting for new events" if 'create_products' not in task_names: task = Task() task.id = int(time.time() * 1000000) task.func = f.create_products task.loop = True task.interval = 3 task.db_use = True task.name = 'create_products' self.queue += [task] if 'send_notifications' not in task_names: task = Task() task.id = int(time.time() * 1000000) task.func = f.inspection_notification_service task.loop = True task.interval = 3 task.db_use = True task.name = 'send_notifications' self.queue += [task] if 'record_messages' not in task_names: task = Task() task.id = int(time.time() * 1000000) task.func = self.record_messages task.loop = True task.interval = 2 task.name = 'record_messages' self.queue += [task] message += "Recording messages" status = 'finished' except: status = 'failed' return {'status': status, 'message': message}
keep_messages = {} if current_messages_str: current_messages = json.loads(current_messages_str) # figure out which current messages we should keep for key in current_messages.keys(): if int(key) > time.time() - 300: keep_messages[key] = current_messages[key] # add current messages for key in self.messages.keys(): keep_messages[key] = self.messages[key] keep_messages_str = json.dumps(keep_messages, indent=4) with open(fname, 'w') as file_: file_.write(keep_messages_str) if __name__ == '__main__': logging.info('start') startup() sc_server = Server() # start shakecast sc_server.start_shakecast() # catch crashes while sc_server.stop_server is False: sc_server.stop_loop = False sc_server.loop()