Attempt to use stateless sessions in read-only operations. (#301)

This commit is contained in:
Kavin 2022-07-04 06:42:01 +01:00 committed by GitHub
parent cdd8a962d7
commit 17b9a974de
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 53 deletions

View file

@ -8,6 +8,7 @@ import me.kavin.piped.utils.*;
import me.kavin.piped.utils.obj.db.PubSub; import me.kavin.piped.utils.obj.db.PubSub;
import me.kavin.piped.utils.obj.db.User; import me.kavin.piped.utils.obj.db.User;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.StatelessSession;
import org.hibernate.Transaction; import org.hibernate.Transaction;
import org.hibernate.query.Query; import org.hibernate.query.Query;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
@ -54,7 +55,7 @@ public class Main {
new Timer().scheduleAtFixedRate(new TimerTask() { new Timer().scheduleAtFixedRate(new TimerTask() {
@Override @Override
public void run() { public void run() {
try (Session s = DatabaseSessionFactory.createSession()) { try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
CriteriaBuilder cb = s.getCriteriaBuilder(); CriteriaBuilder cb = s.getCriteriaBuilder();
CriteriaQuery<PubSub> criteria = cb.createQuery(PubSub.class); CriteriaQuery<PubSub> criteria = cb.createQuery(PubSub.class);

View file

@ -5,8 +5,8 @@ import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.JoinType; import jakarta.persistence.criteria.JoinType;
import jakarta.persistence.criteria.Root; import jakarta.persistence.criteria.Root;
import me.kavin.piped.utils.obj.db.*; import me.kavin.piped.utils.obj.db.*;
import org.hibernate.FlushMode; import org.hibernate.SharedSessionContract;
import org.hibernate.Session; import org.hibernate.StatelessSession;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ -14,13 +14,12 @@ import java.util.UUID;
public class DatabaseHelper { public class DatabaseHelper {
public static User getUserFromSession(String session) { public static User getUserFromSession(String session) {
try (Session s = DatabaseSessionFactory.createSession()) { try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
s.setHibernateFlushMode(FlushMode.MANUAL);
return getUserFromSession(session, s); return getUserFromSession(session, s);
} }
} }
public static User getUserFromSession(String session, Session s) { public static User getUserFromSession(String session, SharedSessionContract s) {
CriteriaBuilder cb = s.getCriteriaBuilder(); CriteriaBuilder cb = s.getCriteriaBuilder();
CriteriaQuery<User> cr = cb.createQuery(User.class); CriteriaQuery<User> cr = cb.createQuery(User.class);
Root<User> root = cr.from(User.class); Root<User> root = cr.from(User.class);
@ -30,8 +29,7 @@ public class DatabaseHelper {
} }
public static User getUserFromSessionWithSubscribed(String session) { public static User getUserFromSessionWithSubscribed(String session) {
try (Session s = DatabaseSessionFactory.createSession()) { try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
s.setHibernateFlushMode(FlushMode.MANUAL);
CriteriaBuilder cb = s.getCriteriaBuilder(); CriteriaBuilder cb = s.getCriteriaBuilder();
CriteriaQuery<User> cr = cb.createQuery(User.class); CriteriaQuery<User> cr = cb.createQuery(User.class);
Root<User> root = cr.from(User.class); Root<User> root = cr.from(User.class);
@ -42,7 +40,7 @@ public class DatabaseHelper {
} }
} }
public static Channel getChannelFromId(Session s, String id) { public static Channel getChannelFromId(SharedSessionContract s, String id) {
CriteriaBuilder cb = s.getCriteriaBuilder(); CriteriaBuilder cb = s.getCriteriaBuilder();
CriteriaQuery<Channel> cr = cb.createQuery(Channel.class); CriteriaQuery<Channel> cr = cb.createQuery(Channel.class);
Root<Channel> root = cr.from(Channel.class); Root<Channel> root = cr.from(Channel.class);
@ -52,13 +50,12 @@ public class DatabaseHelper {
} }
public static Channel getChannelFromId(String id) { public static Channel getChannelFromId(String id) {
try (Session s = DatabaseSessionFactory.createSession()) { try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
s.setHibernateFlushMode(FlushMode.MANUAL);
return getChannelFromId(s, id); return getChannelFromId(s, id);
} }
} }
public static List<Channel> getChannelsFromIds(Session s, List<String> id) { public static List<Channel> getChannelsFromIds(SharedSessionContract s, List<String> id) {
CriteriaBuilder cb = s.getCriteriaBuilder(); CriteriaBuilder cb = s.getCriteriaBuilder();
CriteriaQuery<Channel> cr = cb.createQuery(Channel.class); CriteriaQuery<Channel> cr = cb.createQuery(Channel.class);
Root<Channel> root = cr.from(Channel.class); Root<Channel> root = cr.from(Channel.class);
@ -67,7 +64,7 @@ public class DatabaseHelper {
return s.createQuery(cr).list(); return s.createQuery(cr).list();
} }
public static Video getVideoFromId(Session s, String id) { public static Video getVideoFromId(SharedSessionContract s, String id) {
CriteriaBuilder cb = s.getCriteriaBuilder(); CriteriaBuilder cb = s.getCriteriaBuilder();
CriteriaQuery<Video> cr = cb.createQuery(Video.class); CriteriaQuery<Video> cr = cb.createQuery(Video.class);
Root<Video> root = cr.from(Video.class); Root<Video> root = cr.from(Video.class);
@ -77,13 +74,12 @@ public class DatabaseHelper {
} }
public static Video getVideoFromId(String id) { public static Video getVideoFromId(String id) {
try (Session s = DatabaseSessionFactory.createSession()) { try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
s.setHibernateFlushMode(FlushMode.MANUAL);
return getVideoFromId(s, id); return getVideoFromId(s, id);
} }
} }
public static PlaylistVideo getPlaylistVideoFromId(Session s, String id) { public static PlaylistVideo getPlaylistVideoFromId(SharedSessionContract s, String id) {
CriteriaBuilder cb = s.getCriteriaBuilder(); CriteriaBuilder cb = s.getCriteriaBuilder();
CriteriaQuery<PlaylistVideo> cr = cb.createQuery(PlaylistVideo.class); CriteriaQuery<PlaylistVideo> cr = cb.createQuery(PlaylistVideo.class);
Root<PlaylistVideo> root = cr.from(PlaylistVideo.class); Root<PlaylistVideo> root = cr.from(PlaylistVideo.class);
@ -92,7 +88,7 @@ public class DatabaseHelper {
return s.createQuery(cr).uniqueResult(); return s.createQuery(cr).uniqueResult();
} }
public static Playlist getPlaylistFromId(Session s, String id) { public static Playlist getPlaylistFromId(SharedSessionContract s, String id) {
CriteriaBuilder cb = s.getCriteriaBuilder(); CriteriaBuilder cb = s.getCriteriaBuilder();
CriteriaQuery<Playlist> cr = cb.createQuery(Playlist.class); CriteriaQuery<Playlist> cr = cb.createQuery(Playlist.class);
Root<Playlist> root = cr.from(Playlist.class); Root<Playlist> root = cr.from(Playlist.class);
@ -101,7 +97,7 @@ public class DatabaseHelper {
return s.createQuery(cr).uniqueResult(); return s.createQuery(cr).uniqueResult();
} }
public static List<PlaylistVideo> getPlaylistVideosFromIds(Session s, List<String> id) { public static List<PlaylistVideo> getPlaylistVideosFromIds(SharedSessionContract s, List<String> id) {
CriteriaBuilder cb = s.getCriteriaBuilder(); CriteriaBuilder cb = s.getCriteriaBuilder();
CriteriaQuery<PlaylistVideo> cr = cb.createQuery(PlaylistVideo.class); CriteriaQuery<PlaylistVideo> cr = cb.createQuery(PlaylistVideo.class);
Root<PlaylistVideo> root = cr.from(PlaylistVideo.class); Root<PlaylistVideo> root = cr.from(PlaylistVideo.class);
@ -110,7 +106,7 @@ public class DatabaseHelper {
return s.createQuery(cr).list(); return s.createQuery(cr).list();
} }
public static PubSub getPubSubFromId(Session s, String id) { public static PubSub getPubSubFromId(SharedSessionContract s, String id) {
CriteriaBuilder cb = s.getCriteriaBuilder(); CriteriaBuilder cb = s.getCriteriaBuilder();
CriteriaQuery<PubSub> cr = cb.createQuery(PubSub.class); CriteriaQuery<PubSub> cr = cb.createQuery(PubSub.class);
Root<PubSub> root = cr.from(PubSub.class); Root<PubSub> root = cr.from(PubSub.class);
@ -120,8 +116,7 @@ public class DatabaseHelper {
} }
public static PubSub getPubSubFromId(String id) { public static PubSub getPubSubFromId(String id) {
try (Session s = DatabaseSessionFactory.createSession()) { try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
s.setHibernateFlushMode(FlushMode.MANUAL);
return getPubSubFromId(s, id); return getPubSubFromId(s, id);
} }
} }

View file

@ -1,14 +1,10 @@
package me.kavin.piped.utils; package me.kavin.piped.utils;
import me.kavin.piped.consts.Constants; import me.kavin.piped.consts.Constants;
import me.kavin.piped.utils.obj.db.Channel; import me.kavin.piped.utils.obj.db.*;
import me.kavin.piped.utils.obj.db.Playlist;
import me.kavin.piped.utils.obj.db.PlaylistVideo;
import me.kavin.piped.utils.obj.db.PubSub;
import me.kavin.piped.utils.obj.db.User;
import me.kavin.piped.utils.obj.db.Video;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.SessionFactory; import org.hibernate.SessionFactory;
import org.hibernate.StatelessSession;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
public class DatabaseSessionFactory { public class DatabaseSessionFactory {
@ -31,4 +27,8 @@ public class DatabaseSessionFactory {
public static final Session createSession() { public static final Session createSession() {
return sessionFactory.openSession(); return sessionFactory.openSession();
} }
public static StatelessSession createStatelessSession() {
return sessionFactory.openStatelessSession();
}
} }

View file

@ -29,6 +29,7 @@ import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.exception.ExceptionUtils;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.StatelessSession;
import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor.InfoItemsPage; import org.schabi.newpipe.extractor.ListExtractor.InfoItemsPage;
import org.schabi.newpipe.extractor.Page; import org.schabi.newpipe.extractor.Page;
@ -224,9 +225,10 @@ public class ResponseHelper {
info.getRelatedItems().forEach(o -> relatedStreams.add(collectRelatedStream(o))); info.getRelatedItems().forEach(o -> relatedStreams.add(collectRelatedStream(o)));
Multithreading.runAsync(() -> { Multithreading.runAsync(() -> {
try (Session s = DatabaseSessionFactory.createSession()) {
me.kavin.piped.utils.obj.db.Channel channel = DatabaseHelper.getChannelFromId(s, info.getId()); me.kavin.piped.utils.obj.db.Channel channel = DatabaseHelper.getChannelFromId(info.getId());
try (Session s = DatabaseSessionFactory.createSession()) {
if (channel != null) { if (channel != null) {
if (channel.isVerified() != info.isVerified() if (channel.isVerified() != info.isVerified()
@ -324,7 +326,7 @@ public class ResponseHelper {
} }
private static byte[] playlistPipedResponse(String playlistId) throws IOException { private static byte[] playlistPipedResponse(String playlistId) throws IOException {
try (Session s = DatabaseSessionFactory.createSession()) { try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
var cb = s.getCriteriaBuilder(); var cb = s.getCriteriaBuilder();
var cq = cb.createQuery(me.kavin.piped.utils.obj.db.Playlist.class); var cq = cb.createQuery(me.kavin.piped.utils.obj.db.Playlist.class);
var root = cq.from(me.kavin.piped.utils.obj.db.Playlist.class); var root = cq.from(me.kavin.piped.utils.obj.db.Playlist.class);
@ -421,7 +423,7 @@ public class ResponseHelper {
private static byte[] playlistPipedRSSResponse(String playlistId) private static byte[] playlistPipedRSSResponse(String playlistId)
throws FeedException { throws FeedException {
try (Session s = DatabaseSessionFactory.createSession()) { try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
var cb = s.getCriteriaBuilder(); var cb = s.getCriteriaBuilder();
var cq = cb.createQuery(me.kavin.piped.utils.obj.db.Playlist.class); var cq = cb.createQuery(me.kavin.piped.utils.obj.db.Playlist.class);
var root = cq.from(me.kavin.piped.utils.obj.db.Playlist.class); var root = cq.from(me.kavin.piped.utils.obj.db.Playlist.class);
@ -720,7 +722,7 @@ public class ResponseHelper {
user = user.toLowerCase(); user = user.toLowerCase();
try (Session s = DatabaseSessionFactory.createSession()) { try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
CriteriaBuilder cb = s.getCriteriaBuilder(); CriteriaBuilder cb = s.getCriteriaBuilder();
CriteriaQuery<User> cr = cb.createQuery(User.class); CriteriaQuery<User> cr = cb.createQuery(User.class);
Root<User> root = cr.from(User.class); Root<User> root = cr.from(User.class);
@ -786,11 +788,9 @@ public class ResponseHelper {
tr.commit(); tr.commit();
Multithreading.runAsync(() -> { Multithreading.runAsync(() -> {
try (Session s2 = DatabaseSessionFactory.createSession()) { var channel = DatabaseHelper.getChannelFromId(channelId);
var channel = DatabaseHelper.getChannelFromId(s2, channelId); if (channel == null) {
if (channel == null) { Multithreading.runAsync(() -> saveChannel(channelId));
Multithreading.runAsync(() -> saveChannel(channelId));
}
} }
}); });
} }
@ -825,7 +825,7 @@ public class ResponseHelper {
} }
public static byte[] isSubscribedResponse(String session, String channelId) throws IOException { public static byte[] isSubscribedResponse(String session, String channelId) throws IOException {
try (Session s = DatabaseSessionFactory.createSession()) { try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
var cb = s.getCriteriaBuilder(); var cb = s.getCriteriaBuilder();
var query = cb.createQuery(Long.class); var query = cb.createQuery(Long.class);
var root = query.from(User.class); var root = query.from(User.class);
@ -848,7 +848,7 @@ public class ResponseHelper {
User user = DatabaseHelper.getUserFromSession(session); User user = DatabaseHelper.getUserFromSession(session);
if (user != null) { if (user != null) {
try (Session s = DatabaseSessionFactory.createSession()) { try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
CriteriaBuilder cb = s.getCriteriaBuilder(); CriteriaBuilder cb = s.getCriteriaBuilder();
@ -892,7 +892,7 @@ public class ResponseHelper {
if (user != null) { if (user != null) {
try (Session s = DatabaseSessionFactory.createSession()) { try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
SyndFeed feed = new SyndFeedImpl(); SyndFeed feed = new SyndFeedImpl();
feed.setFeedType("atom_1.0"); feed.setFeedType("atom_1.0");
@ -954,7 +954,7 @@ public class ResponseHelper {
if (user != null) { if (user != null) {
Multithreading.runAsync(() -> { Multithreading.runAsync(() -> {
try (Session sess = DatabaseSessionFactory.createSession()) { try (Session s = DatabaseSessionFactory.createSession()) {
if (override) { if (override) {
user.setSubscribed(Set.of(channelIds)); user.setSubscribed(Set.of(channelIds));
} else { } else {
@ -963,15 +963,15 @@ public class ResponseHelper {
} }
if (channelIds.length > 0) { if (channelIds.length > 0) {
var tr = sess.beginTransaction(); var tr = s.beginTransaction();
sess.merge(user); s.merge(user);
tr.commit(); tr.commit();
} }
} }
}); });
Multithreading.runAsync(() -> { Multithreading.runAsync(() -> {
try (Session s = DatabaseSessionFactory.createSession()) { try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
var channels = DatabaseHelper.getChannelsFromIds(s, Arrays.asList(channelIds)); var channels = DatabaseHelper.getChannelsFromIds(s, Arrays.asList(channelIds));
Arrays.stream(channelIds).parallel() Arrays.stream(channelIds).parallel()
@ -996,7 +996,7 @@ public class ResponseHelper {
User user = DatabaseHelper.getUserFromSession(session); User user = DatabaseHelper.getUserFromSession(session);
if (user != null) { if (user != null) {
try (Session s = DatabaseSessionFactory.createSession()) { try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
CriteriaBuilder cb = s.getCriteriaBuilder(); CriteriaBuilder cb = s.getCriteriaBuilder();
var query = cb.createQuery(me.kavin.piped.utils.obj.db.Channel.class); var query = cb.createQuery(me.kavin.piped.utils.obj.db.Channel.class);
@ -1275,14 +1275,14 @@ public class ResponseHelper {
s.merge(playlist); s.merge(playlist);
tr.commit(); tr.commit();
Multithreading.runAsync(() -> pruneUnusedPlaylistVideos()); Multithreading.runAsync(ResponseHelper::pruneUnusedPlaylistVideos);
return mapper.writeValueAsBytes(new AcceptedResponse()); return mapper.writeValueAsBytes(new AcceptedResponse());
} }
} }
public static String registeredBadgeRedirect() { public static String registeredBadgeRedirect() {
try (Session s = DatabaseSessionFactory.createSession()) { try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
long registered = (Long) s.createQuery("select count(*) from User").uniqueResult(); long registered = (Long) s.createQuery("select count(*) from User").uniqueResult();
return String.format("https://img.shields.io/badge/Registered%%20Users-%s-blue", registered); return String.format("https://img.shields.io/badge/Registered%%20Users-%s-blue", registered);
@ -1349,11 +1349,12 @@ public class ResponseHelper {
private static void updateVideo(String id, StreamInfoItem item, long time, boolean addIfNotExistent) { private static void updateVideo(String id, StreamInfoItem item, long time, boolean addIfNotExistent) {
Multithreading.runAsync(() -> { Multithreading.runAsync(() -> {
try { try {
Session s = DatabaseSessionFactory.createSession(); Video video = DatabaseHelper.getVideoFromId(id);
Video video = DatabaseHelper.getVideoFromId(s, id);
if (video != null) { if (video != null) {
updateVideo(s, video, item.getViewCount(), item.getDuration(), item.getName()); try (Session s = DatabaseSessionFactory.createSession()) {
updateVideo(s, video, item.getViewCount(), item.getDuration(), item.getName());
}
} else if (addIfNotExistent) { } else if (addIfNotExistent) {
handleNewVideo("https://www.youtube.com/watch?v=" + id, time, null); handleNewVideo("https://www.youtube.com/watch?v=" + id, time, null);
} }
@ -1367,11 +1368,12 @@ public class ResponseHelper {
private static void updateVideo(String id, StreamInfo info, long time) { private static void updateVideo(String id, StreamInfo info, long time) {
Multithreading.runAsync(() -> { Multithreading.runAsync(() -> {
try { try {
Session s = DatabaseSessionFactory.createSession(); Video video = DatabaseHelper.getVideoFromId(id);
Video video = DatabaseHelper.getVideoFromId(s, id);
if (video != null) { if (video != null) {
updateVideo(s, video, info.getViewCount(), info.getDuration(), info.getName()); try (Session s = DatabaseSessionFactory.createSession()) {
updateVideo(s, video, info.getViewCount(), info.getDuration(), info.getName());
}
} else { } else {
handleNewVideo(info, time, null); handleNewVideo(info, time, null);
} }