예제 #1
0
 def status(self, value):
     old_status = self._status
     assert value in status_enum_list
     if value == self._status:
         return True
     roles_accepted = self.roles_accepted.get(value, None)
     if roles_accepted:
         perm = Permission(*[RoleNeed(role) for role in roles_accepted])
         if not perm.can():
             raise RuntimeError("You're not authorized to set this status")
     status_required = self.status_required.get(value, None)
     if status_required and self._status != status_required:
         raise ValueError("You cannot set status from {} to {}".format(self._status, value))
     self._status = value
     self.status_changed()
     taxi = TaxiM.cache.get(self.taxi_id)
     taxi.synchronize_status_with_hail(self)
     client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB'])
     try:
         client.write_points([{
             "measurement": "hails_status_changed",
             "tags": {
                 "added_by": User.query.get(self.added_by).email,
                 "operator": self.operateur.email,
                 "zupc": taxi.ads.zupc.insee,
                 "previous_status": old_status,
                 "status": self._status
                 },
             "time": datetime.utcnow().strftime('%Y%m%dT%H:%M:%SZ'),
             "fields": {
                 "value": 1
             }
             }])
     except Exception as e:
         current_app.logger.error('Influxdb Error: {}'.format(e))
예제 #2
0
def add_missing_stats():
    c = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB'])
    r = c.query(
        "select value from hails_status_changed_with_id ORDER BY time LIMIT 1;"
    )
    min_time = r.get_points().next()['time']
    fields = [
        'change_to_sent_to_operator',
        'change_to_received_by_operator',
        'change_to_received_by_taxi',
        'change_to_accepted_by_taxi',
        'change_to_accepted_by_customer',
        'change_to_declined_by_taxi',
        'change_to_declined_by_customer',
        'change_to_incident_taxi',
        'change_to_incident_customer',
        'change_to_timeout_taxi',
        'change_to_timeout_customer',
        'change_to_failure',
        'change_to_finished',
        'change_to_customer_on_board',
        'change_to_timeout_accepted_by_customer',
    ]
    q = Hail.query.filter(Hail.added_at <= min_time,
                          or_(*[getattr(Hail, f) != None for f in fields]))
    for h in q.all():
        previous_status = None
        statuses = [(f[len("change_to_"):], getattr(h, f)) for f in fields]
        statuses = [v for v in statuses if v[1]]
        statuses = sorted(statuses, key=lambda v: v[1])
        for status in statuses:
            c.write_points([{
                "measurement": "hails_status_changed_with_id",
                "tags": {
                    "added_by": User.query.get(h.added_by).email,
                    "operator": h.operateur.email,
                    "zupc": h.taxi_relation.ads.zupc.parent.insee,
                    "previous_status": previous_status,
                    "status": status[0],
                    "hail_id": h.id
                },
                "time": status[1].strftime('%Y%m%dT%H:%M:%SZ'),
                "fields": {
                    "value": 1
                }
            }])
            previous_status = status[0]
예제 #3
0
    def post(self):
        parser = reqparse.DataJSONParser(filter_=hail_expect_post)
        hj = parser.get_data()[0]
        hj['status'] = 'received'
        hail = models.Hail(**hj)
        models.db.session.add(hail)
        models.db.session.commit()

        g.hail_log = models.HailLog('POST', hail, request.data)
        send_request_operator.apply_async(args=[
            hail.id,
            hail.operateur.hail_endpoint(current_app.config['ENV']),
            unicode(hail.operateur.operator_header_name),
            unicode(hail.operateur.operator_api_key), hail.operateur.email
        ],
                                          queue='send_hail_' +
                                          current_app.config['NOW'])

        client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB'])
        if client:
            try:
                client.write_points([{
                    "measurement":
                    "hails_created",
                    "tags": {
                        "added_by":
                        current_user.email,
                        "operator":
                        operateur.email,
                        "zupc":
                        hail.ads_insee,
                        "geohash":
                        Geohash.encode(hail.customer_lat, hail.customer_lon),
                    },
                    "time":
                    datetime.utcnow().strftime('%Y%m%dT%H:%M:%SZ'),
                    "fields": {
                        "value": 1
                    }
                }])
            except Exception as e:
                current_app.logger.error('Influxdb Error: {}'.format(e))
        result = marshal({"data": [hail]}, hail_model)
        result['data'][0]['taxi']['lon'] = hail.initial_taxi_lon
        result['data'][0]['taxi']['lat'] = hail.initial_taxi_lat
        return result, 201
예제 #4
0
    def get(self):
        if not request_wants_json():
            abort(400, message="request needs JSON")
        parser = reqparse.RequestParser()
        parser.add_argument('lon', type=float, required=True, location='args')
        parser.add_argument('lat', type=float, required=True, location='args')
        try:
            args = parser.parse_args()
        except BadRequest as e:
            return json.dumps(e.data), 400, {"Content-Type": "application/json"}

        zupc_list = db.session.execute(
            """SELECT insee, active, nom
               FROM "ZUPC"
               WHERE ST_INTERSECTS(shape, 'POINT(:lon :lat)')
               AND parent_id = id
               ORDER BY max_distance ASC;""",
            args).fetchall()
        to_return = []
        client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB'])
        for zupc in zupc_list:
            if any([zupc[0] == z['insee'] for z in to_return]):
                current_app.logger.debug("ZUPC {} already added, skipping it".format(zupc[0]))
                continue
            to_return.append({"insee": zupc[0], "active": zupc[1], "nom": zupc[2]})
            if not client:
                current_app.logger.error("No influxdb client")
                continue
            request = """SELECT "value" FROM "nb_taxis_every_1" WHERE "zupc" = '{}' AND "operator" = ''  AND time > now() - 1m  fill(null) LIMIT 1;""".format(zupc['insee'])
            try:
                r = client.query(request)
            except InfluxDBClientError as e:
                current_app.logger.error(e)
                continue
            points = list(r.get_points())
            if len(points) <= 0:
                current_app.logger.debug("No stat points found, request: \"{}\"".format(request))
                continue
            to_return[-1]['nb_active'] = points[0].get('value')
        return {"data": to_return}, 200
예제 #5
0
 def status(self, value):
     old_status = self._status
     assert value in status_enum_list
     if value == self._status:
         return True
     roles_accepted = self.roles_accepted.get(value, None)
     if roles_accepted:
         perm = Permission(*[RoleNeed(role) for role in roles_accepted])
         if not perm.can():
             raise RuntimeError("You're not authorized to set this status")
     status_required = self.status_required.get(value, None)
     if status_required and self._status != status_required:
         raise ValueError("You cannot set status from {} to {}".format(
             self._status, value))
     self._status = value
     self.status_changed()
     taxi = TaxiM.cache.get(self.taxi_id)
     taxi.synchronize_status_with_hail(self)
     client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB'])
     try:
         client.write_points([{
             "measurement":
             "hails_status_changed",
             "tags": {
                 "added_by": User.query.get(self.added_by).email,
                 "operator": self.operateur.email,
                 "zupc": taxi.ads.zupc.insee,
                 "previous_status": old_status,
                 "status": self._status
             },
             "time":
             datetime.utcnow().strftime('%Y%m%dT%H:%M:%SZ'),
             "fields": {
                 "value": 1
             }
         }])
     except Exception as e:
         current_app.logger.error('Influxdb Error: {}'.format(e))
예제 #6
0
    def post(self):
        hj = request.json
        hj = hj['data'][0]

        operateur = security_models.User.filter_by_or_404(
            email=hj['operateur'],
            message='Unable to find the taxi\'s operateur')

        descriptions = RawTaxi.get((hj['taxi_id'], ), operateur.id)
        if len(descriptions) == 0 or len(descriptions[0]) == 0:
            g.hail_log = HailLog('POST', None, request.data)
            abort(404,
                  message='Unable to find taxi {} of {}'.format(
                      hj['taxi_id'], hj['operateur']))
        if descriptions[0][0]['vehicle_description_status'] != 'free' or\
                not TaxiRedis(hj['taxi_id']).is_fresh(hj['operateur']):
            g.hail_log = HailLog('POST', None, request.data)
            abort(403, message="The taxi is not available")
        customer = CustomerModel.query.filter_by(
            id=hj['customer_id'], moteur_id=current_user.id).first()
        if not customer:
            customer = CustomerModel(hj['customer_id'])
            current_app.extensions['sqlalchemy'].db.session.add(customer)
        taxi_pos = redis_store.geopos(
            current_app.config['REDIS_GEOINDEX'],
            '{}:{}'.format(hj['taxi_id'], operateur.email))

        hail = HailModel()
        hail.customer_id = hj['customer_id']
        hail.customer_lon = hj['customer_lon']
        hail.customer_lat = hj['customer_lat']
        hail.customer_address = hj['customer_address']
        hail.customer_phone_number = hj['customer_phone_number']
        hail.taxi_id = hj['taxi_id']
        hail.initial_taxi_lat = taxi_pos[0][0] if taxi_pos else None
        hail.initial_taxi_lon = taxi_pos[0][1] if taxi_pos else None
        hail.operateur_id = operateur.id
        if customer.ban_end and datetime.now() < customer.ban_end:
            hail.status = 'customer_banned'
            current_app.extensions['sqlalchemy'].db.session.add(hail)
            current_app.extensions['sqlalchemy'].db.session.commit()
            abort(403, message='Customer is banned')
        hail.status = 'received'
        current_app.extensions['sqlalchemy'].db.session.add(hail)
        current_app.extensions['sqlalchemy'].db.session.commit()

        g.hail_log = HailLog('POST', hail, request.data)

        send_request_operator.apply_async(args=[
            hail.id,
            operateur.hail_endpoint(current_app.config['ENV']),
            unicode(operateur.operator_header_name),
            unicode(operateur.operator_api_key), operateur.email
        ],
                                          queue='send_hail_' +
                                          current_app.config['NOW'])

        client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB'])
        try:
            client.write_points([{
                "measurement":
                "hails_created",
                "tags": {
                    "added_by": current_user.email,
                    "operator": operateur.email,
                    "zupc": descriptions[0][0]['ads_insee'],
                },
                "time":
                datetime.utcnow().strftime('%Y%m%dT%H:%M:%SZ'),
                "fields": {
                    "value": 1
                }
            }])
        except Exception as e:
            current_app.logger.error('Influxdb Error: {}'.format(e))
        result = marshal({"data": [hail]}, hail_model)
        result['data'][0]['taxi']['lon'] = hail.initial_taxi_lon
        result['data'][0]['taxi']['lat'] = hail.initial_taxi_lat
        return result, 201
예제 #7
0
def store_active_taxis(frequency):
    now = datetime.utcnow()
    bound = time() - (Taxi._ACTIVITY_TIMEOUT + frequency * 60)
    map_operateur_insee_nb_active = dict()
    map_operateur_nb_active = dict()
    map_insee_nb_active = dict()
    active_taxis = set()
    insee_zupc_dict = dict()
    prefixed_taxi_ids = []
    convert = lambda d: mktime(d.timetuple())
    for taxi_id_operator in redis_store.zrangebyscore(
            current_app.config['REDIS_TIMESTAMPS'], bound, time()):
        taxi_id, operator = taxi_id_operator.split(':')
        active_taxis.add(taxi_id)
        taxi_db = Taxi.query.get(taxi_id)
        if taxi_db is None:
            current_app.logger.error('Taxi: {}, not found in database'.format(
                taxi_id))
            continue
        if taxi_db.ads is None:
            current_app.logger.error('Taxi: {} is invalid'.format(taxi_id))
            continue
#This a cache for insee to zupc.
        if not taxi_db.ads.insee in insee_zupc_dict:
            zupc = ZUPC.query.get(taxi_db.ads.zupc_id)
            if not zupc:
                current_app.logger.error('Unable to find zupc: {}'.format(
                    taxi_db.ads.zupc_id))
            zupc = zupc.parent
            insee_zupc_dict[zupc.insee] = zupc
            insee_zupc_dict[taxi_db.ads.insee] = zupc
        else:
            zupc = insee_zupc_dict[taxi_db.ads.insee]
        map_insee_nb_active.setdefault(zupc.insee, set()).add(taxi_id)
        if operator not in map_operateur_insee_nb_active:
            u = user_datastore.find_user(email=operator)
            if not u:
                current_app.logger.error('User: {} not found'.format(operator))
                continue
            map_operateur_insee_nb_active[operator] = dict()
        map_operateur_insee_nb_active[operator].setdefault(zupc.insee, set()).add(taxi_id)
        map_operateur_nb_active.setdefault(operator, set()).add(taxi_id)

    map_operateur_insee_nb_available = dict()
    map_operateur_nb_available = dict()

    available_ids = set()
    for operator, insee_taxi_ids in map_operateur_insee_nb_active.iteritems():
        for insee, taxis_ids in insee_taxi_ids.iteritems():
            for ids in izip_longest(*[taxis_ids]*100, fillvalue=None):
                pipe = redis_store.pipeline()
                for id_ in ids_:
                    pipe.sismember(current_app.config['REDIS_TIMESTAMPS'],
                                   i+':'+operator)
                res = compress(ids, pipe.execute())
                map_operateur_insee_nb_available(operator, dict()).setdefault(
                    insee, set()).union(set(res))
                available_ids.union(set(res))

    for operateur, taxis_ids in map_operateur_nb_active.iteritems():
        map_operateur_nb_active.setdefault(operateur, set()).union(
            set([t+':'+operateur for t in taxis_ids]).intersection(avaliable_ids
                )
        )


    client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB'])
    to_insert = []
    bucket_size = 100
    def insert(operator, zupc, active, available=False):
        measurement_name = "nb_taxis_every_{}".format(frequency)
        if available:
            measurement_name += '_available'
        to_insert.append({
                    "measurement": measurement_name,
                    "tags": {
                        "operator": operator,
                        "zupc": zupc
                    },
                    "time": now.strftime('%Y%m%dT%H:%M:%SZ'),
                    "fields": {
                        "value": len(active)
                    }
                }
        )
        if len(to_insert) == 100:
            current_app.logger.debug('To insert: {}'.format(to_insert))
            client.write_points(to_insert)
            to_insert[:] = []

    for operator, zupc_active in map_operateur_insee_nb_active.iteritems():
        for zupc, active in zupc_active.iteritems():
            insert(operator, zupc, active)

    for zupc, active in map_insee_nb_active.iteritems():
        insert("", zupc, active)

    for operateur, active in map_operateur_nb_active.iteritems():
        insert(operateur, "", active)

    insert("", "", active_taxis)

    for operator, zupc_available in map_operateur_insee_nb_active.iteritems():
        for zupc, available in zupc_active.iteritems():
            insert(operator, zupc, available, True)

    for zupc, available in map_insee_nb_active.iteritems():
        insert("", zupc, available, True)

    if len(to_insert) > 0:
        current_app.logger.debug('To insert: {}'.format(to_insert))
        client.write_points(to_insert)
예제 #8
0
def store_active_taxis(frequency):
    now = datetime.utcnow()
    map_operateur_insee_nb_active = dict()
    map_operateur_nb_active = dict()
    map_insee_nb_active = dict()
    active_taxis = set()
    prefixed_taxi_ids = []
    convert = lambda d: mktime(d.timetuple())
    hidden_operator = current_app.config.get('HIDDEN_OPERATOR', 'testing_operator')
    for taxi_ids_operator in get_taxis_ids_operators(frequency):
        taxis = dict()
        for tm in models.RawTaxi.get([t.split(':')[0] for t in taxi_ids_operator]):
            for t in tm:
                taxis[t['taxi_id']+':'+t['u_email']] = t
        for taxi_id_operator in taxi_ids_operator:
            taxi_id, operator = taxi_id_operator.split(':')
            if operator == hidden_operator:
                continue
            active_taxis.add(taxi_id)
            taxi_db = taxis.get(taxi_id_operator, None)
            if taxi_db is None:
                current_app.logger.error('Taxi: {}:{}, not found in database'.format(
                    taxi_id, operator))
                continue
            if 'ads_insee' not in taxi_db:
                current_app.logger.error('Taxi: {} is invalid'.format(taxi_id))
                continue
#This a cache for insee to zupc.
            if not taxi_db['ads_insee'] in store_active_taxis.insee_zupc_dict:
                zupc = models.ZUPC.query.get(taxi_db['ads_zupc_id'])
                if not zupc:
                    current_app.logger.error('Unable to find zupc: {}'.format(
                        taxi_db['ads_zupc_id']))
                    continue
                zupc = zupc.parent
                store_active_taxis.insee_zupc_dict[zupc.insee] = zupc
                store_active_taxis.insee_zupc_dict[taxi_db['ads_insee']] = zupc
            else:
                zupc = store_active_taxis.insee_zupc_dict[taxi_db['ads_insee']]
            map_insee_nb_active.setdefault(zupc.insee, set()).add(taxi_id)
            if operator not in map_operateur_insee_nb_active:
                u = user_datastore.find_user(email=operator)
                if not u:
                    current_app.logger.error('User: {} not found'.format(operator))
                    continue
                map_operateur_insee_nb_active[operator] = dict()
            map_operateur_insee_nb_active[operator].setdefault(zupc.insee, set()).add(taxi_id)
            map_operateur_nb_active.setdefault(operator, set()).add(taxi_id)

    map_operateur_insee_nb_available = dict()
    map_operateur_nb_available = dict()

    available_ids = set()
    for operator, insee_taxi_ids in map_operateur_insee_nb_active.iteritems():
        for insee, taxis_ids in insee_taxi_ids.iteritems():
            for ids in pager(taxis_ids, page_size=100):
                pipe = redis_store.pipeline()
                for id_ in ids:
                    pipe.zscore(current_app.config['REDIS_TIMESTAMPS'],
                                   id_+':'+operator)
                res = compress(ids, pipe.execute())
                map_operateur_insee_nb_available.setdefault(operator, dict()).setdefault(
                    insee, set()).union(set(res))
                available_ids.union(set(res))

    for operateur, taxis_ids in map_operateur_nb_active.iteritems():
        map_operateur_nb_active.setdefault(operateur, set()).union(
            set([t+':'+operateur for t in taxis_ids]).intersection(available_ids
                )
        )


    client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB'])
    to_insert = []
    bucket_size = 100
    def insert(operator, zupc, active, available=False):
        measurement_name = "nb_taxis_every_{}".format(frequency)
        if available:
            measurement_name += '_available'
        to_insert.append({
                    "measurement": measurement_name,
                    "tags": {
                        "operator": operator,
                        "zupc": zupc
                    },
                    "time": now.strftime('%Y%m%dT%H:%M:%SZ'),
                    "fields": {
                        "value": len(active)
                    }
                }
        )
        if len(to_insert) == 100:
            if client:
                client.write_points(to_insert)
            to_insert[:] = []

    for operator, zupc_active in map_operateur_insee_nb_active.iteritems():
        for zupc, active in zupc_active.iteritems():
            insert(operator, zupc, active)

    for zupc, active in map_insee_nb_active.iteritems():
        insert("", zupc, active)

    for operateur, active in map_operateur_nb_active.iteritems():
        insert(operateur, "", active)

    insert("", "", active_taxis)

    for operator, zupc_available in map_operateur_insee_nb_active.iteritems():
        for zupc, available in zupc_active.iteritems():
            insert(operator, zupc, available, True)

    for zupc, available in map_insee_nb_active.iteritems():
        insert("", zupc, available, True)

    if len(to_insert) > 0:
        if client:
            client.write_points(to_insert)
예제 #9
0
파일: hail.py 프로젝트: fabmob/APITaxi
    def post(self):
        hj = request.json
        hj = hj['data'][0]

        operateur = security_models.User.filter_by_or_404(
                email=hj['operateur'],
                message='Unable to find the taxi\'s operateur')

        descriptions = RawTaxi.get((hj['taxi_id'],), operateur.id)
        if len(descriptions) == 0 or len(descriptions[0]) == 0:
            abort(404, message='Unable to find taxi {} of {}'.format(
                hj['taxi_id'], hj['operateur']))
        if descriptions[0][0]['vehicle_description_status'] != 'free' or\
                not TaxiRedis(hj['taxi_id']).is_fresh(hj['operateur']):
            abort(403, message="The taxi is not available")
        customer = CustomerModel.query.filter_by(id=hj['customer_id'],
                operateur_id=current_user.id).first()
        if not customer:
            customer = CustomerModel(hj['customer_id'])
            current_app.extensions['sqlalchemy'].db.session.add(customer)
        taxi_score = redis_store.zscore(current_app.config['REDIS_GEOINDEX'],
                '{}:{}'.format(hj['taxi_id'], operateur.email))
        r = redis_store.geodecode(int(taxi_score)) if taxi_score else None
        taxi_pos = r[0] if r else None

        hail = HailModel()
        hail.customer_id = hj['customer_id']
        hail.customer_lon = hj['customer_lon']
        hail.customer_lat = hj['customer_lat']
        hail.customer_address = hj['customer_address']
        hail.customer_phone_number = hj['customer_phone_number']
        hail.taxi_id = hj['taxi_id']
        hail.initial_taxi_lat = taxi_pos[0] if r else None
        hail.initial_taxi_lon = taxi_pos[1] if r else None
        hail.operateur_id = operateur.id
        hail.status = 'received'
        current_app.extensions['sqlalchemy'].db.session.add(hail)
        current_app.extensions['sqlalchemy'].db.session.commit()

        g.hail_log = HailLog('POST', hail, request.data)

        send_request_operator.apply_async(args=[hail.id,
            operateur.hail_endpoint(current_app.config['ENV']),
            unicode(operateur.operator_header_name),
            unicode(operateur.operator_api_key), operateur.email],
            queue='send_hail_'+current_app.config['NOW'])

        client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB'])
        try:
            client.write_points([{
                "measurement": "hails_created",
                "tags": {
                    "added_by": current_user.email,
                    "operator": operateur.email,
                    "zupc": descriptions[0][0]['ads_insee'],
                    },
                "time": datetime.utcnow().strftime('%Y%m%dT%H:%M:%SZ'),
                "fields": {
                    "value": 1
                }
                }])
        except Exception as e:
            current_app.logger.error('Influxdb Error: {}'.format(e))
        result = marshal({"data": [hail]}, hail_model)
        result['data'][0]['taxi']['lon'] = hail.initial_taxi_lon
        result['data'][0]['taxi']['lat'] = hail.initial_taxi_lat
        return result, 201
예제 #10
0
def create_influx_db(dbname):
    c = influx_db.get_client()
    c.create_database(dbname)
예제 #11
0
def create_influx_db(dbname):
    c = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB'])
    if c:
        c.create_database(dbname)
    else:
        print("There is no client")
예제 #12
0
    def get(self):
        p = get_parser.parse_args()
        lon, lat = p['lon'], p['lat']
        if current_app.config['LIMITED_ZONE'] and\
            not Point(lon, lat).intersects(current_app.config['LIMITED_ZONE']):
            #It must be 403, but I don't know how our clients will react:
            return {'data': []}
        self.zupc_customer = cache_single(
            """SELECT id, parent_id, max_distance, insee
               FROM "ZUPC"
               WHERE ST_INTERSECTS(shape, 'POINT(%s %s)')
               AND parent_id = id
               ORDER BY max_distance ASC;""", (lon, lat),
            "zupc_lon_lat",
            lambda v: (v['id'], v['parent_id']),
            get_id=lambda a: (float(a[1].split(",")[0][1:].strip()),
                              float(a[1].split(",")[1][:-1].strip())))
        if len(self.zupc_customer) == 0:
            current_app.logger.debug('No zone found at {}, {}'.format(
                lat, lon))
            return {'data': []}
        zupc_id = self.zupc_customer[0][0]
        zupc_insee = self.zupc_customer[0][3]
        #We can deactivate the max radius for a certain zone
        inactive_filter_period = current_app.config['INACTIVE_FILTER_PERIOD']
        hour = datetime.now().hour
        if inactive_filter_period[0] > inactive_filter_period[1]:
            is_inactive = hour >= inactive_filter_period[0] or\
                    hour <= inactive_filter_period[1]
        else:
            is_inactive = inactive_filter_period[
                0] <= hour <= inactive_filter_period[1]
        if is_inactive:
            max_distance = current_app.config['DEFAULT_MAX_RADIUS']
        else:
            max_distance = min(
                filter(lambda v: v > 0, [v[2] for v in self.zupc_customer]) +
                [current_app.config['DEFAULT_MAX_RADIUS']])
        self.check_freshness()
        g.keys_to_delete = []
        name_redis = '{}:{}:{}'.format(lon, lat, time())
        g.keys_to_delete.append(name_redis)
        #It returns a list of all taxis near the given point
        #For each taxi you have a tuple with: (id, distance, [lat, lon])
        nb_positions = redis_store.georadius(
            current_app.config['REDIS_GEOINDEX_ID'],
            lat,
            lon,
            radius=max_distance / 1000.0,
            units='km',
            storedistkey=name_redis)
        if nb_positions == 0:
            current_app.logger.debug('No taxi found at {}, {}'.format(
                lat, lon))
            return {'data': []}
        self.parent_zupc = {r[0]: r[1] for r in self.zupc_customer}
        self.zupc_customer = {
            r[0]: r[1]
            for r in cache_in(
                'SELECT id, ST_AsBinary(shape) AS shape FROM "ZUPC" WHERE id in %s',
                {int(r1[1])
                 for r1 in self.zupc_customer},
                "zupc_parent_shape",
                lambda v: (v['id'], prep(load_wkb(bytes(v['shape'])))),
                get_id=lambda v: unicode(v[0]))
        }
        taxis = []
        offset = 0
        count = p['count'] * 4
        self.set_not_available(lon, lat, name_redis)
        while len(taxis) < p['count']:
            page_ids_distances = [
                v for v in redis_store.zrangebyscore(name_redis, 0., '+inf',
                                                     offset, count, True)
                if v[0] not in self.not_available
            ]
            offset += count
            if len(page_ids_distances) == 0:
                break
            page_ids = [v[0] for v in page_ids_distances]
            distances = [v[1] for v in page_ids_distances]
            positions = redis_store.geopos(
                current_app.config['REDIS_GEOINDEX_ID'], *page_ids)
            taxis_db = models.RawTaxi.get(page_ids)
            #We get all timestamps
            pipe = redis_store.pipeline()
            map(
                lambda l_taxis: map(
                    lambda t: pipe.zscore(
                        current_app.config['REDIS_TIMESTAMPS'], t['taxi_id'] +
                        ':' + t['u_email']), l_taxis), taxis_db)
            timestamps = pipe.execute()
            #For each member of timestamp_slices we have the first index of the first element
            #in timestamp, and the index of the last element
            #If we have taxis_db = [{t_1,}, {,}, {t_21, t_22}, {t_3,}]
            #Then we want timestamps_slices = [(0, 1), (1, 1), (1, 3), (3, 4)]
            timestamps_slices = []
            map(lambda i: timestamps_slices.append((0, len(i)))\
                if not timestamps_slices\
                else timestamps_slices.append((timestamps_slices[-1][1],
                                               timestamps_slices[-1][1]+len(i))),
                taxis_db)

            l = [
                models.RawTaxi.generate_dict(
                    t[0],
                    None,
                    None,
                    favorite_operator=p['favorite_operator'],
                    position={
                        "lon": t[1][1],
                        "lat": t[1][0]
                    },
                    distance=t[2],
                    timestamps=islice(timestamps, *t[3])) for t in izip(
                        taxis_db, positions, distances, timestamps_slices)
                if len(t) > 0 if self.filter_zone(t[0], t[1])
            ]
            taxis.extend(filter(None, l))
        client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB'])
        if client:
            try:
                client.write_points([{
                    "measurement":
                    "get_taxis_requests",
                    "tags": {
                        "zupc":
                        zupc_insee,
                        "position":
                        "{:.3f}:{:.3f}".format(float(lon), float(lat)),
                        "moteur":
                        current_user.email,
                        "customer":
                        hashlib.sha224(
                            request.headers.getlist("X-Forwarded-For")[0].
                            rpartition(' ')[-1] if 'X-Forwarded-For' in
                            request.headers else request.remote_addr
                            or 'untrackable').hexdigest()[:10]
                    },
                    "time":
                    datetime.utcnow().strftime('%Y%m%dT%H:%M:%SZ'),
                    "fields": {
                        "value": len(taxis)
                    }
                }])
            except Exception as e:
                current_app.logger.error('Influxdb Error: {}'.format(e))
        return {
            'data': sorted(taxis,
                           key=lambda t: t['crowfly_distance'])[:p['count']]
        }