fix a race condition where a feed could be refreshed before it was created

This commit is contained in:
Athou
2024-07-03 14:16:09 +02:00
parent 1a73dd4004
commit 0dec0e3788
2 changed files with 46 additions and 3 deletions

View File

@@ -2,9 +2,16 @@ package com.commafeed.backend.dao;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.hibernate.SessionFactory;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PostInsertEvent;
import org.hibernate.event.spi.PostInsertEventListener;
import org.hibernate.persister.entity.EntityPersister;
import com.commafeed.backend.model.AbstractModel;
import com.commafeed.backend.model.Feed;
@@ -24,9 +31,32 @@ public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
private final QFeedSubscription sub = QFeedSubscription.feedSubscription;
private final SessionFactory sessionFactory;
@Inject
public FeedSubscriptionDAO(SessionFactory sessionFactory) {
super(sessionFactory);
this.sessionFactory = sessionFactory;
}
public void onPostCommitInsert(Consumer<FeedSubscription> consumer) {
sessionFactory.unwrap(SessionFactoryImplementor.class)
.getServiceRegistry()
.getService(EventListenerRegistry.class)
.getEventListenerGroup(EventType.POST_COMMIT_INSERT)
.appendListener(new PostInsertEventListener() {
@Override
public void onPostInsert(PostInsertEvent event) {
if (event.getEntity() instanceof FeedSubscription s) {
consumer.accept(s);
}
}
@Override
public boolean requiresPostCommitHandling(EntityPersister persister) {
return true;
}
});
}
public FeedSubscription findById(User user, Long id) {

View File

@@ -23,11 +23,9 @@ import com.commafeed.frontend.model.UnreadCount;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
@Singleton
public class FeedSubscriptionService {
@@ -39,6 +37,22 @@ public class FeedSubscriptionService {
private final CacheService cache;
private final CommaFeedConfiguration config;
@Inject
public FeedSubscriptionService(FeedDAO feedDAO, FeedEntryStatusDAO feedEntryStatusDAO, FeedSubscriptionDAO feedSubscriptionDAO,
FeedService feedService, FeedRefreshEngine feedRefreshEngine, CacheService cache, CommaFeedConfiguration config) {
this.feedDAO = feedDAO;
this.feedEntryStatusDAO = feedEntryStatusDAO;
this.feedSubscriptionDAO = feedSubscriptionDAO;
this.feedService = feedService;
this.feedRefreshEngine = feedRefreshEngine;
this.cache = cache;
this.config = config;
// automatically refresh feeds after they are subscribed to
// we need to use this hook because the feed needs to have been persisted because the queue processing is asynchronous
feedSubscriptionDAO.onPostCommitInsert(sub -> feedRefreshEngine.refreshImmediately(sub.getFeed()));
}
public long subscribe(User user, String url, String title) {
return subscribe(user, url, title, null, 0);
}
@@ -83,7 +97,6 @@ public class FeedSubscriptionService {
sub.setTitle(FeedUtils.truncate(title, 128));
feedSubscriptionDAO.saveOrUpdate(sub);
feedRefreshEngine.refreshImmediately(feed);
cache.invalidateUserRootCategory(user);
return sub.getId();
}