-
Notifications
You must be signed in to change notification settings - Fork 0
/
cache.py
112 lines (94 loc) · 3.13 KB
/
cache.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
from models.redis_connection import get_client
from models import Article
import simplejson as json
def _generate_articles_key(sort_by):
return ":".join([Article.__tablename__, sort_by])
def fetch_articles(sort_by):
"""Fetches all the articles from postgresql and construct a set sorted by :sort_by DESC
Args:
sort_by(str): the sort key applied to articles
Returns:
None
"""
articles = Article.query.filter_by(is_active=True).all()
key = _generate_articles_key(sort_by)
redis_client = get_client(key)
data = dict()
for article in articles:
data[str(article.id)] = getattr(article, sort_by)
redis_client.zadd(key, **data)
def get_articles(user, sort_by, offset=0, limit=10):
"""Gets articles from redis or postgresql
Args:
user (User): the current user
sort_by (str): the sort key
offset (int): offset
limit (int): limit
Returns:
An array of articles (formatted by json_data) sorted by :sort_by and limited by :limit started from :offset
"""
rev = sort_by[0] == '-'
if rev:
sort_by = sort_by[1:]
key = _generate_articles_key(sort_by)
redis_client = get_client(key)
if not redis_client.exists(key):
fetch_articles(sort_by)
start = offset
stop = offset + limit - 1
if rev:
article_ids = redis_client.zrevrange(key, start, stop)
else:
article_ids = redis_client.zrange(key, start, stop)
articles = []
for id in article_ids:
articles.append(get_article(id))
return articles
def get_article(id, user=None):
"""Gets a single article (formatted by json_data) from redis or postgresql
And performs some pre-filters for the current user
Args:
id (int): id
user (User): the current user
Returns:
None if the article is not existed or a dict of article data
"""
id = int(id)
key = Article.cache_key(id)
redis_client = get_client(key)
article = None
if not redis_client.exists(key):
article = Article.find_by_pk(id)
if article:
data = article.json_data()
redis_client.set(key, json.dumps(data))
article = data
else:
if redis_client.type(key) == 'hash':
print redis_client
article = json.loads(redis_client.get(key))
article['user_vote'] = Article.check_vote(user, article['id'])
return article
def update_article(id, article=None):
"""Updates the cache of article :id
Args:
id (int): article id
article (Article): if not provided, an article will be queried from postgresql
Returns:
Article
"""
id = int(id)
if not article:
article = Article.find_by_pk(id)
if article:
key = Article.cache_key(id)
redis_client = get_client(key)
data = article.json_data()
redis_client.set(key, json.dumps(data))
return article
def update_sorted_articles(article, sort_by):
key = _generate_articles_key(sort_by)
redis_client = get_client(key)
data = dict()
data[str(article.id)] = getattr(article, sort_by)
redis_client.zadd(key, **data)