Skip to content

Commit

Permalink
2.9.1192
Browse files Browse the repository at this point in the history
Improvements to mod management retry logic:

* If a fatal/non-recoverable error, like a deleted mod, or a mod with an invalid zip occurs, the mod won't have its installation reattempted. This flag persists across sessions.
* Any mods with short-term temporary errors that should be retried (like network errors) get moved to the end of the processing list. This will ensure other mods get a chance to be processed first, to address the issue where we are continually reattempting the same installation and not processing any others.
* The default behaviour will now be to defer a reattempt till the next session, unless the error belongs to the 'retryable' or 'never retry' categories.
* There is now a limit on the number of retries for an installation before that mod will fall back to deferred status
  • Loading branch information
stephenwhittle committed Oct 1, 2021
1 parent 42090ea commit 2b03296
Show file tree
Hide file tree
Showing 31 changed files with 190 additions and 61 deletions.
2 changes: 1 addition & 1 deletion Doc/documentation.html
Original file line number Diff line number Diff line change
Expand Up @@ -5903,7 +5903,7 @@ <h4 id="_values_19" class="discrete">Values</h4>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2021-09-14 15:01:15 +1000
Last updated 2021-10-01 13:09:46 +1000
</div>
</div>
</body>
Expand Down
Binary file modified Doc/img/nd_img_DisableModManagement.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Doc/img/nd_img_GetLogoFullSize.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Doc/img/nd_img_GetLogoThumbnailSize.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Doc/img/nd_img_GetProjectEnvironment.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Doc/img/nd_img_IsModManagementBusy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Doc/img/nd_img_K2_GetModDependenciesAsync.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Doc/img/nd_img_K2_GetModTagOptionsAsync.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Doc/img/nd_img_K2_UnsubscribeFromModAsync.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Doc/img/nd_img_ListUserSubscriptionAsync.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Doc/img/nd_img_MakeApiKey.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Doc/img/nd_img_MakeAuthParams.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Doc/img/nd_img_QueryUserInstallations.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
123 changes: 110 additions & 13 deletions Source/Modio/GeneratedSource/ModioModCollectionEntry.cpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
/*
/*
* Copyright (C) 2021 mod.io Pty Ltd. <https://mod.io>
*
*
* This file is part of the mod.io SDK.
*
* Distributed under the MIT License. (See accompanying file LICENSE or
*
* Distributed under the MIT License. (See accompanying file LICENSE or
* view online at <https://github.com/modio/modio-sdk/blob/main/LICENSE>)
*
*
*/

#ifdef MODIO_SEPARATE_COMPILATION
#include "modio/core/ModioModCollectionEntry.h"
#endif

#include "modio/core/ModioErrorCode.h"
#include "modio/core/ModioLogger.h"
#include "modio/detail/ModioConstants.h"
#include "modio/detail/ModioJsonHelpers.h"
#include "nlohmann/json.hpp"
#include <algorithm>
Expand All @@ -24,15 +26,22 @@ namespace Modio
CurrentState(Modio::ModState::InstallationPending),
ModProfile(ProfileData),
LocalUserSubscriptions(),
PathOnDisk(CalculatedModPath) {};
PathOnDisk(CalculatedModPath),
RetriesRemainingThisSession(Modio::Detail::Constants::Configuration::DefaultNumberOfRetries) {};

ModCollectionEntry::ModCollectionEntry(const ModCollectionEntry& Other)
: ID(Other.ID),
CurrentState(Other.CurrentState.load()),
ModProfile(Other.ModProfile),
LocalUserSubscriptionCount(Other.LocalUserSubscriptionCount.load()),
LocalUserSubscriptions(Other.LocalUserSubscriptions),
PathOnDisk(Other.PathOnDisk) {};
PathOnDisk(Other.PathOnDisk),
RetriesRemainingThisSession(Modio::Detail::Constants::Configuration::DefaultNumberOfRetries) {};

uint8_t ModCollectionEntry::GetRetriesRemaining()
{
return RetriesRemainingThisSession;
}

void ModCollectionEntry::UpdateModProfile(ModInfo ProfileData)
{
Expand Down Expand Up @@ -76,21 +85,76 @@ namespace Modio
void ModCollectionEntry::SetModState(Modio::ModState NewState)
{
CurrentState = NewState;
if (CurrentState == Modio::ModState::Installed)
{
RetriesRemainingThisSession = Modio::Detail::Constants::Configuration::DefaultNumberOfRetries;
}
}

void ModCollectionEntry::MarkModNoRetry()
void ModCollectionEntry::MarkModNoRetryThisSession()
{
ShouldNotRetry.store(true);
}

void ModCollectionEntry::SetLastError(Modio::ErrorCode Reason)
{
// For uninstallations, defer immediately if the error indicates we should defer, else make a number of retry
// attempts then stop
if (GetModState() == ModState::UninstallPending)
{
if (Modio::ErrorCodeMatches(Reason, Modio::ErrorConditionTypes::ModDeleteDeferredError))
{
MarkModNoRetryThisSession();
return;
}
else
{
if (RetriesRemainingThisSession > 0)
{
RetriesRemainingThisSession--;
}
if (RetriesRemainingThisSession == 0)
{
MarkModNoRetryThisSession();
}
}
}
// For installations, if we should retry, make a fixed number of attempts then stop.
// If the error is unrecoverable, prevent future reattempts permanently.
// Otherwise, defer to next startup
else
{
if (Modio::ErrorCodeMatches(Reason, Modio::ErrorConditionTypes::ModInstallRetryableError))
{
if (RetriesRemainingThisSession > 0)
{
RetriesRemainingThisSession--;
}
if (RetriesRemainingThisSession == 0)
{
MarkModNoRetryThisSession();
}
}
else if (Modio::ErrorCodeMatches(Reason, Modio::ErrorConditionTypes::ModInstallUnrecoverableError))
{
NeverRetryReason = Reason;
}
else
{
MarkModNoRetryThisSession();
}
}
}

void ModCollectionEntry::ClearModNoRetry()
{
ShouldNotRetry.store(false);
}

bool ModCollectionEntry::ShouldRetry()
{
return !ShouldNotRetry.load();
// Should only retry if we have don't have a never retry reason AND ShouldNotRetry is not set
return !NeverRetryReason && !ShouldNotRetry.load();
}

Modio::ModState ModCollectionEntry::GetModState() const
Expand Down Expand Up @@ -158,6 +222,7 @@ namespace Modio
LocalUserSubscriptions = Other.LocalUserSubscriptions;
LocalUserSubscriptionCount.store(Other.LocalUserSubscriptionCount.load());
PathOnDisk = Other.PathOnDisk;
RetriesRemainingThisSession = Other.RetriesRemainingThisSession;
return *this;
};

Expand All @@ -175,9 +240,10 @@ namespace Modio
}
else
{
Modio::Detail::Logger().Log(
Modio::LogLevel::Warning, Modio::LogCategory::ModManagement,
"Mod {0} is in state Downloading or Extracting without a transaction in progress. Saving state as InstallationPending", Entry.ID);
Modio::Detail::Logger().Log(Modio::LogLevel::Warning, Modio::LogCategory::ModManagement,
"Mod {0} is in state Downloading or Extracting without a transaction in "
"progress. Saving state as InstallationPending",
Entry.ID);
EntryState = Modio::ModState::InstallationPending;
}
}
Expand All @@ -188,7 +254,10 @@ namespace Modio
{Modio::Detail::Constants::JSONKeys::ModEntrySubCount, Entry.LocalUserSubscriptions},
{Modio::Detail::Constants::JSONKeys::ModEntryState, EntryState},
{Modio::Detail::Constants::JSONKeys::ModSizeOnDisk, Entry.SizeOnDisk},
{Modio::Detail::Constants::JSONKeys::ModPathOnDisk, Entry.PathOnDisk.string()}});
{Modio::Detail::Constants::JSONKeys::ModPathOnDisk, Entry.PathOnDisk.string()},
{Modio::Detail::Constants::JSONKeys::ModNeverRetryCode, Entry.NeverRetryReason.value()},
{Modio::Detail::Constants::JSONKeys::ModNeverRetryCategory,
Modio::Detail::ModioErrorCategoryID(Entry.NeverRetryReason.category())}});
}

void from_json(const nlohmann::json& j, ModCollectionEntry& Entry)
Expand All @@ -201,6 +270,14 @@ namespace Modio
Modio::Detail::ParseSafe(j, StateTmp, Modio::Detail::Constants::JSONKeys::ModEntryState);
Entry.CurrentState.store(StateTmp);
Modio::Detail::ParseSafe(j, Entry.PathOnDisk, Modio::Detail::Constants::JSONKeys::ModPathOnDisk);
if (j.contains(Modio::Detail::Constants::JSONKeys::ModNeverRetryCode) &&
j.contains(Modio::Detail::Constants::JSONKeys::ModNeverRetryCategory))
{
Entry.NeverRetryReason =
std::error_code(j.at(Modio::Detail::Constants::JSONKeys::ModNeverRetryCode).get<uint32_t>(),
Modio::Detail::GetModioErrorCategoryByID(
j.at(Modio::Detail::Constants::JSONKeys::ModNeverRetryCategory).get<uint64_t>()));
}
}

UserSubscriptionList::UserSubscriptionList(std::vector<Modio::ModID>&& NewIDs)
Expand Down Expand Up @@ -323,4 +400,24 @@ namespace Modio
return false;
}

std::vector<std::shared_ptr<Modio::ModCollectionEntry>> ModCollection::SortEntriesByRetryPriority() const
{
std::vector<std::shared_ptr<Modio::ModCollectionEntry>> SortedEntries;
// Copy the entries to the vector
for (const std::pair<Modio::ModID, std::shared_ptr<Modio::ModCollectionEntry>>& Elem : ModEntries)
{
SortedEntries.push_back(Elem.second);
}
// Sort the entries by priority (that is, entries which can be retried should be first, and entries which
// haven't been retried this session should be higher )
auto FirstElemWithNoRetry =
std::partition(SortedEntries.begin(), SortedEntries.end(),
[](std::shared_ptr<Modio::ModCollectionEntry> Elem) { return Elem->ShouldRetry(); });
std::partition(
SortedEntries.begin(), FirstElemWithNoRetry, [](std::shared_ptr<Modio::ModCollectionEntry> Elem) {
return Elem->GetRetriesRemaining() == Modio::Detail::Constants::Configuration::DefaultNumberOfRetries;
});
return SortedEntries;
}

} // namespace Modio
1 change: 0 additions & 1 deletion Source/Modio/Modio.Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ public Modio(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.NoSharedPCHs;
PrivatePCHHeaderFile = "Private/ModioPrivatePCH.h";

bEnableUndefinedIdentifierWarnings = false;
bEnforceIWYU = true;
//bUseUnity = false;
Expand Down
14 changes: 6 additions & 8 deletions Source/Modio/Private/Internal/Convert/FileMetadata.h
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
/*
/*
* Copyright (C) 2021 mod.io Pty Ltd. <https://mod.io>
*
*
* This file is part of the mod.io UE4 Plugin.
*
* Distributed under the MIT License. (See accompanying file LICENSE or
*
* Distributed under the MIT License. (See accompanying file LICENSE or
* view online at <https://github.com/modio/modio-ue4/blob/main/LICENSE>)
*
*
*/

#pragma once
#include "Internal/ModioConvert.h"
#include "Internal/ModioPrivateDefines.h"
#include "ModioSDK.h"
#include "Types/ModioFileMetadata.h"




MODIO_BEGIN_CONVERT_SWITCHES
FORCEINLINE EModioVirusScanStatus ToUnreal(Modio::FileMetadata::VirusScanStatus VirusScanStatus)
{
Expand Down
24 changes: 24 additions & 0 deletions Source/Modio/Private/Internal/Convert/List.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (C) 2021 mod.io Pty Ltd. <https://mod.io>
*
* This file is part of the mod.io UE4 Plugin.
*
* Distributed under the MIT License. (See accompanying file LICENSE or
* view online at <https://github.com/modio/modio-ue4/blob/main/LICENSE>)
*
*/

#pragma once

#include "Internal/ModioConvert.h"
#include "Types/ModioList.h"
#include "ModioSDK.h"

/** Convert a Modio::List to a FModioList */
template<template<typename...> typename DestListType, typename DestValueType, typename SourceListType>
FModioList<DestListType, DestValueType> ToUnrealList(SourceListType Value)
{
FModioList<DestListType, DestValueType> Result;
Result.InternalList = ToUnreal<DestValueType>(Value.GetRawList());
return Result;
}
1 change: 1 addition & 0 deletions Source/Modio/Private/Internal/ModioConvert.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ FORCEINLINE Modio::UserID ToModio(const FModioUserID& In);

#pragma region Implementation


// @todo: Rename this to ToModio as it doesn't matter that it's the part of STD of modio
FORCEINLINE std::string ToSTD(const FString& String)
{
Expand Down
6 changes: 4 additions & 2 deletions Source/Modio/Private/ModioSubsystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "Internal/Convert/ErrorCode.h"
#include "Internal/Convert/FilterParams.h"
#include "Internal/Convert/InitializeOptions.h"
#include "Internal/Convert/List.h"
#include "Internal/Convert/ModCollectionEntry.h"
#include "Internal/Convert/ModDependency.h"
#include "Internal/Convert/ModInfo.h"
Expand Down Expand Up @@ -274,7 +275,7 @@ void UModioSubsystem::GetModMediaAsync(FModioModID ModId, EModioAvatarSize Avata
});
}

void UModioSubsystem::GetModMediaAsync(FModioModID ModId, EModioGallerySize GallerySize, Modio::GalleryIndex Index,
void UModioSubsystem::GetModMediaAsync(FModioModID ModId, EModioGallerySize GallerySize, int32 Index,
FOnGetMediaDelegateFast Callback)
{
Modio::GetModMediaAsync(ToModio(ModId), ToModio(GallerySize), Index,
Expand Down Expand Up @@ -557,7 +558,8 @@ MODIO_API void UModioSubsystem::K2_GetModDependenciesAsync(FModioModID ModID, FO
{
GetModDependenciesAsync(ModID, FOnGetModDependenciesDelegateFast::CreateLambda(
[Callback](FModioErrorCode ec, TOptional<FModioModDependencyList> Dependencies) {
Callback.ExecuteIfBound(ec, FModioOptionalModDependencyList(MoveTempIfPossible(Dependencies)));
Callback.ExecuteIfBound(
ec, FModioOptionalModDependencyList(MoveTempIfPossible(Dependencies)));
}));
}

Expand Down
1 change: 1 addition & 0 deletions Source/Modio/Private/Tests/Commands/ModioTestCommandBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "Misc/TVariant.h"
#include "ModioSubsystem.h"
#include "Types/ModioErrorCode.h"
#include "ModioSDK.h"

#if WITH_DEV_AUTOMATION_TESTS

Expand Down
11 changes: 6 additions & 5 deletions Source/Modio/Private/Types/ModioModInfoList.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
/*
/*
* Copyright (C) 2021 mod.io Pty Ltd. <https://mod.io>
*
*
* This file is part of the mod.io UE4 Plugin.
*
* Distributed under the MIT License. (See accompanying file LICENSE or
*
* Distributed under the MIT License. (See accompanying file LICENSE or
* view online at <https://github.com/modio/modio-ue4/blob/main/LICENSE>)
*
*
*/

#include "Types/ModioModInfoList.h"
#include "Internal/Convert/List.h"
#include "Internal/Convert/ModInfo.h"
#include "ModioSDK.h"

Expand Down
11 changes: 6 additions & 5 deletions Source/Modio/Private/Types/ModioModTagOptions.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
/*
/*
* Copyright (C) 2021 mod.io Pty Ltd. <https://mod.io>
*
*
* This file is part of the mod.io UE4 Plugin.
*
* Distributed under the MIT License. (See accompanying file LICENSE or
*
* Distributed under the MIT License. (See accompanying file LICENSE or
* view online at <https://github.com/modio/modio-ue4/blob/main/LICENSE>)
*
*
*/

#include "Types/ModioModTagOptions.h"
#include "Internal/Convert/List.h"
#include "Internal/Convert/ModTagInfo.h"
#include "ModioSDK.h"

Expand Down
14 changes: 7 additions & 7 deletions Source/Modio/Private/Types/ModioURLListUImpl.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
/*
/*
* Copyright (C) 2021 mod.io Pty Ltd. <https://mod.io>
*
*
* This file is part of the mod.io UE4 Plugin.
*
* Distributed under the MIT License. (See accompanying file LICENSE or
*
* Distributed under the MIT License. (See accompanying file LICENSE or
* view online at <https://github.com/modio/modio-ue4/blob/main/LICENSE>)
*
*
*/

#include "Types/ModioURLList.h"
#include "Internal/Convert/List.h"
#include "ModioSDK.h"
#include "Internal/ModioConvert.h"
#include "Types/ModioURLList.h"

FModioYoutubeURLList::FModioYoutubeURLList(const Modio::YoutubeURLList& URLList)
: FModioList(ToUnrealList<TArray, FString>(URLList))
Expand Down
Loading

0 comments on commit 2b03296

Please sign in to comment.