Skip to content
Snippets Groups Projects
Verified Commit 72fb4e9b authored by Torsten Grote's avatar Torsten Grote
Browse files

Post RSS entries within one transaction

This also fixes a bug where new feeds was not added properly.
parent e10f68b4
No related branches found
No related tags found
No related merge requests found
...@@ -29,6 +29,9 @@ public interface BlogManager { ...@@ -29,6 +29,9 @@ public interface BlogManager {
/** Stores a local blog post. */ /** Stores a local blog post. */
void addLocalPost(BlogPost p) throws DbException; void addLocalPost(BlogPost p) throws DbException;
/** Stores a local blog post. */
void addLocalPost(Transaction txn, BlogPost p) throws DbException;
/** Returns the blog with the given ID. */ /** Returns the blog with the given ID. */
Blog getBlog(GroupId g) throws DbException; Blog getBlog(GroupId g) throws DbException;
......
...@@ -110,4 +110,25 @@ public class Feed { ...@@ -110,4 +110,25 @@ public class Feed {
return lastEntryTime; return lastEntryTime;
} }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o instanceof Feed) {
Feed f = (Feed) o;
return url.equals(f.url) && blogId.equals(f.getBlogId()) &&
equalsWithNull(title, f.getTitle()) &&
equalsWithNull(description, f.getDescription()) &&
equalsWithNull(author, f.getAuthor()) &&
added == f.getAdded() &&
updated == f.getUpdated() &&
lastEntryTime == f.getLastEntryTime();
}
return false;
}
private boolean equalsWithNull(Object a, Object b) {
if (a == b) return true;
if (a == null || b==null) return false;
return a.equals(b);
}
} }
...@@ -234,9 +234,20 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager, ...@@ -234,9 +234,20 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
@Override @Override
public void addLocalPost(BlogPost p) throws DbException { public void addLocalPost(BlogPost p) throws DbException {
BdfDictionary meta; Transaction txn = db.startTransaction(false);
try {
addLocalPost(txn, p);
txn.setComplete();
} finally {
//noinspection ThrowFromFinallyBlock
db.endTransaction(txn);
}
}
@Override
public void addLocalPost(Transaction txn, BlogPost p) throws DbException {
try { try {
meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
if (p.getTitle() != null) meta.put(KEY_TITLE, p.getTitle()); if (p.getTitle() != null) meta.put(KEY_TITLE, p.getTitle());
meta.put(KEY_TIMESTAMP, p.getMessage().getTimestamp()); meta.put(KEY_TIMESTAMP, p.getMessage().getTimestamp());
...@@ -249,25 +260,18 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager, ...@@ -249,25 +260,18 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
meta.put(KEY_CONTENT_TYPE, p.getContentType()); meta.put(KEY_CONTENT_TYPE, p.getContentType());
meta.put(KEY_READ, true); meta.put(KEY_READ, true);
clientHelper.addLocalMessage(p.getMessage(), CLIENT_ID, meta, true); clientHelper.addLocalMessage(txn, p.getMessage(), CLIENT_ID, meta,
} catch (FormatException e) { true);
throw new RuntimeException(e);
}
// broadcast event about new post // broadcast event about new post
Transaction txn = db.startTransaction(true);
try {
GroupId groupId = p.getMessage().getGroupId(); GroupId groupId = p.getMessage().getGroupId();
MessageId postId = p.getMessage().getId(); MessageId postId = p.getMessage().getId();
BlogPostHeader h = getPostHeaderFromMetadata(txn, postId, meta); BlogPostHeader h = getPostHeaderFromMetadata(txn, postId, meta);
BlogPostAddedEvent event = BlogPostAddedEvent event =
new BlogPostAddedEvent(groupId, h, true); new BlogPostAddedEvent(groupId, h, true);
txn.attach(event); txn.attach(event);
txn.setComplete();
} catch (FormatException e) { } catch (FormatException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); throw new DbException(e);
} finally {
db.endTransaction(txn);
} }
} }
......
...@@ -165,13 +165,13 @@ class FeedManagerImpl implements FeedManager, Service, Client { ...@@ -165,13 +165,13 @@ class FeedManagerImpl implements FeedManager, Service, Client {
storeFeeds(txn, feeds); storeFeeds(txn, feeds);
txn.setComplete(); txn.setComplete();
} finally { } finally {
//noinspection ThrowFromFinallyBlock
db.endTransaction(txn); db.endTransaction(txn);
} }
// fetch feed again, post entries this time // fetch feed again, post entries this time
Feed updatedFeed;
try { try {
feed = fetchFeed(feed, true); updatedFeed = fetchFeed(feed, true);
} catch (FeedException e) { } catch (FeedException e) {
throw new IOException(e); throw new IOException(e);
} }
...@@ -180,11 +180,11 @@ class FeedManagerImpl implements FeedManager, Service, Client { ...@@ -180,11 +180,11 @@ class FeedManagerImpl implements FeedManager, Service, Client {
txn = db.startTransaction(false); txn = db.startTransaction(false);
try { try {
List<Feed> feeds = getFeeds(txn); List<Feed> feeds = getFeeds(txn);
feeds.add(feed); feeds.remove(feed);
feeds.add(updatedFeed);
storeFeeds(txn, feeds); storeFeeds(txn, feeds);
txn.setComplete(); txn.setComplete();
} finally { } finally {
//noinspection ThrowFromFinallyBlock
db.endTransaction(txn); db.endTransaction(txn);
} }
} }
...@@ -294,6 +294,9 @@ class FeedManagerImpl implements FeedManager, Service, Client { ...@@ -294,6 +294,9 @@ class FeedManagerImpl implements FeedManager, Service, Client {
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e); LOG.log(WARNING, e.toString(), e);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
} }
} }
...@@ -308,7 +311,7 @@ class FeedManagerImpl implements FeedManager, Service, Client { ...@@ -308,7 +311,7 @@ class FeedManagerImpl implements FeedManager, Service, Client {
} }
private Feed fetchFeed(Feed feed, boolean post) private Feed fetchFeed(Feed feed, boolean post)
throws FeedException, IOException { throws FeedException, IOException, DbException {
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Fetching feed from " + feed.getUrl()); LOG.info("Fetching feed from " + feed.getUrl());
...@@ -331,24 +334,7 @@ class FeedManagerImpl implements FeedManager, Service, Client { ...@@ -331,24 +334,7 @@ class FeedManagerImpl implements FeedManager, Service, Client {
// sort and add new entries // sort and add new entries
if (post) { if (post) {
Collections.sort(f.getEntries(), getEntryComparator()); lastEntryTime = postFeedEntries(feed, f.getEntries());
for (SyndEntry entry : f.getEntries()) {
long entryTime;
if (entry.getPublishedDate() != null) {
entryTime = entry.getPublishedDate().getTime();
} else if (entry.getUpdatedDate() != null) {
entryTime = entry.getUpdatedDate().getTime();
} else {
// no time information available, ignore this entry
if (LOG.isLoggable(WARNING))
LOG.warning("Entry has no date: " + entry.getTitle());
continue;
}
if (entryTime > feed.getLastEntryTime()) {
postEntry(feed, entry);
if (entryTime > lastEntryTime) lastEntryTime = entryTime;
}
}
} }
return new Feed(feed.getUrl(), feed.getBlogId(), title, description, return new Feed(feed.getUrl(), feed.getBlogId(), title, description,
author, feed.getAdded(), updated, lastEntryTime); author, feed.getAdded(), updated, lastEntryTime);
...@@ -384,9 +370,40 @@ class FeedManagerImpl implements FeedManager, Service, Client { ...@@ -384,9 +370,40 @@ class FeedManagerImpl implements FeedManager, Service, Client {
return input.build(new XmlReader(stream)); return input.build(new XmlReader(stream));
} }
private void postEntry(Feed feed, SyndEntry entry) { private long postFeedEntries(Feed feed, List<SyndEntry> entries)
throws DbException {
long lastEntryTime = feed.getLastEntryTime();
Transaction txn = db.startTransaction(false);
try {
Collections.sort(entries, getEntryComparator());
for (SyndEntry entry : entries) {
long entryTime;
if (entry.getPublishedDate() != null) {
entryTime = entry.getPublishedDate().getTime();
} else if (entry.getUpdatedDate() != null) {
entryTime = entry.getUpdatedDate().getTime();
} else {
// no time information available, ignore this entry
if (LOG.isLoggable(WARNING))
LOG.warning("Entry has no date: " + entry.getTitle());
continue;
}
if (entryTime > feed.getLastEntryTime()) {
postEntry(txn, feed, entry);
if (entryTime > lastEntryTime) lastEntryTime = entryTime;
}
}
txn.setComplete();
} finally {
db.endTransaction(txn);
}
return lastEntryTime;
}
private void postEntry(Transaction txn, Feed feed, SyndEntry entry)
throws DbException {
LOG.info("Adding new entry..."); LOG.info("Adding new entry...");
// TODO do this within one database transaction?
// build post body // build post body
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
...@@ -426,13 +443,13 @@ class FeedManagerImpl implements FeedManager, Service, Client { ...@@ -426,13 +443,13 @@ class FeedManagerImpl implements FeedManager, Service, Client {
byte[] body = getPostBody(b.toString()); byte[] body = getPostBody(b.toString());
try { try {
// create and store post // create and store post
Blog blog = blogManager.getBlog(groupId); Blog blog = blogManager.getBlog(txn, groupId);
AuthorId authorId = blog.getAuthor().getId(); AuthorId authorId = blog.getAuthor().getId();
LocalAuthor author = identityManager.getLocalAuthor(authorId); LocalAuthor author = identityManager.getLocalAuthor(txn, authorId);
BlogPost post = blogPostFactory BlogPost post = blogPostFactory
.createBlogPost(groupId, null, time, null, author, .createBlogPost(groupId, null, time, null, author,
"text/plain", body); "text/plain", body);
blogManager.addLocalPost(post); blogManager.addLocalPost(txn, post);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e); LOG.log(WARNING, e.toString(), e);
......
...@@ -284,9 +284,10 @@ public class BlogManagerImplTest extends BriarTestCase { ...@@ -284,9 +284,10 @@ public class BlogManagerImplTest extends BriarTestCase {
); );
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(clientHelper).addLocalMessage(message, CLIENT_ID, meta, true); oneOf(db).startTransaction(false);
oneOf(db).startTransaction(true);
will(returnValue(txn)); will(returnValue(txn));
oneOf(clientHelper)
.addLocalMessage(txn, message, CLIENT_ID, meta, true);
oneOf(identityManager) oneOf(identityManager)
.getAuthorStatus(txn, blog1.getAuthor().getId()); .getAuthorStatus(txn, blog1.getAuthor().getId());
will(returnValue(VERIFIED)); will(returnValue(VERIFIED));
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment