Skip to content

Commit d0d6d24

Browse files
committed
voting: Only need to lock when updating user's liked links
1 parent c226567 commit d0d6d24

File tree

1 file changed

+78
-76
lines changed

1 file changed

+78
-76
lines changed

r2/r2/lib/voting.py

+78-76
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ def process_message(msg):
116116
user = Account._byID(vote_data.pop("user_id"))
117117
link = Link._by_fullname(vote_data.pop("thing_fullname"))
118118

119+
# create the vote and update the voter's liked/disliked under lock so
120+
# that the vote state and cached query are consistent
119121
lock_key = "vote-%s-%s" % (user._id36, link._fullname)
120122
with g.make_lock("voting", lock_key, timeout=5):
121123
print "Processing vote by %s on %s %s" % (user, link, vote_data)
@@ -137,42 +139,9 @@ def process_message(msg):
137139
vote.commit()
138140
timer.intermediate("create_vote_object")
139141

140-
vote_valid = vote.is_automatic_initial_vote or vote.effects.affects_score
141-
link_valid = not (link._spam or link._deleted)
142-
143-
if vote_valid and link_valid:
144-
# these sorts can be changed by voting - we don't need to do "new"
145-
# since that's taken care of by new_link
146-
SORTS = ["hot", "top", "controversial"]
147-
148-
author = Account._byID(link.author_id)
149-
add_queries(
150-
queries=[get_submitted(author, sort, 'all') for sort in SORTS],
151-
insert_items=link,
152-
)
153-
timer.intermediate("author_queries")
154-
155-
sr = link.subreddit_slow
156-
add_queries(
157-
queries=[get_links(sr, sort, "all") for sort in SORTS],
158-
insert_items=link,
159-
)
160-
timer.intermediate("subreddit_queries")
161-
162-
parsed = UrlParser(link.url)
163-
if not is_subdomain(parsed.hostname, 'imgur.com'):
164-
domains = parsed.domain_permutations()
165-
add_queries(
166-
queries=[
167-
get_domain_links(domain, sort, "all")
168-
for domain, sort in product(domains, SORTS)
169-
],
170-
insert_items=link,
171-
)
172-
timer.intermediate("domain_queries")
173-
174142
with CachedQueryMutator() as m:
175-
# if this is a changed vote, remove from the previous cached query
143+
# if this is a changed vote, remove from the previous cached
144+
# query
176145
if vote.previous_vote:
177146
if vote.previous_vote.is_upvote:
178147
m.delete(get_liked(vote.user), [vote.previous_vote])
@@ -187,8 +156,42 @@ def process_message(msg):
187156

188157
timer.intermediate("voter_likes")
189158

190-
timer.stop()
191-
timer.flush()
159+
vote_valid = vote.is_automatic_initial_vote or vote.effects.affects_score
160+
link_valid = not (link._spam or link._deleted)
161+
162+
if vote_valid and link_valid:
163+
# these sorts can be changed by voting - we don't need to do "new"
164+
# since that's taken care of by new_link
165+
SORTS = ["hot", "top", "controversial"]
166+
167+
author = Account._byID(link.author_id)
168+
add_queries(
169+
queries=[get_submitted(author, sort, 'all') for sort in SORTS],
170+
insert_items=link,
171+
)
172+
timer.intermediate("author_queries")
173+
174+
sr = link.subreddit_slow
175+
add_queries(
176+
queries=[get_links(sr, sort, "all") for sort in SORTS],
177+
insert_items=link,
178+
)
179+
timer.intermediate("subreddit_queries")
180+
181+
parsed = UrlParser(link.url)
182+
if not is_subdomain(parsed.hostname, 'imgur.com'):
183+
domains = parsed.domain_permutations()
184+
add_queries(
185+
queries=[
186+
get_domain_links(domain, sort, "all")
187+
for domain, sort in product(domains, SORTS)
188+
],
189+
insert_items=link,
190+
)
191+
timer.intermediate("domain_queries")
192+
193+
timer.stop()
194+
timer.flush()
192195

193196
amqp.consume_items(qname, process_message, verbose=False)
194197

@@ -218,52 +221,51 @@ def process_message(msg):
218221
user = Account._byID(vote_data.pop("user_id"))
219222
comment = Comment._by_fullname(vote_data.pop("thing_fullname"))
220223

221-
lock_key = "vote-%s-%s" % (user._id36, comment._fullname)
222-
with g.make_lock("voting", lock_key, timeout=5):
223-
print "Processing vote by %s on %s %s" % (user, comment, vote_data)
224+
print "Processing vote by %s on %s %s" % (user, comment, vote_data)
224225

225-
try:
226-
vote = Vote(
227-
user,
228-
comment,
229-
direction=vote_data["direction"],
230-
date=datetime.utcfromtimestamp(vote_data["date"]),
231-
data=vote_data["data"],
232-
event_data=vote_data.get("event_data"),
233-
)
234-
except TypeError as e:
235-
# a vote on an invalid type got in the queue, just skip it
236-
g.log.exception("Invalid type: %r", e.message)
237-
return
226+
try:
227+
vote = Vote(
228+
user,
229+
comment,
230+
direction=vote_data["direction"],
231+
date=datetime.utcfromtimestamp(vote_data["date"]),
232+
data=vote_data["data"],
233+
event_data=vote_data.get("event_data"),
234+
)
235+
except TypeError as e:
236+
# a vote on an invalid type got in the queue, just skip it
237+
g.log.exception("Invalid type: %r", e.message)
238+
return
238239

239-
vote.commit()
240-
timer.intermediate("create_vote_object")
240+
vote.commit()
241+
timer.intermediate("create_vote_object")
241242

242-
vote_valid = vote.is_automatic_initial_vote or vote.effects.affects_score
243-
comment_valid = not (comment._spam or comment._deleted)
243+
# update queries
244+
vote_valid = vote.is_automatic_initial_vote or vote.effects.affects_score
245+
comment_valid = not (comment._spam or comment._deleted)
244246

245-
if not (vote_valid and comment_valid):
246-
return
247+
if not (vote_valid and comment_valid):
248+
return
247249

248-
# these sorts can be changed by voting - we don't need to do "new"
249-
# since that's taken care of by new_comment
250-
SORTS = ["hot", "top", "controversial"]
250+
# these sorts can be changed by voting - we don't need to do "new"
251+
# since that's taken care of by new_comment
252+
SORTS = ["hot", "top", "controversial"]
251253

252-
author = Account._byID(comment.author_id)
253-
add_queries(
254-
queries=[get_comments(author, sort, 'all') for sort in SORTS],
255-
insert_items=comment,
256-
)
257-
timer.intermediate("author_queries")
254+
author = Account._byID(comment.author_id)
255+
add_queries(
256+
queries=[get_comments(author, sort, 'all') for sort in SORTS],
257+
insert_items=comment,
258+
)
259+
timer.intermediate("author_queries")
258260

259-
# update the score periodically when a comment has many votes
260-
update_threshold = g.live_config['comment_vote_update_threshold']
261-
update_period = g.live_config['comment_vote_update_period']
262-
num_votes = comment.num_votes
263-
if num_votes <= update_threshold or num_votes % update_period == 0:
264-
add_to_commentstree_q(comment)
261+
# update the score periodically when a comment has many votes
262+
update_threshold = g.live_config['comment_vote_update_threshold']
263+
update_period = g.live_config['comment_vote_update_period']
264+
num_votes = comment.num_votes
265+
if num_votes <= update_threshold or num_votes % update_period == 0:
266+
add_to_commentstree_q(comment)
265267

266-
timer.stop()
267-
timer.flush()
268+
timer.stop()
269+
timer.flush()
268270

269271
amqp.consume_items(qname, process_message, verbose=False)

0 commit comments

Comments
 (0)