feed_plugin: fix bug of overwriting entries before returning them

The entries variables was shared by two threads, the thread of the
request and the relodaing thread.
This commit is contained in:
Benjamin Dauvergne 2014-02-06 14:18:25 +01:00
parent ff517765c6
commit 4528aaa943
2 changed files with 36 additions and 30 deletions

View File

@ -48,7 +48,7 @@ class ShowUserFeedPlugin(CMSPluginBase):
feeds = models.Feed.objects.filter(feedpreference__user=user) \
.order_by('id')
for feed in feeds:
feed_entries = feed.get_feed_entries(feed, instance.limit,
feed_entries = feed.get_feed_entries(instance.limit,
instance.timeout)
if feed_entries:
for date, title, link in feed_entries:

View File

@ -42,37 +42,43 @@ class Feed(models.Model):
verbose_name=_('CSS classes'),
blank=True)
def get_feed_entries(self, feed, limit=10, timeout=3600):
url = feed.url
h = hashlib.md5(url).hexdigest()
key = 'rss-feed-{0}'.format(h)
entries, stamp = cache.get(key, (None, None))
def load(self, now=None, limit=9999):
if now is None:
now = datetime.datetime.utcnow()
feed = feedparser.parse(self.url)
key = self.cache_key()
entries = []
for entry in feed.entries:
for attribute in ('published_parsed', 'updated_parsed',
'created_parsed', 'expired_parsed'):
date = getattr(entry, attribute, None)
if date is not None:
break
if date is None:
continue
title = strip_tags(entry.title.strip())
if not title:
title = strip_tags(entry.description.strip())
title = ' '.join(title.split(' ')[:30])
if not title:
continue
entries.append((date, title, entry.link))
entries.sort(reverse=True)
entries = entries[:limit]
cache.set(key, (entries, now))
duration = datetime.datetime.utcnow()-now
logger.debug('loaded RSS feed %r in %s seconds', self.url, duration.seconds)
return entries
def cache_key(self):
return hashlib.md5(self.url).hexdigest()
def get_feed_entries(self, limit=10, timeout=3600):
key = self.cache_key()
now = datetime.datetime.utcnow()
entries, stamp = cache.get(key, (None, None))
if entries is None or now-stamp > datetime.timedelta(seconds=timeout):
def load():
feed = feedparser.parse(url)
entries = []
for entry in feed.entries:
for attribute in ('published_parsed', 'updated_parsed',
'created_parsed', 'expired_parsed'):
date = getattr(entry, attribute, None)
if date is not None:
break
if date is None:
continue
title = strip_tags(entry.title.strip())
if not title:
title = strip_tags(entry.description.strip())
title = ' '.join(title.split(' ')[:30])
if not title:
continue
entries.append((date, title, entry.link))
entries.sort(reverse=True)
entries = entries[:limit]
cache.set(key, (entries, now))
duration = datetime.datetime.utcnow()-now
logger.debug('loaded RSS feed %r in %s seconds', url, duration.seconds)
utils.launch_in_thread(key, load)
utils.launch_in_thread(key, self.load, now, limit)
return entries