Skip to content

Commit

Permalink
feat: Cache reviews
Browse files Browse the repository at this point in the history
  • Loading branch information
anshg1214 committed Sep 5, 2022
1 parent 236a862 commit 73e4003
Show file tree
Hide file tree
Showing 13 changed files with 580 additions and 280 deletions.
17 changes: 13 additions & 4 deletions critiquebrainz/db/review.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,14 +296,16 @@ def update(review_id, *, drafted, text=None, rating=None, license_id=None, langu
db_revision.update_rating(review_id)

result = connection.execute(sqlalchemy.text("""
SELECT review.entity_id
SELECT review.entity_id,
review.entity_type,
review.user_id
FROM review
WHERE review.id = :review_id
"""), {
"review_id": review_id,
})
review = dict(result.fetchone())
invalidate_ws_entity_cache(review["entity_id"])
invalidate_ws_entity_cache(review["entity_id"], review["entity_type"], review["user_id"])


def create(*, entity_id, entity_type, user_id, is_draft, text=None, rating=None,
Expand Down Expand Up @@ -385,11 +387,11 @@ def create(*, entity_id, entity_type, user_id, is_draft, text=None, rating=None,
if rating:
db_revision.update_rating(review_id)

invalidate_ws_entity_cache(entity_id)
invalidate_ws_entity_cache(entity_id, entity_type, user_id)
return get_by_id(review_id)


def invalidate_ws_entity_cache(entity_id):
def invalidate_ws_entity_cache(entity_id, entity_type, user_id):
cache_keys_for_entity_id_key = cache.gen_key('ws_cache', entity_id)
cache_keys_to_delete = cache.smembers(cache_keys_for_entity_id_key, namespace=REVIEW_CACHE_NAMESPACE)
if cache_keys_to_delete:
Expand All @@ -402,6 +404,13 @@ def invalidate_ws_entity_cache(entity_id):
cache.delete_many(cache_keys_to_delete, namespace=REVIEW_CACHE_NAMESPACE)
cache.delete(cache_keys_for_no_entity_id_key, namespace=REVIEW_CACHE_NAMESPACE)

cache_keys_for_top_reviews_key = cache.gen_key('entity_api', entity_type, entity_id, "top_reviews")
cache_keys_for_latest_reviews_key = cache.gen_key('entity_api', entity_type, entity_id, "latest_reviews")
cache_keys_for_user_reviews_key = cache.gen_key('entity_api', entity_id, user_id, "user_reviews")
cache.delete(cache_keys_for_top_reviews_key, namespace=REVIEW_CACHE_NAMESPACE)
cache.delete(cache_keys_for_latest_reviews_key, namespace=REVIEW_CACHE_NAMESPACE)
cache.delete(cache_keys_for_user_reviews_key, namespace=REVIEW_CACHE_NAMESPACE)


# pylint: disable=too-many-branches
def get_reviews_list(connection, *, inc_drafts=False, inc_hidden=False, entity_id=None,
Expand Down
2 changes: 2 additions & 0 deletions critiquebrainz/ws/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
deploy_env = os.environ.get('DEPLOY_ENV', '')
CONSUL_CONFIG_FILE_RETRY_COUNT = 10
REVIEWS_LIMIT = 5
REVIEW_CACHE_NAMESPACE = "Review"
REVIEW_CACHE_TIMEOUT = 30 * 60 # 30 minutes


def create_app(debug=None, config_path=None):
Expand Down
74 changes: 50 additions & 24 deletions critiquebrainz/ws/artist/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
from critiquebrainz.decorators import crossdomain
from critiquebrainz.ws.exceptions import NotFound
from critiquebrainz.ws.parser import Parser
from critiquebrainz.ws import REVIEWS_LIMIT
from critiquebrainz.ws import REVIEWS_LIMIT, REVIEW_CACHE_NAMESPACE, REVIEW_CACHE_TIMEOUT
from brainzutils import cache

artist_bp = Blueprint('ws_artist', __name__)

Expand Down Expand Up @@ -229,38 +230,63 @@ def artist_entity_handler(artist_mbid):
if not artist:
raise NotFound("Can't find an artist with ID: {artist_mbid}".format(artist_mbid=artist_mbid))

user_review = None

user_id = Parser.uuid('uri', 'user_id', optional=True)
if user_id:
user_review, _ = db_review.list_reviews(
user_review_cache_key = cache.gen_key('entity_api', artist['mbid'], user_id, "user_review")
user_review = cache.get(user_review_cache_key)
if not user_review:
user_review, _ = db_review.list_reviews(
entity_id=artist['mbid'],
entity_type='artist',
user_id=user_id
)
if user_review:
user_review = db_review.to_dict(user_review[0])
else:
user_review = None

cache.set(user_review_cache_key, user_review,
expirein=REVIEW_CACHE_TIMEOUT, namespace=REVIEW_CACHE_NAMESPACE)

ratings_stats, average_rating = db_rating_stats.get_stats(artist_mbid, "artist")

top_reviews_cache_key = cache.gen_key("entity_api_artist", artist['mbid'], "top_reviews")
top_reviews_cached_result = cache.get(top_reviews_cache_key, REVIEW_CACHE_NAMESPACE)

if top_reviews_cached_result:
top_reviews, reviews_count = top_reviews_cached_result
else:
top_reviews, reviews_count = db_review.list_reviews(
entity_id=artist['mbid'],
entity_type='artist',
user_id=user_id
sort='popularity',
limit=REVIEWS_LIMIT,
offset=0,
)
if user_review:
user_review = db_review.to_dict(user_review[0])
else:
user_review = None
top_reviews = [db_review.to_dict(review) for review in top_reviews]

ratings_stats, average_rating = db_rating_stats.get_stats(artist_mbid, "artist")
cache.set(top_reviews_cache_key, (top_reviews, reviews_count),
expirein=REVIEW_CACHE_TIMEOUT, namespace=REVIEW_CACHE_NAMESPACE)

top_reviews, reviews_count = db_review.list_reviews(
entity_id=artist['mbid'],
entity_type='artist',
sort='popularity',
limit=REVIEWS_LIMIT,
offset=0,
)
latest_reviews_cache_key = cache.gen_key("entity_api_artist", artist['mbid'], "latest_reviews")
latest_reviews_cached_result = cache.get(latest_reviews_cache_key, REVIEW_CACHE_NAMESPACE)

latest_reviews, reviews_count = db_review.list_reviews(
entity_id=artist['mbid'],
entity_type='artist',
sort='published_on',
limit=REVIEWS_LIMIT,
offset=0,
)
if latest_reviews_cached_result:
latest_reviews, reviews_count = latest_reviews_cached_result
else:
latest_reviews, reviews_count = db_review.list_reviews(
entity_id=artist['mbid'],
entity_type='artist',
sort='published_on',
limit=REVIEWS_LIMIT,
offset=0,
)
latest_reviews = [db_review.to_dict(review) for review in latest_reviews]

top_reviews = [db_review.to_dict(review) for review in top_reviews]
latest_reviews = [db_review.to_dict(review) for review in latest_reviews]
cache.set(latest_reviews_cache_key, (latest_reviews, reviews_count),
expirein=REVIEW_CACHE_TIMEOUT, namespace=REVIEW_CACHE_NAMESPACE)

result = {
"artist": artist,
Expand Down
78 changes: 52 additions & 26 deletions critiquebrainz/ws/bb_author/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
from critiquebrainz.decorators import crossdomain
from critiquebrainz.ws.exceptions import NotFound
from critiquebrainz.ws.parser import Parser
from critiquebrainz.ws import REVIEWS_LIMIT
from critiquebrainz.ws import REVIEWS_LIMIT, REVIEW_CACHE_NAMESPACE, REVIEW_CACHE_TIMEOUT
from brainzutils import cache

author_bp = Blueprint('ws_author', __name__)

Expand Down Expand Up @@ -166,38 +167,63 @@ def author_entity_handler(author_bbid):
if not author:
raise NotFound("Can't find an author with ID: {author_bbid}".format(author_bbid=author_bbid))

user_review = []

user_id = Parser.uuid('uri', 'user_id', optional=True)
if user_id:
user_review, _ = db_review.list_reviews(
user_review_cache_key = cache.gen_key('entity_api', author['bbid'], user_id, "user_review")
user_review = cache.get(user_review_cache_key)
if not user_review:
user_review, _ = db_review.list_reviews(
entity_id=author['bbid'],
entity_type='bb_author',
user_id=user_id
)
if user_review:
user_review = db_review.to_dict(user_review[0])
else:
user_review = []

cache.set(user_review_cache_key, user_review,
expirein=REVIEW_CACHE_TIMEOUT, namespace=REVIEW_CACHE_NAMESPACE)

ratings_stats, average_rating = db_rating_stats.get_stats(author_bbid, "bb_author")

top_reviews_cache_key = cache.gen_key("entity_api_bb_author", author['bbid'], "top_reviews")
top_reviews_cached_result = cache.get(top_reviews_cache_key, REVIEW_CACHE_NAMESPACE)

if top_reviews_cached_result:
top_reviews, reviews_count = top_reviews_cached_result
else:
top_reviews, reviews_count = db_review.list_reviews(
entity_id=author['bbid'],
entity_type='bb_author',
user_id=user_id
sort='popularity',
limit=REVIEWS_LIMIT,
offset=0,
)
if user_review:
user_review = db_review.to_dict(user_review[0])
else:
user_review = None
top_reviews = [db_review.to_dict(review) for review in top_reviews]

ratings_stats, average_rating = db_rating_stats.get_stats(author_bbid, "bb_author")
cache.set(top_reviews_cache_key, (top_reviews, reviews_count),
expirein=REVIEW_CACHE_TIMEOUT, namespace=REVIEW_CACHE_NAMESPACE)

latest_reviews_cache_key = cache.gen_key("entity_api_bb_author", author['bbid'], "latest_reviews")
latest_reviews_cached_result = cache.get(latest_reviews_cache_key, REVIEW_CACHE_NAMESPACE)

if latest_reviews_cached_result:
latest_reviews, reviews_count = latest_reviews_cached_result
else:
latest_reviews, reviews_count = db_review.list_reviews(
entity_id=author['bbid'],
entity_type='bb_author',
sort='published_on',
limit=REVIEWS_LIMIT,
offset=0,
)
latest_reviews = [db_review.to_dict(review) for review in latest_reviews]

top_reviews, reviews_count = db_review.list_reviews(
entity_id=author['bbid'],
entity_type='bb_author',
sort='popularity',
limit=REVIEWS_LIMIT,
offset=0,
)

latest_reviews, reviews_count = db_review.list_reviews(
entity_id=author['bbid'],
entity_type='bb_author',
sort='published_on',
limit=REVIEWS_LIMIT,
offset=0,
)

top_reviews = [db_review.to_dict(review) for review in top_reviews]
latest_reviews = [db_review.to_dict(review) for review in latest_reviews]
cache.set(latest_reviews_cache_key, (latest_reviews, reviews_count),
expirein=REVIEW_CACHE_TIMEOUT, namespace=REVIEW_CACHE_NAMESPACE)

result = {
"author": author,
Expand Down
78 changes: 52 additions & 26 deletions critiquebrainz/ws/bb_edition_group/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
from critiquebrainz.decorators import crossdomain
from critiquebrainz.ws.exceptions import NotFound
from critiquebrainz.ws.parser import Parser
from critiquebrainz.ws import REVIEWS_LIMIT
from critiquebrainz.ws import REVIEWS_LIMIT, REVIEW_CACHE_NAMESPACE, REVIEW_CACHE_TIMEOUT
from brainzutils import cache

edition_group_bp = Blueprint('ws_edition_group', __name__)

Expand Down Expand Up @@ -144,38 +145,63 @@ def edition_group_entity_handler(edition_group_bbid):
if not edition_group:
raise NotFound("Can't find an edition_group with ID: {edition_group_bbid}".format(edition_group_bbid=edition_group_bbid))

user_review = []

user_id = Parser.uuid('uri', 'user_id', optional=True)
if user_id:
user_review, _ = db_review.list_reviews(
user_review_cache_key = cache.gen_key('entity_api', edition_group['bbid'], user_id, "user_review")
user_review = cache.get(user_review_cache_key)
if not user_review:
user_review, _ = db_review.list_reviews(
entity_id=edition_group['bbid'],
entity_type='bb_edition_group',
user_id=user_id
)
if user_review:
user_review = db_review.to_dict(user_review[0])
else:
user_review = []

cache.set(user_review_cache_key, user_review,
expirein=REVIEW_CACHE_TIMEOUT, namespace=REVIEW_CACHE_NAMESPACE)

ratings_stats, average_rating = db_rating_stats.get_stats(edition_group_bbid, "bb_edition_group")

top_reviews_cache_key = cache.gen_key("entity_api_bb_edition_group", edition_group['bbid'], "top_reviews")
top_reviews_cached_result = cache.get(top_reviews_cache_key, REVIEW_CACHE_NAMESPACE)

if top_reviews_cached_result:
top_reviews, reviews_count = top_reviews_cached_result
else:
top_reviews, reviews_count = db_review.list_reviews(
entity_id=edition_group['bbid'],
entity_type='bb_edition_group',
user_id=user_id
sort='popularity',
limit=REVIEWS_LIMIT,
offset=0,
)
if user_review:
user_review = db_review.to_dict(user_review[0])
else:
user_review = None
top_reviews = [db_review.to_dict(review) for review in top_reviews]

ratings_stats, average_rating = db_rating_stats.get_stats(edition_group_bbid, "bb_edition_group")
cache.set(top_reviews_cache_key, (top_reviews, reviews_count),
expirein=REVIEW_CACHE_TIMEOUT, namespace=REVIEW_CACHE_NAMESPACE)

latest_reviews_cache_key = cache.gen_key("entity_api_bb_edition_group", edition_group['bbid'], "latest_reviews")
latest_reviews_cached_result = cache.get(latest_reviews_cache_key, REVIEW_CACHE_NAMESPACE)

if latest_reviews_cached_result:
latest_reviews, reviews_count = latest_reviews_cached_result
else:
latest_reviews, reviews_count = db_review.list_reviews(
entity_id=edition_group['bbid'],
entity_type='bb_edition_group',
sort='published_on',
limit=REVIEWS_LIMIT,
offset=0,
)
latest_reviews = [db_review.to_dict(review) for review in latest_reviews]

top_reviews, reviews_count = db_review.list_reviews(
entity_id=edition_group['bbid'],
entity_type='bb_edition_group',
sort='popularity',
limit=REVIEWS_LIMIT,
offset=0,
)

latest_reviews, reviews_count = db_review.list_reviews(
entity_id=edition_group['bbid'],
entity_type='bb_edition_group',
sort='published_on',
limit=REVIEWS_LIMIT,
offset=0,
)

top_reviews = [db_review.to_dict(review) for review in top_reviews]
latest_reviews = [db_review.to_dict(review) for review in latest_reviews]
cache.set(latest_reviews_cache_key, (latest_reviews, reviews_count),
expirein=REVIEW_CACHE_TIMEOUT, namespace=REVIEW_CACHE_NAMESPACE)

result = {
"edition_group": edition_group,
Expand Down
Loading

0 comments on commit 73e4003

Please sign in to comment.