diff --git a/src/libs/database/impl/objects/Listen.cpp b/src/libs/database/impl/objects/Listen.cpp index 34758c41..1736dd90 100644 --- a/src/libs/database/impl/objects/Listen.cpp +++ b/src/libs/database/impl/objects/Listen.cpp @@ -462,12 +462,25 @@ namespace lms::db .bind(releaseId)); } - Listen::pointer Listen::getMostRecentListen(Session& session, UserId userId, ScrobblingBackend backend, ReleaseId releaseId) + Listen::pointer Listen::getMostRecentListen(Session& session, UserId userId, ReleaseId releaseId) { session.checkReadTransaction(); // TODO not pending remove? - return utils::fetchQuerySingleResult(session.getDboSession()->query>("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)); + + // clang-format off + auto query{ session.getDboSession()->query>("SELECT l from listen l") + .join("user u ON u.id = l.user_id") + .join("track t ON l.track_id = t.id") + .where("t.release_id = ?").bind(releaseId) + .where("l.user_id = ?").bind(userId) + .where("l.backend = u.scrobbling_backend") + .orderBy("l.date_time DESC") + .limit(1) + }; + // clang-format on + + return utils::fetchQuerySingleResult(query); } Listen::pointer Listen::getMostRecentListen(Session& session, UserId userId, TrackId trackId) @@ -475,6 +488,18 @@ namespace lms::db session.checkReadTransaction(); // TODO not pending remove? - return utils::fetchQuerySingleResult(session.getDboSession()->query>("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)); + + // clang-format off + auto query{ session.getDboSession()->query>("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) + }; + // clang-format on + + return utils::fetchQuerySingleResult(query); } } // namespace lms::db diff --git a/src/libs/database/include/database/objects/Listen.hpp b/src/libs/database/include/database/objects/Listen.hpp index 084a3b65..15863d49 100644 --- a/src/libs/database/include/database/objects/Listen.hpp +++ b/src/libs/database/include/database/objects/Listen.hpp @@ -150,8 +150,8 @@ namespace lms::db static std::size_t getCount(Session& session, UserId userId, TrackId trackId); // for the current backend 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, TrackId trackId); // uses current scrobbling backend + static pointer getMostRecentListen(Session& session, UserId userId, ReleaseId releaseId); // uses current scrobbling backend + static pointer getMostRecentListen(Session& session, UserId userId, TrackId trackId); // uses current scrobbling backend SyncState getSyncState() const { return _syncState; } ObjectPtr getUser() const { return _user; } diff --git a/src/libs/database/test/Listen.cpp b/src/libs/database/test/Listen.cpp index b18c731c..2b7dfbdb 100644 --- a/src/libs/database/test/Listen.cpp +++ b/src/libs/database/test/Listen.cpp @@ -1207,7 +1207,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - const auto listen{ Listen::getMostRecentListen(session, user->getId(), ScrobblingBackend::Internal, release.getId()) }; + const auto listen{ Listen::getMostRecentListen(session, user->getId(), release.getId()) }; EXPECT_FALSE(listen); } @@ -1217,7 +1217,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - const auto listen{ Listen::getMostRecentListen(session, user->getId(), ScrobblingBackend::Internal, release.getId()) }; + const auto listen{ Listen::getMostRecentListen(session, user->getId(), release.getId()) }; EXPECT_TRUE(listen); EXPECT_EQ(listen->getDateTime(), dateTime1); } @@ -1228,7 +1228,7 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - const auto listen{ Listen::getMostRecentListen(session, user->getId(), ScrobblingBackend::Internal, release.getId()) }; + const auto listen{ Listen::getMostRecentListen(session, user->getId(), release.getId()) }; EXPECT_TRUE(listen); EXPECT_EQ(listen->getDateTime(), dateTime1); } @@ -1239,12 +1239,69 @@ namespace lms::db::tests { auto transaction{ session.createReadTransaction() }; - const auto listen{ Listen::getMostRecentListen(session, user->getId(), ScrobblingBackend::Internal, release.getId()) }; + const auto listen{ Listen::getMostRecentListen(session, user->getId(), release.getId()) }; EXPECT_TRUE(listen); EXPECT_EQ(listen->getDateTime(), dateTime3); } } + TEST_F(DatabaseFixture, Listen_getMostRecentRelease_byUserBackend) + { + ScopedTrack track{ session }; + ScopedUser user{ session, "MyUser" }; + ScopedRelease release{ session, "MyRelease" }; + + { + auto transaction{ session.createWriteTransaction() }; + track.get().modify()->setRelease(release.get()); + } + + { + auto transaction{ session.createReadTransaction() }; + EXPECT_FALSE(Listen::getMostRecentListen(session, user->getId(), release.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(), release.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(), release.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(), release.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(), release.getId())); + } + } + TEST_F(DatabaseFixture, Listen_getRecentReleases_multi) { ScopedTrack track1{ session }; diff --git a/src/libs/services/scrobbling/impl/ScrobblingService.cpp b/src/libs/services/scrobbling/impl/ScrobblingService.cpp index b8dc5d98..a03c0069 100644 --- a/src/libs/services/scrobbling/impl/ScrobblingService.cpp +++ b/src/libs/services/scrobbling/impl/ScrobblingService.cpp @@ -223,14 +223,10 @@ namespace lms::scrobbling Wt::WDateTime ScrobblingService::getLastListenDateTime(db::UserId userId, db::ReleaseId releaseId) { - const auto backend{ getUserBackend(userId) }; - if (!backend) - return {}; - Session& session{ _db.getTLSSession() }; auto transaction{ session.createReadTransaction() }; - const db::Listen::pointer listen{ db::Listen::getMostRecentListen(session, userId, *backend, releaseId) }; + const db::Listen::pointer listen{ db::Listen::getMostRecentListen(session, userId, releaseId) }; return listen ? listen->getDateTime() : Wt::WDateTime{}; }