Mercurial > hg > Feedworm
view backend/couchdb/CouchDbBackend.py @ 204:4cb22b47b659
Due to a bug in CouchDB it's possible that a view still references deleted documents. Detect this case and don't add NoneType objects into the list of feeds.
author | dirk |
---|---|
date | Tue, 03 Apr 2012 05:35:13 +0200 |
parents | 50b578588405 |
children | 1ac0b8e2feae 524cbf9e413c |
line wrap: on
line source
from FeedUpdater import FeedUpdater from Preferences import Preferences from backend.AbstractBackend import AbstractBackend from backend.couchdb import CouchDb from backend.couchdb.Feed import Feed from backend.couchdb.FeedEntry import FeedEntry import couchdb import logging class CouchDbBackend(AbstractBackend): ''' Backend that uses CouchDB for persistence ''' def __init__(self): CouchDb.init() server = self._initServer() self.database = server[CouchDb.database] self.prefs = None def _initServer(self): if CouchDb.database_url is not None: return couchdb.Server(CouchDb.database_url) else: return couchdb.Server() def preferences(self): if self.prefs is None: self.prefs = Preferences(self.database) return self.prefs # # handling of feeds # def getFeeds(self): if self.preferences().showOnlyUnreadFeeds(): self.feeds = self._getUnreadFeeds() else: # make sure that the results are actually fetched into memory, otherwise we'll pass # a ViewResults instance around which is not what we want self.feeds = list(Feed.all(self.database)) return self.feeds def _getUnreadFeeds(self): viewResults = self.database.view(CouchDb.feedsWithUnreadEntries(), group=True) feedsWithUnreadEntries = [] for row in viewResults: feed = Feed.load(self.database, row["key"]) # see https://issues.apache.org/jira/browse/COUCHDB-1279 # it's possible that the view references documents that have already been deleted if feed is not None: feedsWithUnreadEntries.append(feed) return feedsWithUnreadEntries def _retrieveEntriesForSelectedFeed(self, hideReadEntries): viewResults = FeedEntry.entriesForFeed(self.selectedFeed, self.database) if hideReadEntries: filterFunc = lambda feedEntry: feedEntry.read == False viewResults = filter(filterFunc, viewResults) return viewResults def markSelectedFeedAsRead(self): for feedEntry in self.entriesForSelectedFeed(): feedEntry.markRead(self.database) # # handling of the selected feed entry # def _markSelectedFeedEntryRead(self): self.selectedFeedEntry.markRead(self.database) def toggleSelectedFeedEntryRead(self): self.selectedFeedEntry.toggleRead(self.database) def createFeed(self, url): feed = Feed.create(url) feed.store(self.database) FeedUpdater(self.database, self.preferences()).update(feed) def updateFeed(self, feed, changes): for key in changes.keys(): feed[key] = changes[key] feed.store(self.database) def deleteSelectedFeed(self): viewResults = self.database.view(CouchDb.feedEntriesByFeed(), key=self.selectedFeed.id) for row in viewResults: del self.database[row.id] del self.database[self.selectedFeed.id] def entriesForFeed(self, feed, hideReadEntries): viewName = CouchDb.feedEntriesByFeed() if hideReadEntries: viewName = CouchDb.unreadFeedEntriesByFeed() return list(FeedEntry.view(self.database, viewName)) def markFeedEntriesAsRead(self, indices): for index in indices: feedEntry = self.entriesForSelectedFeed()[index] feedEntry.markRead(self.database) def updateAllFeeds(self): # TODO use a view instead of iterating all feeds allFeeds = Feed.all(self.database) for feed in allFeeds: if feed.needsUpdate(): FeedUpdater(self.database, self.preferences()).update(feed) def expireFeedEntries(self): expireDate = self._calculateExpireDate() logger = logging.getLogger("expiry") logger.info("expiring entries older than " + str(expireDate)) for entry in FeedEntry.getReadFeedEntriesOlderThan(expireDate, self.database): del self.database[entry.id]