Reworked TAAR as a plugin for a webservice

* Reworked taar so that it exports an entrypoint for use by taar-api
* An application wrapper is required to facilitate instrumentation of
  state within TAAR when it is under test.
* bumped to version 0.1.1
This commit is contained in:
Victor Ng 2018-07-18 11:00:55 -04:00
Родитель 791c222a63
Коммит d433430201
2 изменённых файлов: 119 добавлений и 1 удалений

Просмотреть файл

@ -3,7 +3,7 @@ from setuptools import find_packages, setup
setup(
name='mozilla-taar3',
use_scm_version=False,
version='0.0.28',
version='0.1.1',
setup_requires=['setuptools_scm', 'pytest-runner'],
tests_require=['pytest'],
include_package_data = True,
@ -33,5 +33,9 @@ setup(
'Topic :: Internet :: WWW/HTTP',
'Topic :: Scientific/Engineering :: Information Analysis'
],
entry_points="""
[taarapi_app]
app=taar.plugin:configure_plugin
""",
zip_safe=False,
)

114
taar/plugin.py Normal file
Просмотреть файл

@ -0,0 +1,114 @@
# 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 decouple import config
from flask import request
import json
# TAAR specific libraries
from taar.context import default_context
from taar.profile_fetcher import ProfileFetcher
from taar import recommenders
from taar import ProfileController
# These are configurations that are specific to the TAAR library
VALID_BRANCHES = set(['linear', 'ensemble', 'control'])
DYNAMO_REGION = config('DYNAMO_REGION', default='us-west-2')
DYNAMO_TABLE_NAME = config('DYNAMO_TABLE_NAME', default='taar_addon_data_20180206')
TAAR_MAX_RESULTS = config('TAAR_MAX_RESULTS', default=10, cast=int)
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()
def configure_plugin(app):
"""
This is a factory function that configures all the routes for
flask given a particular library.
"""
@app.route('/api/recommendations/<uuid:uuid_client_id>/')
def recommendations(uuid_client_id):
"""Return a list of recommendations provided a telemetry client_id."""
# Use the module global PROXY_MANAGER
global PROXY_MANAGER
# Coerce the uuid.UUID type into a string
client_id = str(uuid_client_id)
branch = request.args.get('branch', '')
if branch.endswith('-taar'):
branch = branch.replace("-taar", "")
if branch not in VALID_BRANCHES:
# Force branch to be a control branch if an invalid request
# comes in.
branch = 'control'
extra_data = {'branch': branch}
locale = request.args.get('locale', None)
if locale is not None:
extra_data['locale'] = locale
platform = request.args.get('platform', None)
if platform is not None:
extra_data['platform'] = platform
if PROXY_MANAGER.getResource() is None:
ctx = default_context()
dynamo_client = ProfileController(region_name=DYNAMO_REGION,
table_name=DYNAMO_TABLE_NAME)
profile_fetcher = ProfileFetcher(dynamo_client)
ctx['profile_fetcher'] = profile_fetcher
# Lock the context down after we've got basic bits installed
root_ctx = ctx.child()
r_factory = recommenders.RecommenderFactory(root_ctx)
root_ctx['recommender_factory'] = r_factory
instance = recommenders.RecommendationManager(root_ctx.child())
PROXY_MANAGER.setResource(instance)
instance = PROXY_MANAGER.getResource()
recommendations = instance.recommend(client_id=client_id,
limit=TAAR_MAX_RESULTS,
extra_data=extra_data)
# 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
class MyPlugin:
def set(self, config_options):
"""
This setter is primarily so that we can instrument the
cached RecommendationManager implementation under test.
All plugins should implement this set method to enable
overwriting configuration options with a TAAR library.
"""
global PROXY_MANAGER
if 'PROXY_RESOURCE' in config_options:
PROXY_MANAGER._resource = config_options['PROXY_RESOURCE']
return MyPlugin()