Add simple cleanup of old build actions

This commit is contained in:
Martchus 2022-11-24 21:33:42 +01:00
parent 9cf0fed450
commit 218e1f6b17
6 changed files with 86 additions and 12 deletions

View File

@ -323,6 +323,9 @@ LibPkg::StorageID BuildAction::start(ServiceSetup &setup, std::unique_ptr<Io::Pa
case BuildActionType::CustomCommand:
post<CustomCommand>();
break;
case BuildActionType::BuildServiceCleanup:
post<BuildServiceCleanup>();
break;
default:
resultData = "not implemented yet or invalid type";
return conclude(BuildActionResult::Failure);
@ -409,6 +412,43 @@ LibPkg::StorageID BuildAction::conclude(BuildActionResult result)
return id;
}
BuildServiceCleanup::BuildServiceCleanup(ServiceSetup &setup, const std::shared_ptr<BuildAction> &buildAction)
: InternalBuildAction(setup, buildAction)
{
}
void BuildServiceCleanup::run()
{
// validate parameter
if (auto error = validateParameter(RequiredDatabases::None, RequiredParameters::None); !error.empty()) {
reportError(move(error));
return;
}
// iterate though build actions and delete those that are unlikely to be relevant anymore
auto count = std::size_t();
constexpr auto stopAt = 150;
m_setup.building.forEachBuildAction(
[this, &count, twoWeeksAgo = DateTime::gmtNow() - TimeSpan::fromDays(14)](
LibPkg::StorageID id, BuildAction &action, ServiceSetup::BuildSetup::VisitorBehavior &visitorBehavior) {
if (count <= stopAt) {
return true; // abort deletion if under 150 build actions anyways
}
if (m_buildAction->id == id || action.finished.isNull()) {
return false; // avoid deleting cleanup action itself as well as any unfinished actions
}
if (action.result != BuildActionResult::Success || action.finished > twoWeeksAgo) {
return false; // delete only successful actions that are at least two weeks old
}
visitorBehavior = ServiceSetup::BuildSetup::VisitorBehavior::Delete;
return --count <= stopAt;
},
&count);
const auto buildActionLock = m_setup.building.lockToWrite();
reportSuccess();
}
#ifdef LIBREPOMGR_DUMMY_BUILD_ACTION_ENABLED
DummyBuildAction::DummyBuildAction(ServiceSetup &setup, const std::shared_ptr<BuildAction> &buildAction)
: InternalBuildAction(setup, buildAction)

View File

@ -373,6 +373,18 @@ BuildActionMetaInfo::BuildActionMetaInfo()
.destinationDb = false,
.packageNames = false,
},
BuildActionTypeMetaInfo{
.id = BuildActionType::BuildServiceCleanup,
.category = "Misc",
.name = "Clean build-service-internal data",
.type = "build-service-cleanup",
.flags = {},
.settings = {},
.directory = false,
.sourceDb = false,
.destinationDb = false,
.packageNames = false,
},
})
, states({
BuildActionStatusMetaInfo{

View File

@ -47,7 +47,8 @@ enum class BuildActionType : std::uint64_t {
CleanRepository,
DummyBuildAction,
CustomCommand,
LastType = CustomCommand,
BuildServiceCleanup,
LastType = BuildServiceCleanup,
};
using BuildActionFlagType = std::uint64_t;

View File

@ -656,6 +656,13 @@ private:
bool m_useContainer;
};
struct LIBREPOMGR_EXPORT BuildServiceCleanup : public InternalBuildAction {
BuildServiceCleanup(ServiceSetup &setup, const std::shared_ptr<BuildAction> &buildAction);
void run();
private:
};
#ifdef LIBREPOMGR_DUMMY_BUILD_ACTION_ENABLED
struct LIBREPOMGR_EXPORT DummyBuildAction : public InternalBuildAction {
DummyBuildAction(ServiceSetup &setup, const std::shared_ptr<BuildAction> &buildAction);

View File

@ -417,22 +417,30 @@ void ServiceSetup::BuildSetup::forEachBuildAction(
}
}
void ServiceSetup::BuildSetup::forEachBuildAction(ServiceSetup::BuildSetup::BuildActionVisitorWriteable &&func)
void ServiceSetup::BuildSetup::forEachBuildAction(ServiceSetup::BuildSetup::BuildActionVisitorWriteable &&func, std::size_t *count)
{
auto txn = m_storage->buildActions.getRWTransaction();
if (count) {
*count = txn.size();
}
for (auto i = txn.begin(); i != txn.end(); ++i) {
const auto running = m_runningActions.find(i.getID());
auto &action = running != m_runningActions.end() ? *running->second : i.value();
auto save = false;
const auto stop = func(i.getID(), action, save);
if (save) {
auto visitorBehavior = VisitorBehavior::DiscardChanges;
const auto stop = func(i.getID(), action, visitorBehavior);
if (visitorBehavior == VisitorBehavior::SaveChanges) {
if (running != m_runningActions.end() && !action.isExecuting()) {
m_runningActions.erase(running);
}
txn.put(action, i.getID());
} else if (visitorBehavior == VisitorBehavior::Delete && !action.isExecuting()) {
if (running != m_runningActions.end()) {
m_runningActions.erase(running);
}
txn.del(i.getID());
}
if (stop) {
return;
break;
}
}
txn.commit();
@ -713,12 +721,12 @@ void ServiceSetup::restoreState()
building.initStorage(building.dbPath.data());
// ensure no build actions are considered running anymore and populate follow up actions
building.forEachBuildAction([this](LibPkg::StorageID, BuildAction &buildAction, bool &save) {
building.forEachBuildAction([this](LibPkg::StorageID, BuildAction &buildAction, BuildSetup::VisitorBehavior &visitorBehavior) {
if (buildAction.isExecuting()) {
buildAction.status = BuildActionStatus::Finished;
buildAction.result = BuildActionResult::Failure;
buildAction.resultData = "service crashed while exectuing";
save = true;
visitorBehavior = BuildSetup::VisitorBehavior::SaveChanges;
} else if (buildAction.isScheduled()) {
for (const auto previousBuildActionId : buildAction.startAfter) {
building.m_followUpActions[previousBuildActionId].emplace(buildAction.id);
@ -809,11 +817,11 @@ int ServiceSetup::run()
try {
#endif
saveState();
building.forEachBuildAction([](LibPkg::StorageID, BuildAction &buildAction, bool &save) {
building.forEachBuildAction([](LibPkg::StorageID, BuildAction &buildAction, BuildSetup::VisitorBehavior &visitorBehavior) {
if (buildAction.isExecuting()) {
buildAction.status = BuildActionStatus::Finished;
buildAction.result = BuildActionResult::Aborted;
save = true;
visitorBehavior = BuildSetup::VisitorBehavior::SaveChanges;
}
return false;
});

View File

@ -92,6 +92,12 @@ struct LIBREPOMGR_EXPORT ServiceSetup : public LibPkg::Lockable {
BuildSetup &setup;
};
enum class VisitorBehavior {
DiscardChanges,
SaveChanges,
Delete,
};
explicit BuildSetup();
BuildSetup(BuildSetup &&) = delete;
~BuildSetup();
@ -148,8 +154,8 @@ struct LIBREPOMGR_EXPORT ServiceSetup : public LibPkg::Lockable {
void rebuildDb();
using BuildActionVisitorBase = std::function<bool(LibPkg::StorageID, BuildActionBase &&)>;
void forEachBuildAction(std::function<void(std::size_t)> count, BuildActionVisitorBase &&func, std::size_t limit, std::size_t start);
using BuildActionVisitorWriteable = std::function<bool(LibPkg::StorageID, BuildAction &, bool &)>;
void forEachBuildAction(BuildActionVisitorWriteable &&func);
using BuildActionVisitorWriteable = std::function<bool(LibPkg::StorageID, BuildAction &, VisitorBehavior &)>;
void forEachBuildAction(BuildActionVisitorWriteable &&func, std::size_t *count = nullptr);
std::vector<std::shared_ptr<BuildAction>> followUpBuildActions(BuildActionIdType forId);
private: