summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--lib/feed2imap/cache.rb45
-rw-r--r--lib/feed2imap/feed2imap.rb2
-rwxr-xr-xtest/tc_cache.rb12
4 files changed, 46 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index 5a82c63..6560126 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
Feed2Imap 0.2 (date unknown)
============================
+* Fixed a problem with feeds with strange caching bugs (old items going away
+ and coming back)
* The text version is now encoded in iso-8859-1 instead of utf-8.
* The subject is now MIME-encoded in utf-8. It works with mutt & evo.
* No longer overwrite mail flags (Read, Important,..) when updating an item.
diff --git a/lib/feed2imap/cache.rb b/lib/feed2imap/cache.rb
index c984a5d..48913f0 100644
--- a/lib/feed2imap/cache.rb
+++ b/lib/feed2imap/cache.rb
@@ -35,10 +35,10 @@ class ItemCache
return @channels[id].get_new_items(items)
end
- # Replace the existing cached items by those ones
- def update_cache(id, items)
+ # Commit changes to the cache
+ def commit_cache(id)
@channels[id] ||= CachedChannel::new
- @channels[id].update(items)
+ @channels[id].commit
end
# Get the last time the cache was updated
@@ -91,18 +91,36 @@ class ItemCache
end
class CachedChannel
+ # Size of the cache for each feed
+ CACHESIZE = 50
+
attr_accessor :lastcheck, :items
def initialize
@lastcheck = Time::at(0)
@items = []
+ @itemstemp = [] # see below
+ @nbnewitems = 0
end
+ # Let's explain @items and @itemstemp.
+ # @items contains the CachedItems serialized to the disk cache.
+ # The - quite complicated - get_new_items method fills in @itemstemp
+ # but leaves @items unchanged.
+ # Later, the commit() method replaces @items with @itemstemp and
+ # empties @itemstemp. This way, if something wrong happens during the
+ # upload to the IMAP server, items aren't lost.
+ # @nbnewitems is set by get_new_items, and is used to limit the number
+ # of (old) items serialized.
+
# Returns the really new items amongst items
def get_new_items(items)
+ # save number of new items
+ @nbnewitems = items.length
# set items' cached version if not set yet
newitems = []
updateditems = []
+ @itemstemp = @items
items.each { |i| i.cacheditem ||= CachedItem::new(i) }
items.each do |i|
found = false
@@ -111,6 +129,9 @@ class CachedChannel
if i.cacheditem == j
i.cacheditem.index = j.index
found = true
+ # let's put j in front of itemstemp
+ @itemstemp.delete(j)
+ @itemstemp.unshift(j)
break
end
end
@@ -123,6 +144,9 @@ class CachedChannel
i.cacheditem.updated = true
updateditems.push(i)
found = true
+ # let's put j in front of itemstemp
+ @itemstemp.delete(j)
+ @itemstemp.unshift(j)
break
end
end
@@ -130,16 +154,17 @@ class CachedChannel
# add as new
i.cacheditem.create_index
newitems.push(i)
+ # add i.cacheditem to @itemstemp
+ @itemstemp.unshift(i.cacheditem)
end
return [newitems, updateditems]
end
-
- # Replace the existing cached items by those ones
- def update(items)
- @items = []
- items.each do |i|
- @items.push(i.cacheditem)
- end
+
+ def commit
+ # too old items must be dropped
+ n = @nbnewitems > CACHESIZE ? @nbnewitems : CACHESIZE
+ @items = @itemstemp[0..n]
+ @itemstemp = []
self
end
diff --git a/lib/feed2imap/feed2imap.rb b/lib/feed2imap/feed2imap.rb
index daee87d..1df93bd 100644
--- a/lib/feed2imap/feed2imap.rb
+++ b/lib/feed2imap/feed2imap.rb
@@ -133,7 +133,7 @@ class Feed2Imap
next
end
begin
- @cache.update_cache(f.name, channel.items)
+ @cache.commit_cache(f.name)
rescue
@logger.fatal("Exception caught while updating cache for #{f.name}: #{$!}")
next
diff --git a/test/tc_cache.rb b/test/tc_cache.rb
index d472d71..e03d81f 100755
--- a/test/tc_cache.rb
+++ b/test/tc_cache.rb
@@ -33,10 +33,14 @@ class ItemCacheTest < Test::Unit::TestCase
i2.title = 'title2'
i2.link = 'link2'
i2.content = 'content2'
+ i3 = Item::new
+ i3.title = 'title3'
+ i3.link = 'link3'
+ i3.content = 'content3'
assert_equal([i1, i2], c.get_new_items('id', [i1, i2])[0])
- c.update_cache('id', [i1])
- assert_equal(1, c.nbitems)
- assert_equal([i2], c.get_new_items('id', [i1, i2])[0])
+ c.commit_cache('id')
+ assert_equal(2, c.nbitems)
+ assert_equal([i3], c.get_new_items('id', [i2, i3])[0])
end
def test_cache_management_updated
@@ -57,7 +61,7 @@ class ItemCacheTest < Test::Unit::TestCase
assert_equal(0, idx1)
idx2 = i2.cacheditem.index
assert_equal(1, idx2)
- c.update_cache('id', [i1, i2])
+ c.commit_cache('id')
i3 = Item::new
i3.title = 'title 1 - updated'
i3.link = 'link1'