Subsonic API: cached cluster stats for track and releases, in order to make the getGenre entrypoint efficient on large databases
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Emeric Poupon
|
||||
*
|
||||
* This file is part of LMS.
|
||||
*
|
||||
* LMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* LMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ScanStepComputeClusterStats.hpp"
|
||||
#include "services/database/Db.hpp"
|
||||
#include "services/database/Cluster.hpp"
|
||||
#include "services/database/Session.hpp"
|
||||
#include "utils/Logger.hpp"
|
||||
#include "utils/Path.hpp"
|
||||
|
||||
namespace Scanner
|
||||
{
|
||||
void ScanStepComputeClusterStats::process(ScanContext& context)
|
||||
{
|
||||
using namespace Database;
|
||||
|
||||
if (context.stats.nbChanges() == 0)
|
||||
return;
|
||||
|
||||
Session& dbSession{ _db.getTLSSession() };
|
||||
|
||||
const std::size_t clusterCount{ [&] {
|
||||
auto transaction{ dbSession.createSharedTransaction() };
|
||||
return Cluster::getCount(dbSession);
|
||||
}() };
|
||||
|
||||
context.currentStepStats.totalElems = clusterCount;
|
||||
|
||||
foreachSubRange(Range{ 0, clusterCount }, 100, [&](Range range)
|
||||
{
|
||||
const std::vector<ClusterId> clusterIds{ [&]
|
||||
{
|
||||
Cluster::FindParameters params;
|
||||
params.setRange(range);
|
||||
|
||||
{
|
||||
auto transaction{ dbSession.createSharedTransaction() };
|
||||
return std::move(Cluster::findIds(dbSession, params).results);
|
||||
}
|
||||
}() };
|
||||
|
||||
for (const ClusterId clusterId : clusterIds)
|
||||
{
|
||||
std::size_t trackCount;
|
||||
std::size_t releaseCount;
|
||||
|
||||
{
|
||||
auto transaction{ dbSession.createSharedTransaction() };
|
||||
|
||||
trackCount = Cluster::computeTrackCount(dbSession, clusterId);
|
||||
releaseCount = Cluster::computeReleaseCount(dbSession, clusterId);
|
||||
}
|
||||
|
||||
{
|
||||
auto transaction{ dbSession.createUniqueTransaction() };
|
||||
|
||||
auto cluster{ Cluster::find(dbSession, clusterId) };
|
||||
cluster.modify()->setTrackCount(trackCount);
|
||||
cluster.modify()->setReleaseCount(releaseCount);
|
||||
}
|
||||
|
||||
context.currentStepStats.processedElems++;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
LMS_LOG(DBUPDATER, DEBUG) << "Recomputed stats for " << clusterCount << " clusters!";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Emeric Poupon
|
||||
*
|
||||
* This file is part of LMS.
|
||||
*
|
||||
* LMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* LMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ScanStepBase.hpp"
|
||||
|
||||
namespace Scanner
|
||||
{
|
||||
class ScanStepComputeClusterStats : public ScanStepBase
|
||||
{
|
||||
public:
|
||||
using ScanStepBase::ScanStepBase;
|
||||
|
||||
private:
|
||||
ScanStep getStep() const override { return ScanStep::ComputeClusterStats; }
|
||||
std::string_view getStepName() const override { return "Compute cluster stats"; }
|
||||
void process(ScanContext& context) override;
|
||||
};
|
||||
}
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "ScanStepDiscoverFiles.hpp"
|
||||
#include "ScanStepRemoveOrphanDbFiles.hpp"
|
||||
#include "ScanStepScanFiles.hpp"
|
||||
#include "ScanStepComputeClusterStats.hpp"
|
||||
|
||||
using namespace Database;
|
||||
|
||||
@@ -357,6 +358,7 @@ ScannerService::refreshScanSettings()
|
||||
_scanSteps.push_back(std::make_unique<ScanStepDiscoverFiles>(params));
|
||||
_scanSteps.push_back(std::make_unique<ScanStepScanFiles>(params));
|
||||
_scanSteps.push_back(std::make_unique<ScanStepRemoveOrphanDbFiles>(params));
|
||||
_scanSteps.push_back(std::make_unique<ScanStepComputeClusterStats>(params));
|
||||
_scanSteps.push_back(std::make_unique<ScanStepCheckDuplicatedDbFiles>(params));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user