taar-api-lite/taar_api/app.py

131 строка
3.9 KiB
Python

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from flask import Flask
from flask import request
from dockerflow.flask import Dockerflow
from taar_lite.recommenders import GuidBasedRecommender
from srgutil.interfaces import IMozLogging
from srgutil.context import default_context
import json
from decouple import config
import optparse
app = Flask(__name__)
dockerflow = Dockerflow(app)
VALID_BRANCHES = set(['linear', 'ensemble', 'control'])
TAAR_MAX_RESULTS = config('TAAR_MAX_RESULTS', default=4, cast=int)
CACHE_URL = config('CACHE_URL', default='redis://redis:6379/0')
class ResourceProxy(object):
def __init__(self):
self._resource = None
def setResource(self, rsrc):
self._resource = rsrc
def getResource(self):
return self._resource
PROXY_MANAGER = ResourceProxy()
@app.route('/taarlite/api/v1/addon_recommendations/<string:guid>/')
def recommendations(guid):
"""Return a list of recommendations provided a telemetry client_id."""
# Use the module global PROXY_MANAGER
global PROXY_MANAGER
if PROXY_MANAGER.getResource() is None:
ctx = default_context()
logger = ctx[IMozLogging].get_logger('taar-api-lite')
ctx['CACHE_URL'] = CACHE_URL
logger.info("Set CACHE_URL to: [{}]".format(ctx['CACHE_URL']))
# Lock the context down after we've got basic bits installed
root_ctx = ctx.child()
instance = GuidBasedRecommender(root_ctx)
PROXY_MANAGER.setResource(instance)
instance = PROXY_MANAGER.getResource()
cdict = {'guid': guid}
normalization_type = request.args.get('normalize', None)
if normalization_type is not None:
cdict['normalize'] = normalization_type
recommendations = instance.recommend(client_data=cdict,
limit=TAAR_MAX_RESULTS)
if len(recommendations) != TAAR_MAX_RESULTS:
recommendations = []
# Strip out weights from TAAR results to maintain compatibility
# with TAAR 1.0
jdata = {"results": [x[0] for x in recommendations]}
response = app.response_class(
response=json.dumps(jdata),
status=200,
mimetype='application/json'
)
return response
def flaskrun(app, default_host="127.0.0.1", default_port="8000"):
"""
Takes a flask.Flask instance and runs it. Parses
command-line flags to configure the app.
"""
# Set up the command-line options
parser = optparse.OptionParser()
parser.add_option("-H", "--host",
help="Hostname of the Flask app " +
"[default %s]" % default_host,
default=default_host)
parser.add_option("-P", "--port",
help="Port for the Flask app " +
"[default %s]" % default_port,
default=default_port)
# Two options useful for debugging purposes, but
# a bit dangerous so not exposed in the help message.
parser.add_option("-d", "--debug",
action="store_true", dest="debug",
help=optparse.SUPPRESS_HELP)
parser.add_option("-p", "--profile",
action="store_true", dest="profile",
help=optparse.SUPPRESS_HELP)
options, _ = parser.parse_args()
# If the user selects the profiling option, then we need
# to do a little extra setup
if options.profile:
from werkzeug.contrib.profiler import ProfilerMiddleware
app.config['PROFILE'] = True
app.wsgi_app = ProfilerMiddleware(app.wsgi_app, restrictions=[30])
options.debug = True
app.run(
debug=options.debug,
host=options.host,
port=int(options.port)
)
if __name__ == '__main__':
flaskrun(app)