|
| 1 | +from jormungandr import i_manager |
| 2 | +from jormungandr.protobuf_to_dict import protobuf_to_dict |
| 3 | +from jormungandr.interfaces.v1.StatedResource import StatedResource |
| 4 | +from navitiacommon import type_pb2, request_pb2 |
| 5 | +from jormungandr import exceptions |
| 6 | +from collections import defaultdict |
| 7 | +import gevent, gevent.pool |
| 8 | +from jormungandr import app |
| 9 | + |
| 10 | + |
| 11 | +class BackendsStatus(StatedResource): |
| 12 | + def __init__(self, *args, **kwargs): |
| 13 | + super().__init__(self, *args, **kwargs) |
| 14 | + |
| 15 | + def get(self): |
| 16 | + regions = i_manager.get_regions() |
| 17 | + |
| 18 | + response = { |
| 19 | + 'lokis': {}, |
| 20 | + 'krakens': {}, |
| 21 | + 'errors': [], |
| 22 | + } |
| 23 | + |
| 24 | + pool = gevent.pool.Pool(app.config.get('BACKENDS_STATUS_GREENLET_POOL_SIZE', 10)) |
| 25 | + |
| 26 | + def do(instance_name, pt_planner_type, pt_planner, req): |
| 27 | + try: |
| 28 | + resp = pt_planner.send_and_receive(req, request_id='backend_status') |
| 29 | + status = protobuf_to_dict(resp, use_enum_labels=True) |
| 30 | + is_loaded = status.get('status', {}).get('loaded') is True |
| 31 | + if not is_loaded: |
| 32 | + return instance_name, pt_planner_type, status, 'data is not loaded' |
| 33 | + return instance_name, pt_planner_type, status, None |
| 34 | + except exceptions.DeadSocketException as e: |
| 35 | + return ( |
| 36 | + instance_name, |
| 37 | + pt_planner_type, |
| 38 | + None, |
| 39 | + 'instance {} backend {} did not respond because: {}'.format( |
| 40 | + instance_name, pt_planner_type, str(e) |
| 41 | + ), |
| 42 | + ) |
| 43 | + |
| 44 | + futures = [] |
| 45 | + |
| 46 | + req = request_pb2.Request() |
| 47 | + req.requested_api = type_pb2.STATUS |
| 48 | + |
| 49 | + for key_region in regions: |
| 50 | + instance = i_manager.instances[key_region] |
| 51 | + for pt_planner_type, pt_planner in instance.get_all_pt_planners(): |
| 52 | + futures.append(pool.spawn(do, instance.name, pt_planner_type, pt_planner, req)) |
| 53 | + |
| 54 | + found_err = False |
| 55 | + status_code = 200 |
| 56 | + |
| 57 | + for future in gevent.iwait(futures): |
| 58 | + instance_name, pt_planner_type, status, err = future.get() |
| 59 | + found_err |= err is not None |
| 60 | + if err: |
| 61 | + response['errors'].append( |
| 62 | + {'backend_type': pt_planner_type, 'backend_name': instance_name, 'error': err} |
| 63 | + ) |
| 64 | + |
| 65 | + key = 'krakens' if pt_planner_type == 'kraken' else 'lokis' |
| 66 | + status_ = status.get('status', {}) if status is not None else {} |
| 67 | + response[key][instance_name] = { |
| 68 | + 'status': status_.get('status'), |
| 69 | + 'backend_version': status_.get('navitia_version'), |
| 70 | + 'start_date': status_.get('start_production_date'), |
| 71 | + 'end_date': status_.get('end_production_date'), |
| 72 | + 'loaded': status_.get('loaded'), |
| 73 | + 'last_load_at': status_.get('last_load_at'), |
| 74 | + 'last_load_status': status_.get('last_load_status'), |
| 75 | + 'is_realtime_loaded': status_.get('is_realtime_loaded'), |
| 76 | + 'last_rt_data_loaded': status_.get('last_rt_data_loaded'), |
| 77 | + } |
| 78 | + |
| 79 | + if found_err: |
| 80 | + status_code = 503 |
| 81 | + |
| 82 | + return response, status_code |
0 commit comments