Skip to content

Commit 85ccb5a

Browse files
committed
reddit: cache user profile API fetches for 5m to avoid repeating them
...when fetching multiiple comments or posts from the same author. snarfed/bridgy#1021
1 parent d521dde commit 85ccb5a

File tree

3 files changed

+26
-5
lines changed

3 files changed

+26
-5
lines changed

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,9 @@ Changelog
338338
* Bug fix: URL-encode list names in API calls.
339339
* Bug fix: propagate alt text into AS1 `photo.displayName` so that it gets all the way into microformats2 JSON and HTML ([#183](https://github.com/snarfed/granary/issues/183)).
340340
* Reddit:
341-
* Fix `post_id()`.
341+
* Implement `post_id()`.
342+
* Cache user data fetched from the API for 5m to avoid repeating user profile API requests ([bridgy#1021](https://github.com/snarfed/bridgy/issues/1021)).
343+
when fetching multiple comments or posts from the same author
342344
* Bug fix: use 'displayName' instead of 'name' in AS1 objects for submissions.
343345
* Bug fix: use tag URIs for activity ids.
344346
* ActivityStreams 2:

granary/reddit.py

+21-4
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,24 @@
99
PRAW API docs:
1010
https://praw.readthedocs.io/
1111
"""
12-
13-
from . import source
1412
import logging
15-
from oauth_dropins import reddit
16-
from oauth_dropins.webutil import appengine_info, util
13+
import operator
1714
import re
1815
import urllib.parse, urllib.request
16+
import threading
1917

18+
from cachetools import cachedmethod, TTLCache
19+
from oauth_dropins import reddit
20+
from oauth_dropins.webutil import appengine_info, util
2021
import praw
2122
from prawcore.exceptions import NotFound
2223

24+
from . import source
25+
26+
USER_CACHE_TIME = 5 * 60 # 5 minute expiration, in seconds
27+
user_cache = TTLCache(1000, USER_CACHE_TIME)
28+
user_cache_lock = threading.RLock()
29+
2330

2431
class Reddit(source.Source):
2532
"""Reddit source class. See file docstring and Source class for details."""
@@ -57,13 +64,23 @@ def post_id(self, url):
5764
if len(path_parts) >= 2:
5865
return path_parts[-2]
5966

67+
@cachedmethod(lambda self: user_cache, lock=lambda self: user_cache_lock,
68+
key=lambda user: getattr(user, 'name', None))
6069
def praw_to_actor(self, praw_user):
6170
"""Converts a PRAW Redditor to an actor.
6271
6372
Makes external calls to fetch data from the Reddit API.
6473
6574
https://praw.readthedocs.io/en/latest/code_overview/models/redditor.html
6675
76+
Caches fetched user data for 5m to avoid repeating user profile API requests
77+
when fetching multiple comments or posts from the same author. Background:
78+
https://github.com/snarfed/bridgy/issues/1021
79+
80+
Ideally this would be part of PRAW, but they seem uninterested:
81+
https://github.com/praw-dev/praw/issues/131
82+
https://github.com/praw-dev/praw/issues/1140
83+
6784
Args:
6885
user: PRAW Redditor object
6986

granary/tests/test_reddit.py

+2
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ def setUp(self):
175175
self.submission_link.selftext = ''
176176
self.submission_link.url = 'https://reddit.com/ezv3f2'
177177

178+
reddit.user_cache.clear()
179+
178180
def test_user_url(self):
179181
self.assert_equals('https://reddit.com/user/foo', self.reddit.user_url('foo'))
180182

0 commit comments

Comments
 (0)