forked from Archives/Athou_commafeed
unit of work refactoring
This commit is contained in:
@@ -5,17 +5,26 @@ import org.hibernate.SessionFactory;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.context.internal.ManagedSessionContext;
|
||||
|
||||
public abstract class UnitOfWork<T> {
|
||||
public class UnitOfWork {
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
public UnitOfWork(SessionFactory sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
@FunctionalInterface
|
||||
public static interface SessionRunner {
|
||||
public void runInSession();
|
||||
}
|
||||
|
||||
protected abstract T runInSession() throws Exception;
|
||||
@FunctionalInterface
|
||||
public static interface SessionRunnerReturningValue<T> {
|
||||
public T runInSession();
|
||||
}
|
||||
|
||||
public T run() {
|
||||
public static void run(SessionFactory sessionFactory, SessionRunner sessionRunner) {
|
||||
run(sessionFactory, () -> {
|
||||
sessionRunner.runInSession();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public static <T> T run(SessionFactory sessionFactory, SessionRunnerReturningValue<T> sessionRunner) {
|
||||
final Session session = sessionFactory.openSession();
|
||||
if (ManagedSessionContext.hasBind(sessionFactory)) {
|
||||
throw new IllegalStateException("Already in a unit of work!");
|
||||
@@ -25,11 +34,11 @@ public abstract class UnitOfWork<T> {
|
||||
ManagedSessionContext.bind(session);
|
||||
session.beginTransaction();
|
||||
try {
|
||||
t = runInSession();
|
||||
t = sessionRunner.runInSession();
|
||||
commitTransaction(session);
|
||||
} catch (Exception e) {
|
||||
rollbackTransaction(session);
|
||||
this.<RuntimeException> rethrow(e);
|
||||
UnitOfWork.<RuntimeException> rethrow(e);
|
||||
}
|
||||
} finally {
|
||||
session.close();
|
||||
@@ -38,14 +47,14 @@ public abstract class UnitOfWork<T> {
|
||||
return t;
|
||||
}
|
||||
|
||||
private void rollbackTransaction(Session session) {
|
||||
private static void rollbackTransaction(Session session) {
|
||||
final Transaction txn = session.getTransaction();
|
||||
if (txn != null && txn.isActive()) {
|
||||
txn.rollback();
|
||||
}
|
||||
}
|
||||
|
||||
private void commitTransaction(Session session) {
|
||||
private static void commitTransaction(Session session) {
|
||||
final Transaction txn = session.getTransaction();
|
||||
if (txn != null && txn.isActive()) {
|
||||
txn.commit();
|
||||
@@ -53,7 +62,7 @@ public abstract class UnitOfWork<T> {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <E extends Exception> void rethrow(Exception e) throws E {
|
||||
private static <E extends Exception> void rethrow(Exception e) throws E {
|
||||
throw (E) e;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,12 +68,7 @@ public class FeedRefreshTaskGiver implements Managed {
|
||||
public void run() {
|
||||
while (!executor.isShutdown()) {
|
||||
try {
|
||||
FeedRefreshContext context = new UnitOfWork<FeedRefreshContext>(sessionFactory) {
|
||||
@Override
|
||||
protected FeedRefreshContext runInSession() throws Exception {
|
||||
return queues.take();
|
||||
}
|
||||
}.run();
|
||||
FeedRefreshContext context = UnitOfWork.run(sessionFactory, () -> queues.take());
|
||||
if (context != null) {
|
||||
feedRefreshed.mark();
|
||||
worker.updateFeed(context);
|
||||
|
||||
@@ -120,12 +120,7 @@ public class FeedRefreshUpdater implements Managed {
|
||||
if (!lastEntries.contains(cacheKey)) {
|
||||
log.debug("cache miss for {}", entry.getUrl());
|
||||
if (subscriptions == null) {
|
||||
subscriptions = new UnitOfWork<List<FeedSubscription>>(sessionFactory) {
|
||||
@Override
|
||||
protected List<FeedSubscription> runInSession() throws Exception {
|
||||
return feedSubscriptionDAO.findByFeed(feed);
|
||||
}
|
||||
}.run();
|
||||
subscriptions = UnitOfWork.run(sessionFactory, () -> feedSubscriptionDAO.findByFeed(feed));
|
||||
}
|
||||
ok &= addEntry(feed, entry, subscriptions);
|
||||
entryCacheMiss.mark();
|
||||
@@ -190,12 +185,7 @@ public class FeedRefreshUpdater implements Managed {
|
||||
locked1 = lock1.tryLock(1, TimeUnit.MINUTES);
|
||||
locked2 = lock2.tryLock(1, TimeUnit.MINUTES);
|
||||
if (locked1 && locked2) {
|
||||
boolean inserted = new UnitOfWork<Boolean>(sessionFactory) {
|
||||
@Override
|
||||
protected Boolean runInSession() throws Exception {
|
||||
return feedUpdateService.addEntry(feed, entry, subscriptions);
|
||||
}
|
||||
}.run();
|
||||
boolean inserted = UnitOfWork.run(sessionFactory, () -> feedUpdateService.addEntry(feed, entry, subscriptions));
|
||||
if (inserted) {
|
||||
entryInserted.mark();
|
||||
}
|
||||
|
||||
@@ -17,8 +17,6 @@ import com.commafeed.backend.dao.FeedEntryDAO;
|
||||
import com.commafeed.backend.dao.FeedEntryDAO.FeedCapacity;
|
||||
import com.commafeed.backend.dao.FeedEntryStatusDAO;
|
||||
import com.commafeed.backend.dao.UnitOfWork;
|
||||
import com.commafeed.backend.model.Feed;
|
||||
import com.commafeed.backend.model.FeedEntryStatus;
|
||||
|
||||
/**
|
||||
* Contains utility methods for cleaning the database
|
||||
@@ -42,13 +40,7 @@ public class DatabaseCleaningService {
|
||||
long total = 0;
|
||||
int deleted = 0;
|
||||
do {
|
||||
deleted = new UnitOfWork<Integer>(sessionFactory) {
|
||||
@Override
|
||||
protected Integer runInSession() throws Exception {
|
||||
List<Feed> feeds = feedDAO.findWithoutSubscriptions(1);
|
||||
return feedDAO.delete(feeds);
|
||||
};
|
||||
}.run();
|
||||
deleted = UnitOfWork.run(sessionFactory, () -> feedDAO.delete(feedDAO.findWithoutSubscriptions(1)));
|
||||
total += deleted;
|
||||
log.info("removed {} feeds without subscriptions", total);
|
||||
} while (deleted != 0);
|
||||
@@ -61,12 +53,7 @@ public class DatabaseCleaningService {
|
||||
long total = 0;
|
||||
int deleted = 0;
|
||||
do {
|
||||
deleted = new UnitOfWork<Integer>(sessionFactory) {
|
||||
@Override
|
||||
protected Integer runInSession() throws Exception {
|
||||
return feedEntryContentDAO.deleteWithoutEntries(BATCH_SIZE);
|
||||
}
|
||||
}.run();
|
||||
deleted = UnitOfWork.run(sessionFactory, () -> feedEntryContentDAO.deleteWithoutEntries(BATCH_SIZE));
|
||||
total += deleted;
|
||||
log.info("removed {} contents without entries", total);
|
||||
} while (deleted != 0);
|
||||
@@ -77,13 +64,8 @@ public class DatabaseCleaningService {
|
||||
public long cleanEntriesForFeedsExceedingCapacity(final int maxFeedCapacity) {
|
||||
long total = 0;
|
||||
while (true) {
|
||||
List<FeedCapacity> feeds = new UnitOfWork<List<FeedCapacity>>(sessionFactory) {
|
||||
@Override
|
||||
protected List<FeedCapacity> runInSession() throws Exception {
|
||||
return feedEntryDAO.findFeedsExceedingCapacity(maxFeedCapacity, BATCH_SIZE);
|
||||
}
|
||||
}.run();
|
||||
|
||||
List<FeedCapacity> feeds = UnitOfWork.run(sessionFactory,
|
||||
() -> feedEntryDAO.findFeedsExceedingCapacity(maxFeedCapacity, BATCH_SIZE));
|
||||
if (feeds.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
@@ -92,12 +74,8 @@ public class DatabaseCleaningService {
|
||||
long remaining = feed.getCapacity() - maxFeedCapacity;
|
||||
do {
|
||||
final long rem = remaining;
|
||||
int deleted = new UnitOfWork<Integer>(sessionFactory) {
|
||||
@Override
|
||||
protected Integer runInSession() throws Exception {
|
||||
return feedEntryDAO.deleteOldEntries(feed.getId(), Math.min(BATCH_SIZE, rem));
|
||||
};
|
||||
}.run();
|
||||
int deleted = UnitOfWork.run(sessionFactory,
|
||||
() -> feedEntryDAO.deleteOldEntries(feed.getId(), Math.min(BATCH_SIZE, rem)));
|
||||
total += deleted;
|
||||
remaining -= deleted;
|
||||
log.info("removed {} entries for feeds exceeding capacity", total);
|
||||
@@ -113,13 +91,8 @@ public class DatabaseCleaningService {
|
||||
long total = 0;
|
||||
int deleted = 0;
|
||||
do {
|
||||
deleted = new UnitOfWork<Integer>(sessionFactory) {
|
||||
@Override
|
||||
protected Integer runInSession() throws Exception {
|
||||
List<FeedEntryStatus> list = feedEntryStatusDAO.getOldStatuses(olderThan, BATCH_SIZE);
|
||||
return feedEntryStatusDAO.delete(list);
|
||||
}
|
||||
}.run();
|
||||
deleted = UnitOfWork.run(sessionFactory,
|
||||
() -> feedEntryStatusDAO.delete(feedEntryStatusDAO.getOldStatuses(olderThan, BATCH_SIZE)));
|
||||
total += deleted;
|
||||
log.info("cleaned {} old read statuses", total);
|
||||
} while (deleted != 0);
|
||||
|
||||
@@ -44,15 +44,10 @@ public class StartupService implements Managed {
|
||||
@Override
|
||||
public void start() throws Exception {
|
||||
updateSchema();
|
||||
new UnitOfWork<Void>(sessionFactory) {
|
||||
@Override
|
||||
protected Void runInSession() throws Exception {
|
||||
if (userDAO.count() == 0) {
|
||||
initialData();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}.run();
|
||||
long count = UnitOfWork.run(sessionFactory, () -> userDAO.count());
|
||||
if (count == 0) {
|
||||
UnitOfWork.run(sessionFactory, () -> initialData());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSchema() {
|
||||
|
||||
@@ -32,23 +32,12 @@ public class CustomCssServlet extends HttpServlet {
|
||||
protected void doGet(final HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
resp.setContentType("text/css");
|
||||
|
||||
final Optional<User> user = new UnitOfWork<Optional<User>>(sessionFactory) {
|
||||
@Override
|
||||
protected Optional<User> runInSession() throws Exception {
|
||||
return new SessionHelper(req).getLoggedInUser();
|
||||
}
|
||||
}.run();
|
||||
final Optional<User> user = UnitOfWork.run(sessionFactory, () -> new SessionHelper(req).getLoggedInUser());
|
||||
if (!user.isPresent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
UserSettings settings = new UnitOfWork<UserSettings>(sessionFactory) {
|
||||
@Override
|
||||
protected UserSettings runInSession() {
|
||||
return userSettingsDAO.findByUser(user.get());
|
||||
}
|
||||
}.run();
|
||||
|
||||
UserSettings settings = UnitOfWork.run(sessionFactory, () -> userSettingsDAO.findByUser(user.get()));
|
||||
if (settings == null || settings.getCustomCss() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -51,17 +51,11 @@ public class NextUnreadServlet extends HttpServlet {
|
||||
final String categoryId = req.getParameter(PARAM_CATEGORYID);
|
||||
String orderParam = req.getParameter(PARAM_READINGORDER);
|
||||
|
||||
final Optional<User> user = new UnitOfWork<Optional<User>>(sessionFactory) {
|
||||
@Override
|
||||
protected Optional<User> runInSession() throws Exception {
|
||||
SessionHelper sessionHelper = new SessionHelper(req);
|
||||
Optional<User> loggedInUser = sessionHelper.getLoggedInUser();
|
||||
if (loggedInUser.isPresent()) {
|
||||
userService.performPostLoginActivities(loggedInUser.get());
|
||||
}
|
||||
return loggedInUser;
|
||||
}
|
||||
}.run();
|
||||
SessionHelper sessionHelper = new SessionHelper(req);
|
||||
Optional<User> user = sessionHelper.getLoggedInUser();
|
||||
if (user.isPresent()) {
|
||||
UnitOfWork.run(sessionFactory, () -> userService.performPostLoginActivities(user.get()));
|
||||
}
|
||||
if (!user.isPresent()) {
|
||||
resp.sendRedirect(resp.encodeRedirectURL(config.getApplicationSettings().getPublicUrl()));
|
||||
return;
|
||||
@@ -69,32 +63,31 @@ public class NextUnreadServlet extends HttpServlet {
|
||||
|
||||
final ReadingOrder order = StringUtils.equals(orderParam, "asc") ? ReadingOrder.asc : ReadingOrder.desc;
|
||||
|
||||
FeedEntryStatus status = new UnitOfWork<FeedEntryStatus>(sessionFactory) {
|
||||
@Override
|
||||
protected FeedEntryStatus runInSession() throws Exception {
|
||||
FeedEntryStatus status = null;
|
||||
if (StringUtils.isBlank(categoryId) || CategoryREST.ALL.equals(categoryId)) {
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findAll(user.get());
|
||||
List<FeedEntryStatus> statuses = feedEntryStatusDAO.findBySubscriptions(user.get(), subs, true, null, null, 0, 1,
|
||||
order, true, false, null);
|
||||
status = Iterables.getFirst(statuses, null);
|
||||
} else {
|
||||
FeedCategory category = feedCategoryDAO.findById(user.get(), Long.valueOf(categoryId));
|
||||
if (category != null) {
|
||||
List<FeedCategory> children = feedCategoryDAO.findAllChildrenCategories(user.get(), category);
|
||||
List<FeedSubscription> subscriptions = feedSubscriptionDAO.findByCategories(user.get(), children);
|
||||
List<FeedEntryStatus> statuses = feedEntryStatusDAO.findBySubscriptions(user.get(), subscriptions, true, null,
|
||||
null, 0, 1, order, true, false, null);
|
||||
status = Iterables.getFirst(statuses, null);
|
||||
FeedEntryStatus status = UnitOfWork.run(
|
||||
sessionFactory,
|
||||
() -> {
|
||||
FeedEntryStatus s = null;
|
||||
if (StringUtils.isBlank(categoryId) || CategoryREST.ALL.equals(categoryId)) {
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findAll(user.get());
|
||||
List<FeedEntryStatus> statuses = feedEntryStatusDAO.findBySubscriptions(user.get(), subs, true, null, null, 0, 1,
|
||||
order, true, false, null);
|
||||
s = Iterables.getFirst(statuses, null);
|
||||
} else {
|
||||
FeedCategory category = feedCategoryDAO.findById(user.get(), Long.valueOf(categoryId));
|
||||
if (category != null) {
|
||||
List<FeedCategory> children = feedCategoryDAO.findAllChildrenCategories(user.get(), category);
|
||||
List<FeedSubscription> subscriptions = feedSubscriptionDAO.findByCategories(user.get(), children);
|
||||
List<FeedEntryStatus> statuses = feedEntryStatusDAO.findBySubscriptions(user.get(), subscriptions, true, null,
|
||||
null, 0, 1, order, true, false, null);
|
||||
s = Iterables.getFirst(statuses, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (status != null) {
|
||||
status.setRead(true);
|
||||
feedEntryStatusDAO.saveOrUpdate(status);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}.run();
|
||||
if (s != null) {
|
||||
s.setRead(true);
|
||||
feedEntryStatusDAO.saveOrUpdate(s);
|
||||
}
|
||||
return s;
|
||||
});
|
||||
|
||||
if (status == null) {
|
||||
resp.sendRedirect(resp.encodeRedirectURL(config.getApplicationSettings().getPublicUrl()));
|
||||
@@ -103,5 +96,4 @@ public class NextUnreadServlet extends HttpServlet {
|
||||
resp.sendRedirect(resp.encodeRedirectURL(url));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user