93 lines
2.8 KiB
Python
93 lines
2.8 KiB
Python
import datetime
|
|
from flask import current_app
|
|
from flask import jsonify
|
|
from functools import wraps
|
|
import jsonschema
|
|
import math
|
|
|
|
from collector.api.app import db
|
|
|
|
|
|
def handle_response(http_code, *path):
|
|
"""Checks response, if VALIDATE_RESPONSE in app.config is set to True
|
|
and path is not empty.
|
|
Jsonifies response, adds http_code to returning values.
|
|
|
|
:param http_code:
|
|
:type http_code: integer
|
|
:param path: path to response json schema
|
|
:type path: collection of strings
|
|
:return: tuple of jsonifyed response and http_code
|
|
"""
|
|
def wrapper(fn):
|
|
@wraps(fn)
|
|
def decorated(*args, **kwargs):
|
|
response = fn(*args, **kwargs)
|
|
current_app.logger.debug(
|
|
"Processing response: {}".format(response)
|
|
)
|
|
if current_app.config.get('VALIDATE_RESPONSE', False) and path:
|
|
current_app.logger.debug(
|
|
"Validating response: {}".format(response)
|
|
)
|
|
jsonschema_ext = current_app.extensions.get('jsonschema')
|
|
jsonschema.validate(response, jsonschema_ext.get_schema(path))
|
|
current_app.logger.debug(
|
|
"Response validated: {}".format(response)
|
|
)
|
|
current_app.logger.debug(
|
|
"Response processed: {}".format(response)
|
|
)
|
|
return jsonify(response), http_code
|
|
return decorated
|
|
return wrapper
|
|
|
|
|
|
def exec_time(fn):
|
|
"""Adds 'exec_time' into function result dict. Execution time is
|
|
in seconds with microseconds. Decorator should be applied
|
|
after handle_response (before response is jsonified) and before
|
|
db_transaction (to take account of DB transaction processing).
|
|
"""
|
|
@wraps(fn)
|
|
def decorated(*args, **kwargs):
|
|
start = datetime.datetime.now()
|
|
resp = fn(*args, **kwargs)
|
|
end = datetime.datetime.now()
|
|
td = end - start
|
|
resp['exec_time'] = float('%d.%06d' % (td.seconds, td.microseconds))
|
|
return resp
|
|
return decorated
|
|
|
|
|
|
def db_transaction(fn):
|
|
"""Wraps function call into DB transaction
|
|
"""
|
|
@wraps(fn)
|
|
def decorated(*args, **kwargs):
|
|
db.session.begin()
|
|
try:
|
|
result = fn(*args, **kwargs)
|
|
db.session.commit()
|
|
return result
|
|
except Exception:
|
|
db.session.rollback()
|
|
raise
|
|
return decorated
|
|
|
|
|
|
def split_collection(collection, chunk_size=1000):
|
|
chunks_num = int(math.ceil(float(len(collection)) / chunk_size))
|
|
for i in xrange(chunks_num):
|
|
start = i * chunk_size
|
|
end = start + chunk_size
|
|
yield collection[start:end]
|
|
|
|
|
|
def build_index(dicts_coll, *fields):
|
|
index = {}
|
|
for d in dicts_coll:
|
|
idx = tuple([d[f] for f in fields])
|
|
index[idx] = d
|
|
return index
|