Optimized get most recent listen query

This commit is contained in:
emeric
2026-06-18 18:41:06 +02:00
parent 5ecdc58b97
commit 2da0e98b9f
4 changed files with 60 additions and 12 deletions
+3 -2
View File
@@ -470,10 +470,11 @@ namespace lms::db
return utils::fetchQuerySingleResult(session.getDboSession()->query<Wt::Dbo::ptr<Listen>>("SELECT l from listen l").join("track t ON l.track_id = t.id").where("t.release_id = ?").bind(releaseId).where("l.user_id = ?").bind(userId).where("l.backend = ?").bind(backend).orderBy("l.date_time DESC").limit(1));
}
Listen::pointer Listen::getMostRecentListen(Session& session, UserId userId, ScrobblingBackend backend, TrackId trackId)
Listen::pointer Listen::getMostRecentListen(Session& session, UserId userId, TrackId trackId)
{
session.checkReadTransaction();
// TODO not pending remove?
return utils::fetchQuerySingleResult(session.getDboSession()->query<Wt::Dbo::ptr<Listen>>("SELECT l from listen l").where("l.track_id = ?").bind(trackId).where("l.user_id = ?").bind(userId).where("l.backend = ?").bind(backend).orderBy("l.date_time DESC").limit(1));
return utils::fetchQuerySingleResult(session.getDboSession()->query<Wt::Dbo::ptr<Listen>>("SELECT l from listen l").join("user u ON u.id = l.user_id").where("l.track_id = ?").bind(trackId).where("l.user_id = ?").bind(userId).where("l.backend = u.scrobbling_backend").orderBy("l.date_time DESC").limit(1));
}
} // namespace lms::db
@@ -151,7 +151,7 @@ namespace lms::db
static std::size_t getCount(Session& session, UserId userId, ReleaseId trackId); // for the current backend
static pointer getMostRecentListen(Session& session, UserId userId, ScrobblingBackend backend, ReleaseId releaseId);
static pointer getMostRecentListen(Session& session, UserId userId, ScrobblingBackend backend, TrackId releaseId);
static pointer getMostRecentListen(Session& session, UserId userId, TrackId trackId); // uses current scrobbling backend
SyncState getSyncState() const { return _syncState; }
ObjectPtr<User> getUser() const { return _user; }
+55 -4
View File
@@ -1592,7 +1592,7 @@ namespace lms::db::tests
{
auto transaction{ session.createReadTransaction() };
auto listen{ Listen::getMostRecentListen(session, user->getId(), ScrobblingBackend::Internal, track.getId()) };
auto listen{ Listen::getMostRecentListen(session, user->getId(), track.getId()) };
EXPECT_FALSE(listen);
}
@@ -1602,7 +1602,7 @@ namespace lms::db::tests
{
auto transaction{ session.createReadTransaction() };
auto listen{ Listen::getMostRecentListen(session, user->getId(), ScrobblingBackend::Internal, track.getId()) };
auto listen{ Listen::getMostRecentListen(session, user->getId(), track.getId()) };
EXPECT_TRUE(listen);
EXPECT_EQ(listen->getDateTime(), dateTime1);
}
@@ -1613,7 +1613,7 @@ namespace lms::db::tests
{
auto transaction{ session.createReadTransaction() };
auto listen{ Listen::getMostRecentListen(session, user->getId(), ScrobblingBackend::Internal, track.getId()) };
auto listen{ Listen::getMostRecentListen(session, user->getId(), track.getId()) };
EXPECT_TRUE(listen);
EXPECT_EQ(listen->getDateTime(), dateTime1);
}
@@ -1624,7 +1624,7 @@ namespace lms::db::tests
{
auto transaction{ session.createReadTransaction() };
auto listen{ Listen::getMostRecentListen(session, user->getId(), ScrobblingBackend::Internal, track.getId()) };
auto listen{ Listen::getMostRecentListen(session, user->getId(), track.getId()) };
EXPECT_TRUE(listen);
EXPECT_EQ(listen->getDateTime(), dateTime3);
}
@@ -1698,6 +1698,57 @@ namespace lms::db::tests
}
}
TEST_F(DatabaseFixture, Listen_getMostRecentTrack_byUserBackend)
{
ScopedTrack track{ session };
ScopedUser user{ session, "MyUser" };
{
auto transaction{ session.createReadTransaction() };
EXPECT_FALSE(Listen::getMostRecentListen(session, user->getId(), track.getId()));
}
const Wt::WDateTime dateTime1{ Wt::WDate{ 2000, 1, 2 }, Wt::WTime{ 12, 0, 1 } };
ScopedListen listen1{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, dateTime1 };
{
auto transaction{ session.createReadTransaction() };
const auto listen{ Listen::getMostRecentListen(session, user->getId(), track.getId()) };
ASSERT_TRUE(listen);
EXPECT_EQ(listen->getDateTime(), dateTime1);
}
const Wt::WDateTime dateTime2{ Wt::WDate{ 1999, 1, 2 }, Wt::WTime{ 12, 0, 1 } };
ScopedListen listen2{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, dateTime2 };
{
auto transaction{ session.createReadTransaction() };
const auto listen{ Listen::getMostRecentListen(session, user->getId(), track.getId()) };
ASSERT_TRUE(listen);
EXPECT_EQ(listen->getDateTime(), dateTime1);
}
const Wt::WDateTime dateTime3{ Wt::WDate{ 2001, 1, 2 }, Wt::WTime{ 12, 0, 1 } };
ScopedListen listen3{ session, user.lockAndGet(), track.lockAndGet(), ScrobblingBackend::Internal, dateTime3 };
{
auto transaction{ session.createReadTransaction() };
const auto listen{ Listen::getMostRecentListen(session, user->getId(), track.getId()) };
ASSERT_TRUE(listen);
EXPECT_EQ(listen->getDateTime(), dateTime3);
}
{
auto transaction{ session.createWriteTransaction() };
user.get().modify()->setScrobblingBackend(ScrobblingBackend::ListenBrainz);
}
{
auto transaction{ session.createReadTransaction() };
EXPECT_FALSE(Listen::getMostRecentListen(session, user->getId(), track.getId()));
}
}
TEST_F(DatabaseFixture, Listen_getRecentTracks_cluster)
{
ScopedTrack track{ session };