From 714677e6358e8ac63877f6c3f58fda1b45f6c54a Mon Sep 17 00:00:00 2001 From: Oleg Sych Date: Wed, 19 Jun 2024 14:46:06 -0700 Subject: [PATCH 1/2] Remove KVS to RC migration projects The KVS to RC migration projects were created years ago based on the direction from the Service Fabric Data team, who didn't want to support automatic migration. Since then, the strategy has changed and the migration effort was abandoned and these projects haven't been maintained. In addition, to being abandoned, these projects have a dependency on the unsafe packages, such as Newtonsoft.Json, which are now reported by the component governance. Since there is no plan to resume this effort, the abandoned code is removed. Remove migration projects --- code.sln | 33 - ...rviceFabric.Actors.KVSToRCMigration.nuproj | 82 -- ...ervice_fabric_managed_netframework.targets | 7 +- ...service_fabric_managed_netstandard.targets | 4 +- properties/service_fabric_nuget.targets | 4 +- .../AmbiguousActorIdHandlerBase.cs | 81 -- .../CatchupPhaseWorkload.cs | 27 - .../AspNetCoreCommunicationListener.cs | 185 ---- .../GenericHostCommunicationListener.cs | 87 -- .../HttpSysCommunicationListener.cs | 82 -- .../WebHostCommunicationListener.cs | 80 -- .../Controllers/KvsMigrationController.cs | 133 --- .../MigrationControllerFeatureProvider.cs | 25 - .../Controllers/RcMigrationController.cs | 90 -- .../CopyPhaseWorkload.cs | 65 -- .../DowntimeWorkload.cs | 26 - .../ApplicationBuilderExtensions.cs | 38 - .../KvsActorStateProviderExtensions.cs | 337 ------ .../ServiceParitionClientExtensions.cs | 62 -- .../WebHostBuilderServiceFabricExtensions.cs | 58 - .../Friend.cs | 18 - .../HttpCommunicationClient.cs | 52 - .../HttpCommunicationClientFactory.cs | 46 - .../HttpExceptionHandler.cs | 71 -- .../IAmbiguousActorIdHandler.cs | 40 - .../IMigrationPhaseWorkload.cs | 29 - .../IWorker.cs | 30 - .../KVSAmbiguousActorIdHandler.cs | 64 -- .../KVStoRCMigrationActorStateProvider.cs | 698 ------------ ...rviceFabric.Actors.KVSToRCMigration.csproj | 34 - .../DefaultMigrationExceptionMiddleware.cs | 63 -- .../ServiceFabricIntegrationOptions.cs | 26 - .../Middleware/ServiceFabricMiddleware.cs | 64 -- .../Middleware/ServiceFabricSetupFilter.cs | 35 - .../MigrationConstants.cs | 81 -- .../MigrationDataValidationException.cs | 35 - .../MigrationOrchestratorBase.cs | 197 ---- .../MigrationPhaseWorkloadBase.cs | 543 ---------- .../MigrationSettings.cs | 110 -- .../MigrationUtility.cs | 564 ---------- .../MigrationWorker.cs | 310 ------ .../Models/EnumerationRequest.cs | 66 -- .../Models/EnumerationResponse.cs | 41 - .../Models/KeyValuePair.cs | 49 - .../PartitionHealthExceptionFilter.cs | 170 --- .../PhaseInput.cs | 113 -- .../Properties/AssemblyInfo.cs | 6 - .../RCAmbiguousActorIdHandler.cs | 109 -- .../ReliableDictionaryExtensions.cs | 48 - .../SerializationUtility.cs | 61 -- .../SourceMigrationOrchestrator.cs | 188 ---- .../Startup.cs | 49 - .../TargetMigrationOrchestrator.cs | 999 ------------------ .../WorkerBase.cs | 141 --- src/Microsoft.ServiceFabric.Actors/Friend.cs | 7 - .../Friend.cs | 1 - .../Friend.cs | 3 - ...Actors.KVSToRCMigration_netstandard.csproj | 36 - .../AmbiguousActorIdTest.cs | 100 -- ...eFabric.Actors.StateMigration.Tests.csproj | 27 - .../MigrationActorStateProviderTests.cs | 279 ----- .../MigrationSettingsTest.cs | 52 - .../MigrationWorkerTests.cs | 81 -- .../MockKVStoRCMigrationActorStateProvider.cs | 40 - .../MockReliableCollectionsStateProvider.cs | 205 ---- .../MockTypes/MockReliableDictionary.cs | 342 ------ .../MockTypes/MockServicePartitionClient.cs | 123 --- .../TargetMigrationOrchestratorTests.cs | 641 ----------- 68 files changed, 4 insertions(+), 8589 deletions(-) delete mode 100644 nuprojs/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Microsoft.ServiceFabric.Actors.KVSToRCMigration.nuproj delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/AmbiguousActorIdHandlerBase.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CatchupPhaseWorkload.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CommunicationListener/AspNetCoreCommunicationListener.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CommunicationListener/GenericHostCommunicationListener.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CommunicationListener/HttpSysCommunicationListener.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CommunicationListener/WebHostCommunicationListener.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Controllers/KvsMigrationController.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Controllers/MigrationControllerFeatureProvider.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Controllers/RcMigrationController.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CopyPhaseWorkload.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/DowntimeWorkload.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Extensions/ApplicationBuilderExtensions.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Extensions/KvsActorStateProviderExtensions.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Extensions/ServiceParitionClientExtensions.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Extensions/WebHostBuilderServiceFabricExtensions.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Friend.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/HttpCommunicationClient.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/HttpCommunicationClientFactory.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/HttpExceptionHandler.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/IAmbiguousActorIdHandler.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/IMigrationPhaseWorkload.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/IWorker.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/KVSAmbiguousActorIdHandler.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/KVStoRCMigrationActorStateProvider.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Microsoft.ServiceFabric.Actors.KVSToRCMigration.csproj delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Middleware/DefaultMigrationExceptionMiddleware.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Middleware/ServiceFabricIntegrationOptions.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Middleware/ServiceFabricMiddleware.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Middleware/ServiceFabricSetupFilter.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationConstants.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationDataValidationException.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationOrchestratorBase.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationPhaseWorkloadBase.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationSettings.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationUtility.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationWorker.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Models/EnumerationRequest.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Models/EnumerationResponse.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Models/KeyValuePair.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/PartitionHealthExceptionFilter.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/PhaseInput.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Properties/AssemblyInfo.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/RCAmbiguousActorIdHandler.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/ReliableDictionaryExtensions.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/SerializationUtility.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/SourceMigrationOrchestrator.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Startup.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/TargetMigrationOrchestrator.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/WorkerBase.cs delete mode 100644 src/netstandard/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Microsoft.ServiceFabric.Actors.KVSToRCMigration_netstandard.csproj delete mode 100644 test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/AmbiguousActorIdTest.cs delete mode 100644 test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/Microsoft.ServiceFabric.Actors.StateMigration.Tests.csproj delete mode 100644 test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MigrationActorStateProviderTests.cs delete mode 100644 test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MigrationSettingsTest.cs delete mode 100644 test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MigrationWorkerTests.cs delete mode 100644 test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MockTypes/MockKVStoRCMigrationActorStateProvider.cs delete mode 100644 test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MockTypes/MockReliableCollectionsStateProvider.cs delete mode 100644 test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MockTypes/MockReliableDictionary.cs delete mode 100644 test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MockTypes/MockServicePartitionClient.cs delete mode 100644 test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/TargetMigrationOrchestratorTests.cs diff --git a/code.sln b/code.sln index 3f412a7e..5b5816de 100644 --- a/code.sln +++ b/code.sln @@ -44,12 +44,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ServiceFabric.Ser EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ServiceFabric.Services.Tests", "test\unittests\Microsoft.ServiceFabric.Services.Tests\Microsoft.ServiceFabric.Services.Tests.csproj", "{ECB3825D-B309-4C76-A20D-76544459F611}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ServiceFabric.Actors.KVSToRCMigration", "src\Microsoft.ServiceFabric.Actors.KVSToRCMigration\Microsoft.ServiceFabric.Actors.KVSToRCMigration.csproj", "{B5E3B9D7-E91E-4B76-959D-D418E973FCAF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ServiceFabric.Actors.KVSToRCMigration_netstandard", "src\netstandard\Microsoft.ServiceFabric.Actors.KVSToRCMigration\Microsoft.ServiceFabric.Actors.KVSToRCMigration_netstandard.csproj", "{E5B52C61-66BE-4D71-88D2-E50F78011C72}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ServiceFabric.Actors.StateMigration.Tests", "test\unittests\Microsoft.ServiceFabric.Actors.StateMigration.Tests\Microsoft.ServiceFabric.Actors.StateMigration.Tests.csproj", "{1BDC4681-FDBA-4E55-A247-5F779627A4D7}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -162,30 +156,6 @@ Global {ECB3825D-B309-4C76-A20D-76544459F611}.Release|Any CPU.Build.0 = Release|Any CPU {ECB3825D-B309-4C76-A20D-76544459F611}.Release|x64.ActiveCfg = Release|x64 {ECB3825D-B309-4C76-A20D-76544459F611}.Release|x64.Build.0 = Release|x64 - {B5E3B9D7-E91E-4B76-959D-D418E973FCAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B5E3B9D7-E91E-4B76-959D-D418E973FCAF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B5E3B9D7-E91E-4B76-959D-D418E973FCAF}.Debug|x64.ActiveCfg = Debug|x64 - {B5E3B9D7-E91E-4B76-959D-D418E973FCAF}.Debug|x64.Build.0 = Debug|x64 - {B5E3B9D7-E91E-4B76-959D-D418E973FCAF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B5E3B9D7-E91E-4B76-959D-D418E973FCAF}.Release|Any CPU.Build.0 = Release|Any CPU - {B5E3B9D7-E91E-4B76-959D-D418E973FCAF}.Release|x64.ActiveCfg = Release|x64 - {B5E3B9D7-E91E-4B76-959D-D418E973FCAF}.Release|x64.Build.0 = Release|x64 - {E5B52C61-66BE-4D71-88D2-E50F78011C72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E5B52C61-66BE-4D71-88D2-E50F78011C72}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E5B52C61-66BE-4D71-88D2-E50F78011C72}.Debug|x64.ActiveCfg = Debug|x64 - {E5B52C61-66BE-4D71-88D2-E50F78011C72}.Debug|x64.Build.0 = Debug|x64 - {E5B52C61-66BE-4D71-88D2-E50F78011C72}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E5B52C61-66BE-4D71-88D2-E50F78011C72}.Release|Any CPU.Build.0 = Release|Any CPU - {E5B52C61-66BE-4D71-88D2-E50F78011C72}.Release|x64.ActiveCfg = Release|x64 - {E5B52C61-66BE-4D71-88D2-E50F78011C72}.Release|x64.Build.0 = Release|x64 - {1BDC4681-FDBA-4E55-A247-5F779627A4D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1BDC4681-FDBA-4E55-A247-5F779627A4D7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1BDC4681-FDBA-4E55-A247-5F779627A4D7}.Debug|x64.ActiveCfg = Debug|x64 - {1BDC4681-FDBA-4E55-A247-5F779627A4D7}.Debug|x64.Build.0 = Debug|x64 - {1BDC4681-FDBA-4E55-A247-5F779627A4D7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1BDC4681-FDBA-4E55-A247-5F779627A4D7}.Release|Any CPU.Build.0 = Release|Any CPU - {1BDC4681-FDBA-4E55-A247-5F779627A4D7}.Release|x64.ActiveCfg = Release|x64 - {1BDC4681-FDBA-4E55-A247-5F779627A4D7}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -207,9 +177,6 @@ Global {63B58D31-66BB-4879-B4F1-0969FA3F4464} = {BB93122C-21C5-4BB8-B385-74FC423D6027} {AE4034AC-27BC-43B8-9176-068B4794E25E} = {BB93122C-21C5-4BB8-B385-74FC423D6027} {ECB3825D-B309-4C76-A20D-76544459F611} = {BB93122C-21C5-4BB8-B385-74FC423D6027} - {B5E3B9D7-E91E-4B76-959D-D418E973FCAF} = {861D6F40-D3CE-46CF-B8AD-0215B9F38BE1} - {E5B52C61-66BE-4D71-88D2-E50F78011C72} = {8B80B63B-5107-4845-9F19-647CFA7911A3} - {1BDC4681-FDBA-4E55-A247-5F779627A4D7} = {BB93122C-21C5-4BB8-B385-74FC423D6027} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8CC7D7F7-CBD9-428B-A190-7A4D56C920FE} diff --git a/nuprojs/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Microsoft.ServiceFabric.Actors.KVSToRCMigration.nuproj b/nuprojs/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Microsoft.ServiceFabric.Actors.KVSToRCMigration.nuproj deleted file mode 100644 index 160cb9d9..00000000 --- a/nuprojs/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Microsoft.ServiceFabric.Actors.KVSToRCMigration.nuproj +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - Microsoft.ServiceFabric.Actors.KVSToRCMigration - Microsoft.ServiceFabric.Actors.KVSToRCMigration - This package contains the Actor Framework KVS to RC Migration APIs. - This package contains the Actor Framework KVS to RC Migration APIs. - ServiceFabric Microsoft Azure Fabric Actors - v4.8.1 - - - - - - - - lib\net462 - - - lib\net462 - - - lib\net47 - - - lib\net47 - - - lib\net471 - - - lib\net471 - - - lib\net472 - - - lib\net472 - - - lib\netstandard2.0 - - - lib\netstandard2.0 - - - runtimes\win\lib\net462 - - - runtimes\win\lib\net47 - - - runtimes\win\lib\net471 - - - runtimes\win\lib\net472 - - - - - - [$(NuGetPackageVersion)] - - - 2.2.0 - - - 2.2.7 - - - 2.2.0 - - - 2.2.0 - - - 2.2.0 - - - \ No newline at end of file diff --git a/properties/service_fabric_managed_netframework.targets b/properties/service_fabric_managed_netframework.targets index 8bfde532..4c8b9fed 100644 --- a/properties/service_fabric_managed_netframework.targets +++ b/properties/service_fabric_managed_netframework.targets @@ -7,13 +7,11 @@ $(RepoRoot)src\Microsoft.ServiceFabric.Actors.Wcf\Microsoft.ServiceFabric.Actors.Wcf.csproj; $(RepoRoot)src\Microsoft.ServiceFabric.Services\Microsoft.ServiceFabric.Services.csproj; $(RepoRoot)src\Microsoft.ServiceFabric.Services.Remoting\Microsoft.ServiceFabric.Services.Remoting.csproj; - $(RepoRoot)src\Microsoft.ServiceFabric.Services.Wcf\\Microsoft.ServiceFabric.Services.Wcf.csproj; - $(RepoRoot)src\Microsoft.ServiceFabric.Actors.KVSToRCMigration\Microsoft.ServiceFabric.Actors.KVSToRCMigration.csproj" /> + $(RepoRoot)src\Microsoft.ServiceFabric.Services.Wcf\\Microsoft.ServiceFabric.Services.Wcf.csproj;" /> + $(RepoRoot)test\unittests\Microsoft.ServiceFabric.Services.Tests\Microsoft.ServiceFabric.Services.Tests.csproj;" /> @@ -59,7 +57,6 @@ - diff --git a/properties/service_fabric_managed_netstandard.targets b/properties/service_fabric_managed_netstandard.targets index 0a8f1880..038b612c 100644 --- a/properties/service_fabric_managed_netstandard.targets +++ b/properties/service_fabric_managed_netstandard.targets @@ -6,8 +6,7 @@ + $(RepoRoot)src\netstandard\Microsoft.ServiceFabric.Services.Remoting\Microsoft.ServiceFabric.Services.Remoting_netstandard.csproj;" /> @@ -37,7 +36,6 @@ - diff --git a/properties/service_fabric_nuget.targets b/properties/service_fabric_nuget.targets index b3e6a0c3..09b78eec 100644 --- a/properties/service_fabric_nuget.targets +++ b/properties/service_fabric_nuget.targets @@ -7,8 +7,7 @@ $(RepoRoot)nuprojs\Microsoft.ServiceFabric.Services\Microsoft.ServiceFabric.Services.nuproj; $(RepoRoot)nuprojs\Microsoft.ServiceFabric.Services.Remoting\Microsoft.ServiceFabric.Services.Remoting.nuproj; $(RepoRoot)nuprojs\Microsoft.ServiceFabric.Services.Wcf\\Microsoft.ServiceFabric.Services.Wcf.nuproj; - $(RepoRoot)nuprojs\SF.ActorsServices.Internal\SF.ActorsServices.Internal.nuproj; - $(RepoRoot)nuprojs\Microsoft.ServiceFabric.Actors.KVSToRCMigration\Microsoft.ServiceFabric.Actors.KVSToRCMigration.nuproj;"/> + $(RepoRoot)nuprojs\SF.ActorsServices.Internal\SF.ActorsServices.Internal.nuproj;"/> @@ -29,7 +28,6 @@ - diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/AmbiguousActorIdHandlerBase.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/AmbiguousActorIdHandlerBase.cs deleted file mode 100644 index 894cb3f9..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/AmbiguousActorIdHandlerBase.cs +++ /dev/null @@ -1,81 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Collections.Generic; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.Runtime; - - internal abstract class AmbiguousActorIdHandlerBase : IAmbiguousActorIdHandler - { - private ActorStateProviderHelper stateProviderHelper; - - public AmbiguousActorIdHandlerBase(ActorStateProviderHelper stateProviderHelper) - { - this.stateProviderHelper = stateProviderHelper; - } - - public abstract Task TryResolveActorIdAsync(string stateStorageKey, CancellationToken cancellationToken); - - protected List GetActorIdsToResolve(string actorIdWithUnderscores) - { - var result = new List(); - var tokens = actorIdWithUnderscores.Split('_'); - var currentSearch = string.Empty; - foreach (var token in tokens) - { - currentSearch = currentSearch == string.Empty ? token : $"{currentSearch}_{token}"; - result.Add(currentSearch); - } - - return result; - } - - protected async Task TryResolveActorIdAsync(List search, Func> resolveFunc, CancellationToken cancellationToken) - { - var match = string.Empty; - foreach (var s in search) - { - if (await resolveFunc.Invoke(s, cancellationToken)) - { - if (match == string.Empty) - { - match = s; - } - else - { - return new IAmbiguousActorIdHandler.ConditionalValue - { - HasValue = false, - }; - } - } - } - - return new IAmbiguousActorIdHandler.ConditionalValue - { - HasValue = match != string.Empty, - Value = match, - }; - } - - protected virtual string StripPrefixAndSuffixTokens(string storageKey) - { - if (storageKey.StartsWith($"{ActorIdKind.String.ToString()}_")) - { - var remaining = storageKey.Substring(storageKey.IndexOf('_') + 1); - return remaining.Substring(0, remaining.LastIndexOf('_')); - } - else - { - var remaining = storageKey.Substring(storageKey.IndexOf('_') + 1); - return remaining.Substring(0, remaining.IndexOf('_')); - } - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CatchupPhaseWorkload.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CatchupPhaseWorkload.cs deleted file mode 100644 index dd62a5fb..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CatchupPhaseWorkload.cs +++ /dev/null @@ -1,27 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System.Fabric; - using Microsoft.ServiceFabric.Actors.Migration; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Services.Communication.Client; - - internal class CatchupPhaseWorkload : MigrationPhaseWorkloadBase - { - public CatchupPhaseWorkload( - int curentIteration, - KVStoRCMigrationActorStateProvider stateProvider, - ServicePartitionClient servicePartitionClient, - StatefulServiceContext statefulServiceContext, - MigrationSettings migrationSettings, - ActorTypeInformation actorTypeInfo, - string traceId) - : base(MigrationPhase.Catchup, curentIteration, 1, stateProvider, servicePartitionClient, statefulServiceContext, migrationSettings, actorTypeInfo, traceId) - { - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CommunicationListener/AspNetCoreCommunicationListener.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CommunicationListener/AspNetCoreCommunicationListener.cs deleted file mode 100644 index 643b83d5..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CommunicationListener/AspNetCoreCommunicationListener.cs +++ /dev/null @@ -1,185 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Fabric; - using System.Fabric.Description; - using System.Globalization; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.AspNetCore.Hosting; - using Microsoft.Extensions.Hosting; - using Microsoft.ServiceFabric.Services.Communication.Runtime; - - /// - /// Base class for creating AspNetCore based communication listener for Service Fabric stateless or stateful service. - /// - internal abstract class AspNetCoreCommunicationListener : ICommunicationListener - { - private readonly ServiceContext serviceContext; - private readonly ICommunicationListener internalListener; - private string urlSuffix = null; - private bool configuredToUseUniqueServiceUrl = false; - - /// - /// Initializes a new instance of the class. - /// - /// The context of the service for which this communication listener is being constructed. - /// Delegate to build Microsoft.AspNetCore.Hosting.IWebHost, endpoint url generated by the listener is given as input to this delegate. - /// This gives the flexibility to change the url before creating Microsoft.AspNetCore.Hosting.IWebHost if needed. - public AspNetCoreCommunicationListener(ServiceContext serviceContext, Func build) - { - if (serviceContext == null) - { - throw new ArgumentNullException("serviceContext"); - } - - if (build == null) - { - throw new ArgumentNullException("build"); - } - - this.serviceContext = serviceContext; - this.internalListener = new WebHostCommunicationListener(build, this); - this.urlSuffix = string.Empty; - } - - /// - /// Initializes a new instance of the class. - /// - /// The context of the service for which this communication listener is being constructed. - /// Delegate to build Microsoft.Extensions.Hosting.IHost, endpoint url generated by the listener is given as input to this delegate. - /// This gives the flexibility to change the url before creating Microsoft.Extensions.Hosting.IHost if needed. - public AspNetCoreCommunicationListener(ServiceContext serviceContext, Func build) - { - if (serviceContext == null) - { - throw new ArgumentNullException("serviceContext"); - } - - if (build == null) - { - throw new ArgumentNullException("build"); - } - - this.serviceContext = serviceContext; - this.internalListener = new GenericHostCommunicationListener(build, this); - this.urlSuffix = string.Empty; - } - - /// - /// Gets the context of the service for which this communication listener is being constructed. - /// - public ServiceContext ServiceContext - { - get { return this.serviceContext; } - } - - /// - /// Gets the url suffix to be used based on specified in - /// . - /// - public string UrlSuffix - { - get - { - return this.urlSuffix; - } - } - - /// - /// This method causes the communication listener to close. Close is a terminal state and - /// this method causes the transition to close ungracefully. Any outstanding operations - /// (including close) should be canceled when this method is called. - /// - public virtual void Abort() - { - this.internalListener.Abort(); - } - - /// - /// This method causes the communication listener to close. Close is a terminal state and - /// this method allows the communication listener to transition to this state in a graceful manner. - /// - /// Cancellation token. - /// - /// A Task that represents outstanding operation. - /// - public virtual Task CloseAsync(CancellationToken cancellationToken) - { - return this.internalListener.CloseAsync(cancellationToken); - } - - /// - /// This method causes the communication listener to be opened. Once the Open - /// completes, the communication listener becomes usable - accepts and sends messages. - /// - /// Cancellation token. - /// - /// A Task that represents outstanding operation. The result of the Task is - /// is endpoint string on which IWebHost/IHost is listening. - /// - public virtual Task OpenAsync(CancellationToken cancellationToken) - { - return this.internalListener.OpenAsync(cancellationToken); - } - - /// - /// Configures the listener to use UniqueServiceUrl by appending a urlSuffix PartitionId and ReplicaId. - /// It helps in scenarios when ServiceA listening on a node on port X moves and another Service takes its place on the same node and starts using the same port X, - /// The UniqueServiceUrl in conjunction with middleware rejects requests meant for serviceA arriving at ServiceB. - /// Example: - /// Service A is dynamically assigned port 30000 on node with IP 10.0.0.1, it listens on http://+:30000/ and reports to Naming service http://10.0.0.1:30000/serviceName-A/partitionId-A/replicaId-A - /// Client resolves URL from NS: http://10.0.0.1:30000/serviceName-A/partitionId-A/replicaId-A and sends a request, Service A compares URL path segments to its own service name, partition ID, replica ID, finds they are equal, serves request. - /// Now Service A moves to a different node and Service B comes up at the node with IP 10.0.0.1 and is dynamically assigned port 30000. - /// Service B listens on: http://+:30000/ and reports to NS http://10.0.0.1:30000/serviceName-B/partitionId-B/replicaId-B, Client for Service a sends request to http://10.0.0.1:30000/serviceName-A/partitionId-A/replicaId-A - /// Service B compares URL path segments to its own service name, partition ID, replica ID, finds they do not match, ends the request and responds with HTTP 410. Client receives 410 and re-resolves for service A. - /// - internal void ConfigureToUseUniqueServiceUrl() - { - if (!this.configuredToUseUniqueServiceUrl) - { - this.urlSuffix = string.Format(CultureInfo.InvariantCulture, "/{0}/{1}", this.serviceContext.PartitionId, this.serviceContext.ReplicaOrInstanceId); - - if (this.ServiceContext is StatefulServiceContext) - { - // For stateful service, also append a Guid, Guid makes the url unique in scenarios for stateful services when Listener is - // created to support read on secondary and change role happens from Primary->Secondary for the replica. - this.urlSuffix += "/" + Guid.NewGuid(); - } - - this.configuredToUseUniqueServiceUrl = true; - } - } - - /// - /// Gets url for this listener to be used with Web Server. - /// - /// url for this listener to be used with Web Server. - protected internal abstract string GetListenerUrl(); - - /// - /// Retrieves the endpoint resource with a given name from the service manifest. - /// - /// The name of the endpoint. - /// The endpoint resource with the specified name. - protected EndpointResourceDescription GetEndpointResourceDescription(string endpointName) - { - if (endpointName == null) - { - throw new ArgumentNullException("endpointName"); - } - - if (!this.serviceContext.CodePackageActivationContext.GetEndpoints().Contains(endpointName)) - { - throw new InvalidOperationException(string.Format("{0} not found in Service Manifest.", endpointName)); - } - - return this.serviceContext.CodePackageActivationContext.GetEndpoint(endpointName); - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CommunicationListener/GenericHostCommunicationListener.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CommunicationListener/GenericHostCommunicationListener.cs deleted file mode 100644 index 4c6a4df0..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CommunicationListener/GenericHostCommunicationListener.cs +++ /dev/null @@ -1,87 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Fabric; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.AspNetCore.Hosting.Server; - using Microsoft.AspNetCore.Hosting.Server.Features; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.Hosting; - using Microsoft.ServiceFabric.Services.Communication.Runtime; - - internal class GenericHostCommunicationListener : ICommunicationListener - { - private readonly Func build; - private readonly ServiceContext serviceContext; - private readonly AspNetCoreCommunicationListener listener; - private IHost host; - - public GenericHostCommunicationListener(Func build, AspNetCoreCommunicationListener listener) - { - this.serviceContext = listener.ServiceContext; - this.build = build; - this.listener = listener; - } - - public void Abort() - { - if (this.host != null) - { - this.host.Dispose(); - } - } - - public async Task CloseAsync(CancellationToken cancellationToken) - { - if (this.host != null) - { - await this.host.StopAsync(cancellationToken); - this.host.Dispose(); - } - } - - public async Task OpenAsync(CancellationToken cancellationToken) - { - this.host = this.build(this.listener.GetListenerUrl(), this.listener); - if (this.host == null) - { - throw new InvalidOperationException("IHost returned from build delegate is null."); - } - - await this.host.StartAsync(cancellationToken); - - var server = this.host.Services.GetService(); - if (server == null) - { - throw new InvalidOperationException("No web server found over IHost"); - } - - var url = server.Features.Get().Addresses.FirstOrDefault(); - if (url == null) - { - throw new InvalidOperationException("No Url returned from AspNetCore IServerAddressesFeature."); - } - - var publishAddress = this.serviceContext.PublishAddress; - - if (url.Contains("://+:")) - { - url = url.Replace("://+:", $"://{publishAddress}:"); - } - else if (url.Contains("://[::]:")) - { - url = url.Replace("://[::]:", $"://{publishAddress}:"); - } - - url = url.TrimEnd(new[] { '/' }); - - return url; - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CommunicationListener/HttpSysCommunicationListener.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CommunicationListener/HttpSysCommunicationListener.cs deleted file mode 100644 index e285c0f3..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CommunicationListener/HttpSysCommunicationListener.cs +++ /dev/null @@ -1,82 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Fabric; - using System.Globalization; - using Microsoft.AspNetCore.Hosting; - using Microsoft.Extensions.Hosting; - - /// - /// An AspNetCore HttpSys server based communication listener for Service Fabric stateless or stateful service. - /// - internal class HttpSysCommunicationListener : AspNetCoreCommunicationListener - { - private readonly string endpointName; - - /// - /// Initializes a new instance of the class. - /// - /// The context of the service for which this communication listener is being constructed. - /// Name of endpoint resource defined in service manifest that should be used to create the address for listener. - /// Delegate to build Microsoft.AspNetCore.Hosting.IWebHost, endpoint url generated by the listener is given as input to this delegate. - /// This gives the flexibility to change the url before creating Microsoft.AspNetCore.Hosting.IWebHost if needed. - public HttpSysCommunicationListener(ServiceContext serviceContext, string endpointName, Func build) - : base(serviceContext, build) - { - if (string.IsNullOrEmpty(endpointName)) - { - throw new ArgumentException("endpointName cannot be null or empty string."); - } - - this.endpointName = endpointName; - } - - /// - /// Initializes a new instance of the class. - /// - /// The context of the service for which this communication listener is being constructed. - /// Name of endpoint resource defined in service manifest that should be used to create the address for listener. - /// Delegate to build Microsoft.Extensions.Hosting.IHost, endpoint url generated by the listener is given as input to this delegate. - /// This gives the flexibility to change the url before creating Microsoft.Extensions.Hosting.IHost if needed. - public HttpSysCommunicationListener(ServiceContext serviceContext, string endpointName, Func build) - : base(serviceContext, build) - { - if (string.IsNullOrEmpty(endpointName)) - { - throw new ArgumentException("endpointName cannot be null or empty string."); - } - - this.endpointName = endpointName; - } - - /// - /// Gets url for the listener. Listener url is created using the endpointName passed in the constructor. - /// - /// url for the listener. - protected internal override string GetListenerUrl() - { - var serviceEndpoint = this.GetEndpointResourceDescription(this.endpointName); - var listenUrl = string.Format( - CultureInfo.InvariantCulture, - "{0}://+:{1}", - serviceEndpoint.Protocol.ToString().ToLowerInvariant(), - serviceEndpoint.Port); - - // When returning url to naming service, add UrlSuffix to it. - // This UrlSuffix will be used by middleware to: - // - drop calls not intended for the service and return 410. - // - modify Path and PathBase in Microsoft.AspNetCore.Http.HttpRequest to be sent correctly to the service code. - var uniqueUrl = string.Format( - CultureInfo.InvariantCulture, - "{0}{1}", - listenUrl, - this.UrlSuffix.ToLowerInvariant()); - - return uniqueUrl; - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CommunicationListener/WebHostCommunicationListener.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CommunicationListener/WebHostCommunicationListener.cs deleted file mode 100644 index 1e8d601b..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CommunicationListener/WebHostCommunicationListener.cs +++ /dev/null @@ -1,80 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Fabric; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.AspNetCore.Hosting; - using Microsoft.AspNetCore.Hosting.Server.Features; - using Microsoft.ServiceFabric.Services.Communication.Runtime; - - internal class WebHostCommunicationListener : ICommunicationListener - { - private readonly Func build; - private readonly ServiceContext serviceContext; - private readonly AspNetCoreCommunicationListener listener; - private IWebHost host; - - public WebHostCommunicationListener(Func build, AspNetCoreCommunicationListener listener) - { - this.serviceContext = listener.ServiceContext; - this.build = build; - this.listener = listener; - } - - public void Abort() - { - if (this.host != null) - { - this.host.Dispose(); - } - } - - public async Task CloseAsync(CancellationToken cancellationToken) - { - if (this.host != null) - { - await this.host.StopAsync(cancellationToken); - this.host.Dispose(); - } - } - - public async Task OpenAsync(CancellationToken cancellationToken) - { - this.host = this.build(this.listener.GetListenerUrl(), this.listener); - if (this.host == null) - { - throw new InvalidOperationException("IWebHost returned from build delegate is null."); - } - - await this.host.StartAsync(cancellationToken); - - var url = this.host.ServerFeatures.Get().Addresses.FirstOrDefault(); - - if (url == null) - { - throw new InvalidOperationException("No Url returned from AspNetCore IServerAddressesFeature."); - } - - var publishAddress = this.serviceContext.PublishAddress; - - if (url.Contains("://+:")) - { - url = url.Replace("://+:", $"://{publishAddress}:"); - } - else if (url.Contains("://[::]:")) - { - url = url.Replace("://[::]:", $"://{publishAddress}:"); - } - - url = url.TrimEnd(new[] { '/' }); - - return url; - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Controllers/KvsMigrationController.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Controllers/KvsMigrationController.cs deleted file mode 100644 index 3f694512..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Controllers/KvsMigrationController.cs +++ /dev/null @@ -1,133 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration.Controllers -{ - using System.Threading; - using System.Threading.Tasks; - using Microsoft.AspNetCore.Mvc; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration.Models; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Actors.Runtime.Migration; - - /// - /// Represents the controller class for KVS migration REST API. - /// - [Route("[controller]")] - internal class KvsMigrationController : ControllerBase - { - private KvsActorStateProvider kvsActorStateProvider; - private IMigrationOrchestrator migrationOrchestrator; - private KVSAmbiguousActorIdHandler ambiguousActorIdHandler; - private string traceId; - - /// - /// Initializes a new instance of the class. - /// - /// Source migraiton orchestrator - public KvsMigrationController(IMigrationOrchestrator migrationOrchestrator) - { - this.migrationOrchestrator = migrationOrchestrator; - this.kvsActorStateProvider = (KvsActorStateProvider)this.migrationOrchestrator.GetMigrationActorStateProvider(); - this.traceId = ((MigrationOrchestratorBase)this.migrationOrchestrator).TraceId; - this.ambiguousActorIdHandler = new KVSAmbiguousActorIdHandler(this.kvsActorStateProvider); - } - - /// - /// Gets the First Sequence number of KVS - /// - /// Token to signal cancellation on the asynchronous operation - /// A representing the result of the asynchronous operation. - [HttpGet("GetFirstSequenceNumber")] - public async Task GetFirstSequenceNumberAsync(CancellationToken cancellationToken) - { - return await MigrationUtility.ExecuteWithRetriesAsync( - () => this.kvsActorStateProvider.GetFirstSequenceNumberAsync(this.traceId, cancellationToken), - this.traceId, - $"{this.GetType().Name}.GetFirstSequenceNumberAsync"); - } - - /// - /// Gets the Last Sequence number of KVS - /// - /// Token to signal cancellation on the asynchronous operation - /// A representing the result of the asynchronous operation. - [HttpGet("GetLastSequenceNumber")] - public Task GetLastSequenceNumberAsync(CancellationToken cancellationToken) - { - return MigrationUtility.ExecuteWithRetriesAsync( - () => this.kvsActorStateProvider.GetLastSequenceNumberAsync(this.traceId, cancellationToken), - this.traceId, - $"{this.GetType().Name}.GetLastSequenceNumber"); - } - - /// - /// Enumerates Key value store data by Sequence Number - /// - /// EnumerationRequest - /// Token to signal cancellation on the asynchronous operation - /// A representing the result of the asynchronous operation. - [HttpGet("EnumerateBySequenceNumber")] - public async Task EnumerateBySequenceNumberAsync([FromBody] EnumerationRequest request, CancellationToken cancellationToken) - { - await MigrationUtility.ExecuteWithRetriesAsync( - () => this.kvsActorStateProvider.EnumerateAsync(request, this.Response, this.traceId, cancellationToken), - this.traceId, - $"{this.GetType().Name}.EnumerateAsync"); - } - - /// - /// Gets DisableTombstoneCleanup Setting value if KVSReplica - /// - /// A representing the result of the asynchronous operation. - [HttpGet("IsTombstoneCleanupDisabled")] - public bool IsTombstoneCleanupDisabled() - { - return this.kvsActorStateProvider.IsTombstoneCleanupDisabled(); - } - - /// - /// Starts the Downtime phase on the current partition. In the downtime phase all the actor calls are actively rejected with MigrationException. - /// - /// Token to signal cancellation on the asynchronous operation - /// A representing the asynchronous operation. - [HttpPut("StartDowntime")] - public async Task StartDowntimeAsync(CancellationToken cancellationToken) - { - await MigrationUtility.ExecuteWithRetriesAsync( - () => this.migrationOrchestrator.StartDowntimeAsync(false, cancellationToken), - this.traceId, - $"{this.GetType().Name}.StartDowntimeAsync"); - } - - /// - /// Aborts the Actor state migration on the current partition. - /// - /// Token to signal cancellation on the asynchronous operation - /// A representing the result of the asynchronous operation. - [HttpPut("AbortMigration")] - public async Task AbortMigrationAsync(CancellationToken cancellationToken) - { - await MigrationUtility.ExecuteWithRetriesAsync( - () => this.migrationOrchestrator.AbortMigrationAsync(false, cancellationToken), - this.traceId, - $"{this.GetType().Name}.AbortMigrationAsync"); - } - - /// - /// Starts the Actor state migration on the current partition. - /// - /// Token to signal cancellation on the asynchronous operation - /// A representing the result of the asynchronous operation. - [HttpPut("StartMigration")] - public async Task StartMigrationAsync(CancellationToken cancellationToken) - { - await MigrationUtility.ExecuteWithRetriesAsync( - () => this.migrationOrchestrator.StartMigrationAsync(false, cancellationToken), - this.traceId, - $"{this.GetType().Name}.StartMigrationAsync"); - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Controllers/MigrationControllerFeatureProvider.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Controllers/MigrationControllerFeatureProvider.cs deleted file mode 100644 index 0987b445..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Controllers/MigrationControllerFeatureProvider.cs +++ /dev/null @@ -1,25 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration.Controllers -{ - using System.Reflection; - using Microsoft.AspNetCore.Mvc.Controllers; - - /// - /// MigrationControllerFeatureProvider class to override IsController to be able - /// to load internal migration controllers - /// - internal class MigrationControllerFeatureProvider : ControllerFeatureProvider - { - protected override bool IsController(TypeInfo typeInfo) - { - var isMigrationController = !typeInfo.IsAbstract - && (typeof(RcMigrationController).IsAssignableFrom(typeInfo) - || typeof(KvsMigrationController).IsAssignableFrom(typeInfo)); - return isMigrationController || base.IsController(typeInfo); - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Controllers/RcMigrationController.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Controllers/RcMigrationController.cs deleted file mode 100644 index ce4e2270..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Controllers/RcMigrationController.cs +++ /dev/null @@ -1,90 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration.Controllers -{ - using System; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.AspNetCore.Mvc; - using Microsoft.ServiceFabric.Actors.Migration; - using Microsoft.ServiceFabric.Actors.Runtime.Migration; - - /// - /// Represents the controller class for KVS migration REST API. - /// - [Route("[controller]")] - internal class RcMigrationController : ControllerBase - { - private IMigrationOrchestrator migrationOrchestrator; - private string traceId; - - /// - /// Initializes a new instance of the class. - /// - /// Target Migration orchestrator - public RcMigrationController(IMigrationOrchestrator migrationOrchestrator) - { - this.migrationOrchestrator = migrationOrchestrator; - this.traceId = ((MigrationOrchestratorBase)this.migrationOrchestrator).TraceId; - } - - /// - /// Gets migration status - /// - /// Cancellation Token - /// A representing the result of the asynchronous operation. - [HttpGet("GetMigrationStatus")] - public async Task GetMigrationStatusAsync(CancellationToken cancellationToken) - { - return await MigrationUtility.ExecuteWithRetriesAsync( - () => ((TargetMigrationOrchestrator)this.migrationOrchestrator).GetResultAsync(cancellationToken), - this.traceId, - "RcMigrationController.GetMigrationStatusAsync"); - } - - /// - /// Starts the Downtime phase on the current partition. In the downtime phase all the actor calls are actively rejected with MigrationException. - /// - /// Token to signal cancellation on the asynchronous operation - /// A representing the asynchronous operation. - [HttpPut("StartDowntime")] - public async Task StartDowntimeAsync(CancellationToken cancellationToken) - { - await MigrationUtility.ExecuteWithRetriesAsync( - () => this.migrationOrchestrator.StartDowntimeAsync(true, cancellationToken), - this.traceId, - $"{this.GetType().Name}.StartDowntimeAsync"); - } - - /// - /// Aborts the Actor state migration on the current partition. - /// - /// Token to signal cancellation on the asynchronous operation - /// A representing the result of the asynchronous operation. - [HttpPut("AbortMigration")] - public async Task AbortMigrationAsync(CancellationToken cancellationToken) - { - await MigrationUtility.ExecuteWithRetriesAsync( - () => this.migrationOrchestrator.AbortMigrationAsync(true, cancellationToken), - this.traceId, - $"{this.GetType().Name}.AbortMigrationAsync"); - } - - /// - /// Starts the Actor state migration on the current partition. - /// - /// Token to signal cancellation on the asynchronous operation - /// A representing the result of the asynchronous operation. - [HttpPut("StartMigration")] - public async Task StartMigrationAsync(CancellationToken cancellationToken) - { - await MigrationUtility.ExecuteWithRetriesAsync( - () => this.migrationOrchestrator.StartMigrationAsync(true, cancellationToken), - this.traceId, - $"{this.GetType().Name}.StartMigrationAsync"); - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CopyPhaseWorkload.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CopyPhaseWorkload.cs deleted file mode 100644 index d706edaf..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/CopyPhaseWorkload.cs +++ /dev/null @@ -1,65 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System.Fabric; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration.Extensions; - using Microsoft.ServiceFabric.Actors.Migration; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Services.Communication.Client; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.MigrationConstants; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.MigrationUtility; - - internal class CopyPhaseWorkload : MigrationPhaseWorkloadBase - { - private static readonly string TraceType = typeof(CopyPhaseWorkload).Name; - - public CopyPhaseWorkload( - KVStoRCMigrationActorStateProvider stateProvider, - ServicePartitionClient servicePartitionClient, - StatefulServiceContext statefulServiceContext, - MigrationSettings migrationSettings, - ActorTypeInformation actorTypeInfo, - string traceId) - : base(MigrationPhase.Copy, 1, migrationSettings.CopyPhaseParallelism, stateProvider, servicePartitionClient, statefulServiceContext, migrationSettings, actorTypeInfo, traceId) - { - } - - protected override async Task GetStartSequenceNumberAsync(CancellationToken cancellationToken) - { - long startSequenceNumber; - using (var tx = this.Transaction) - { - var cond = await this.MetaDataDictionary.TryGetValueAsync( - tx, - MigrationLastAppliedSeqNum, - DefaultRCTimeout, - cancellationToken); - await tx.CommitAsync(); - - if (cond.HasValue) - { - startSequenceNumber = ParseLong(cond.Value, this.TraceId); - } - else - { - var response = await this.ServicePartitionClient.InvokeWebRequestWithRetryAsync( - async client => - { - return await client.HttpClient.GetAsync($"{KVSMigrationControllerName}/{GetStartSNEndpoint}"); - }, - "GetStartSequenceNumberAsync", - cancellationToken); - return (await ParseLongAsync(async () => await response.Content.ReadAsStringAsync(), this.TraceId)).Value; - } - } - - return startSequenceNumber; - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/DowntimeWorkload.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/DowntimeWorkload.cs deleted file mode 100644 index 12a55243..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/DowntimeWorkload.cs +++ /dev/null @@ -1,26 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System.Fabric; - using Microsoft.ServiceFabric.Actors.Migration; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Services.Communication.Client; - - internal class DowntimeWorkload : MigrationPhaseWorkloadBase - { - public DowntimeWorkload( - KVStoRCMigrationActorStateProvider stateProvider, - ServicePartitionClient servicePartitionClient, - StatefulServiceContext statefulServiceContext, - MigrationSettings migrationSettings, - ActorTypeInformation actorTypeInfo, - string traceId) - : base(MigrationPhase.Downtime, 1, 1, stateProvider, servicePartitionClient, statefulServiceContext, migrationSettings, actorTypeInfo, traceId) - { - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Extensions/ApplicationBuilderExtensions.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Extensions/ApplicationBuilderExtensions.cs deleted file mode 100644 index e15f5f36..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Extensions/ApplicationBuilderExtensions.cs +++ /dev/null @@ -1,38 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using Microsoft.AspNetCore.Builder; - - /// - /// Class containing extension methods for IApplicationBuilder. - /// - internal static class ApplicationBuilderExtensions - { - /// - /// Extension method to use ServiceFabricMiddleware for Service Fabric stateful or stateless service - /// using Kestrel or HttpSys as WebServer. - /// - /// Microsoft.AspNetCore.Builder.IApplicationBuilder. - /// Url suffix to determine if the request is meant for current partition and replica. - /// IApplicationBuilder instance. - public static IApplicationBuilder UseServiceFabricMiddleware(this IApplicationBuilder builder, string urlSuffix) - { - if (builder == null) - { - throw new ArgumentNullException("builder"); - } - - if (urlSuffix == null) - { - throw new ArgumentNullException("urlSuffix"); - } - - return builder.UseMiddleware(urlSuffix); - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Extensions/KvsActorStateProviderExtensions.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Extensions/KvsActorStateProviderExtensions.cs deleted file mode 100644 index f7ee9733..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Extensions/KvsActorStateProviderExtensions.cs +++ /dev/null @@ -1,337 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Collections.Generic; - using System.Fabric; - using System.Globalization; - using System.Runtime.Serialization.Json; - using System.Text; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.AspNetCore.Http; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration.Models; - using Microsoft.ServiceFabric.Actors.Migration.Exceptions; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Services; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.MigrationConstants; - - internal static class KvsActorStateProviderExtensions - { - public static readonly string TombstoneCleanupMessage = "KeyValueStoreReplicaSettings.DisableTombstoneCleanup is either not enabled or set to false"; - public static readonly DataContractJsonSerializer ResponseSerializer = new DataContractJsonSerializer(typeof(EnumerationResponse), new[] { typeof(List) }); - private static readonly string TraceType = typeof(KvsActorStateProviderExtensions).Name; - - internal static async Task GetFirstSequenceNumberAsync(this KvsActorStateProvider stateProvider, string traceId, CancellationToken cancellationToken) - { - stateProvider.ThrowIfTombCleanupIsNotEnabled(); - var storeReplica = stateProvider.GetStoreReplica(); - var lsn = storeReplica.GetLastCommittedSequenceNumber(); - return await stateProvider.GetActorStateProviderHelper().ExecuteWithRetriesAsync( - () => - { - using (var txn = storeReplica.CreateTransaction()) - { - var enumerator = storeReplica.EnumerateBySequenceNumber(txn, 0); - var hasData = enumerator.MoveNext(); - - while (hasData) - { - cancellationToken.ThrowIfCancellationRequested(); - if (enumerator.Current.Metadata.ValueSizeInBytes > 0) - { - return Task.FromResult(enumerator.Current.Metadata.SequenceNumber); - } - - hasData = enumerator.MoveNext(); - } - } - - return Task.FromResult(lsn); - }, - "GetFirstSequeceNumberAsync", - cancellationToken); - } - - internal static async Task GetLastSequenceNumberAsync(this KvsActorStateProvider stateProvider, string traceId, CancellationToken cancellationToken) - { - stateProvider.ThrowIfTombCleanupIsNotEnabled(); - cancellationToken.ThrowIfCancellationRequested(); - return await stateProvider.GetActorStateProviderHelper().ExecuteWithRetriesAsync( - async () => - { - return await Task.Run(() => - { - return stateProvider.GetStoreReplica().GetLastCommittedSequenceNumber(); - }); - }, - "GetLastSequenceNumber", - cancellationToken); - } - - internal static Task EnumerateAsync(this KvsActorStateProvider stateProvider, EnumerationRequest request, HttpResponse response, string traceId, CancellationToken cancellationToken) - { - stateProvider.ThrowIfTombCleanupIsNotEnabled(); - var storeReplica = stateProvider.GetStoreReplica(); - var lsn = storeReplica.GetLastCommittedSequenceNumber(); - return stateProvider.GetActorStateProviderHelper().ExecuteWithRetriesAsync( - async () => - { - try - { - bool hasData; - bool endSequenceNumberReached = false; - - using (var txn = storeReplica.CreateTransaction()) - { - IEnumerator enumerator; - - if (request.IncludeDeletes) - { - enumerator = storeReplica.EnumerateKeysAndTombstonesBySequenceNumber(txn, request.StartSequenceNumber); - } - else - { - enumerator = storeReplica.EnumerateBySequenceNumber(txn, request.StartSequenceNumber); - } - - hasData = enumerator.MoveNext(); - int chunk = 1; - while (hasData - && chunk <= request.NumberOfChunksPerEnumeration - && !endSequenceNumberReached) - { - cancellationToken.ThrowIfCancellationRequested(); - var pairs = new List(); - var valuePairs = new List(); - var sequenceNumberFullyDrained = true; - long? firstSNInChunk = null; - long? endSNInChunk = null; - - while (hasData - && !endSequenceNumberReached - && (pairs.Count < request.ChunkSize || !sequenceNumberFullyDrained)) - { - cancellationToken.ThrowIfCancellationRequested(); - if (firstSNInChunk == null) - { - firstSNInChunk = enumerator.Current.Metadata.SequenceNumber; - } - - var keyValuePair = await MakeKeyValuePairAsync(stateProvider, enumerator.Current, request, cancellationToken); - if (request.ComputeHash - && !keyValuePair.IsDeleted - && !MigrationUtility.IgnoreKey(keyValuePair.Key)) - { - valuePairs.Add(keyValuePair.Value); - } - - var currentSequenceNumber = keyValuePair.Version; - pairs.Add(keyValuePair); - hasData = enumerator.MoveNext(); - - if (hasData) - { - var nextKeyValuePair = enumerator.Current; - var nextKeySequenceNumber = nextKeyValuePair.Metadata.SequenceNumber; - endSequenceNumberReached = nextKeySequenceNumber > request.EndSequenceNumber; - sequenceNumberFullyDrained = !(nextKeySequenceNumber == currentSequenceNumber); - //// TODO : sequenceNumberFullyDrained?? - } - - endSNInChunk = currentSequenceNumber; - } - - var computedHash = string.Empty; - if (request.ComputeHash) - { - computedHash = CRC64.ToCRC64(valuePairs.ToArray()).ToString("X", CultureInfo.InvariantCulture); - } - - await WriteKeyValuePairsToResponseAsync( - new EnumerationResponse - { - KeyValuePairs = pairs, - EndSequenceNumberReached = endSequenceNumberReached, - ResolveActorIdsForStateKVPairs = request.ResolveActorIdsForStateKVPairs, - ValueHash = computedHash, - }, - response); - ++chunk; - } - } - } - catch (Exception e) - { - ActorTrace.Source.WriteErrorWithId(TraceType, traceId, $"{e.Message} {e.StackTrace}"); - if (e.InnerException != null) - { - ActorTrace.Source.WriteErrorWithId(TraceType, traceId, $"{e.InnerException.Message} {e.InnerException.StackTrace}/n"); - } - } - }, - "EnumerateAsync", - cancellationToken); - } - - internal static async Task TryAbortExistingTransactionsAndRejectWritesAsync(this KvsActorStateProvider stateProvider, string traceId, CancellationToken cancellationToken) - { - stateProvider.ThrowIfTombCleanupIsNotEnabled(); - cancellationToken.ThrowIfCancellationRequested(); - return await stateProvider.GetActorStateProviderHelper().ExecuteWithRetriesAsync( - async () => - { - return await Task.Run(() => - { - return stateProvider.GetStoreReplica().TryAbortExistingTransactionsAndRejectWrites(); - }); - }, - "TryAbortExistingTransactionsAndRejectWrites", - cancellationToken); - } - - internal static async Task RejectWritesAsync(this KvsActorStateProvider stateProvider, string traceId, CancellationToken cancellationToken) - { - stateProvider.ThrowIfTombCleanupIsNotEnabled(); - cancellationToken.ThrowIfCancellationRequested(); - await stateProvider.GetActorStateProviderHelper().ExecuteWithRetriesAsync( - async () => - { - using (var tx = stateProvider.GetStoreReplica().CreateTransaction()) - { - if (stateProvider.GetStoreReplica().TryGet(tx, RejectWritesKey) != null) - { - stateProvider.GetStoreReplica().TryUpdate(tx, RejectWritesKey, BitConverter.GetBytes(true)); - } - else - { - stateProvider.GetStoreReplica().TryAdd(tx, RejectWritesKey, BitConverter.GetBytes(true)); - } - - await tx.CommitAsync(); - } - }, - "RejectWritesAsync", - cancellationToken); - - await stateProvider.GetActorStateProviderHelper().ExecuteWithRetriesAsync( - () => - { - if (!stateProvider.GetStoreReplica().TryAbortExistingTransactionsAndRejectWrites()) - { - throw new FabricTransientException("Unable to abort exiting transactions."); - } - - return Task.CompletedTask; - }, - "TryAbortExistingTransactionsAndRejectWrites", - cancellationToken); - } - - internal static async Task ResumeWritesAsync(this KvsActorStateProvider stateProvider, string traceId, CancellationToken cancellationToken) - { - stateProvider.ThrowIfTombCleanupIsNotEnabled(); - cancellationToken.ThrowIfCancellationRequested(); - await stateProvider.GetActorStateProviderHelper().ExecuteWithRetriesAsync( - async () => - { - using (var tx = stateProvider.GetStoreReplica().CreateTransaction()) - { - if (stateProvider.GetStoreReplica().TryGet(tx, RejectWritesKey) != null) - { - stateProvider.GetStoreReplica().TryUpdate(tx, RejectWritesKey, BitConverter.GetBytes(false)); - } - else - { - stateProvider.GetStoreReplica().TryAdd(tx, RejectWritesKey, BitConverter.GetBytes(false)); - } - - await tx.CommitAsync(); - } - }, - "ResumeWritesAsync", - cancellationToken); - } - - internal static async Task GetRejectWriteStateAsync(this KvsActorStateProvider stateProvider, string traceId, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - return await stateProvider.GetActorStateProviderHelper().ExecuteWithRetriesAsync( - async () => - { - return await Task.Run(() => - { - using (var tx = stateProvider.GetStoreReplica().CreateTransaction()) - { - var result = stateProvider.GetStoreReplica().TryGet(tx, RejectWritesKey); - - if (result != null) - { - return BitConverter.ToBoolean(result.Value, 0); - } - } - - return false; - }); - }, - "GetRejectWriteStateAsync", - cancellationToken); - } - - internal static bool IsTombstoneCleanupDisabled(this KvsActorStateProvider stateProvider) - { - return stateProvider.GetStoreReplica().KeyValueStoreReplicaSettings.DisableTombstoneCleanup; - } - - private static async Task WriteKeyValuePairsToResponseAsync(EnumerationResponse enumerationResponse, HttpResponse httpResponse) - { - var byteArray = SerializationUtility.Serialize(ResponseSerializer, enumerationResponse); - var newLine = Encoding.UTF8.GetBytes("\n"); - - ActorTrace.Source.WriteNoise(TraceType, $"ByteArray: {byteArray} ArrayLength: {byteArray.Length}"); - - if (string.IsNullOrEmpty(httpResponse.ContentType)) - { - // Set the content type - httpResponse.ContentType = "application/json; charset=utf-8"; - } - - await httpResponse.Body.WriteAsync(byteArray, 0, byteArray.Length); - await httpResponse.Body.WriteAsync(newLine, 0, newLine.Length); - await httpResponse.Body.FlushAsync(); - } - - private static async Task MakeKeyValuePairAsync(this KvsActorStateProvider stateProvider, KeyValueStoreItem item, EnumerationRequest request, CancellationToken cancellationToken) - { - bool isDeleted = item.Metadata.ValueSizeInBytes < 0; - var result = new KeyValuePair - { - IsDeleted = isDeleted, - Version = item.Metadata.SequenceNumber, - Key = item.Metadata.Key, - Value = isDeleted ? new byte[0] : item.Value, - }; - - var ambiguousActoIdHandler = new KVSAmbiguousActorIdHandler(stateProvider); - if (request.ResolveActorIdsForStateKVPairs && item.Metadata.Key.StartsWith("Actor_")) - { - var cv = await ambiguousActoIdHandler.TryResolveActorIdAsync(item.Metadata.Key, cancellationToken); - result.ActorId = cv.HasValue ? cv.Value : null; - } - - return result; - } - - private static void ThrowIfTombCleanupIsNotEnabled(this KvsActorStateProvider stateProvider) - { - if (!stateProvider.IsTombstoneCleanupDisabled()) - { - throw new InvalidMigrationConfigException(TombstoneCleanupMessage); - } - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Extensions/ServiceParitionClientExtensions.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Extensions/ServiceParitionClientExtensions.cs deleted file mode 100644 index ef7d78b5..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Extensions/ServiceParitionClientExtensions.cs +++ /dev/null @@ -1,62 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration.Extensions -{ - using System; - using System.Fabric; - using System.Net.Http; - using System.Runtime.Serialization; - using System.Runtime.Serialization.Json; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.Migration; - using Microsoft.ServiceFabric.Services.Communication.Client; - - internal static class ServiceParitionClientExtensions - { - private static readonly DataContractJsonSerializer ErrorSerializer = new DataContractJsonSerializer(typeof(ErrorResponse)); - - public static async Task InvokeWebRequestWithRetryAsync( - this ServicePartitionClient partitionClient, - Func> asyncFunc, - string funcTag, - CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - return await partitionClient.InvokeWithRetryAsync( - async client => - { - var response = await asyncFunc.Invoke(client); - await ThrowIfErrorResponseAsync(response); - - return response; - }, - cancellationToken); - } - - private static async Task ThrowIfErrorResponseAsync(HttpResponseMessage response) - { - if (!response.IsSuccessStatusCode) - { - var buffer = await response.Content.ReadAsByteArrayAsync(); - var error = SerializationUtility.Deserialize(ErrorSerializer, buffer); - Exception ex = null; - if (error.IsFabricError) - { - ex = new FabricException(error.Message, error.ErrorCode); - } - else - { - ex = new Exception(error.Message); - } - - ex.Data.Add("ActualExceptionType", error.ExceptionType); - ex.Data.Add("IsErrorAtSource", true); - throw ex; - } - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Extensions/WebHostBuilderServiceFabricExtensions.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Extensions/WebHostBuilderServiceFabricExtensions.cs deleted file mode 100644 index f6298eb1..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Extensions/WebHostBuilderServiceFabricExtensions.cs +++ /dev/null @@ -1,58 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using Microsoft.AspNetCore.Hosting; - using Microsoft.Extensions.DependencyInjection; - - /// - /// Class containing Service Fabric related extension methods for Microsoft.AspNetCore.Hosting.IWebHostBuilder. - /// - internal static class WebHostBuilderServiceFabricExtensions - { - private static readonly string SettingName = "UseServiceFabricIntegration"; - - /// - /// Configures the Service to use ServiceFabricMiddleware and tells the listener that middleware is configured for the service so that it can - /// suffix PartitionId and ReplicaOrInstanceId to url before providing it to Service Fabric Runtime. - /// - /// The Microsoft.AspNetCore.Hosting.IWebHostBuilder to configure. - /// The to configure. - /// Options to configure ServiceFabricMiddleware and AspNetCoreCommunicationListener. - /// The Microsoft.AspNetCore.Hosting.IWebHostBuilder. - public static IWebHostBuilder UseServiceFabricIntegration(this IWebHostBuilder hostBuilder, AspNetCoreCommunicationListener listener, ServiceFabricIntegrationOptions options) - { - if (hostBuilder == null) - { - throw new ArgumentNullException("hostBuilder"); - } - - // Check if 'UseServiceFabricIntegration' has already been called. - if (hostBuilder.GetSetting(SettingName) == true.ToString()) - { - return hostBuilder; - } - - // Set flag to prevent double service configuration - hostBuilder.UseSetting(SettingName, true.ToString()); - - // Configure listener to use PartitionId and ReplicaId as urlSuffix only when specified in options. - if (options.HasFlag(ServiceFabricIntegrationOptions.UseUniqueServiceUrl)) - { - // notify listener to use urlSuffix when giving url to Service Fabric Runtime from OpenAsync() - listener.ConfigureToUseUniqueServiceUrl(); - } - - hostBuilder.ConfigureServices(services => - { - // Configure MiddleWare - services.AddSingleton(new ServiceFabricSetupFilter(listener.UrlSuffix, options)); - }); - - return hostBuilder; - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Friend.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Friend.cs deleted file mode 100644 index 011cc64b..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Friend.cs +++ /dev/null @@ -1,18 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("FabActUtil,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: InternalsVisibleTo("Microsoft.ServiceFabric.Actors,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: InternalsVisibleTo("ActorMigrationTestKvsActorService,PublicKey=00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0")] -[assembly: InternalsVisibleTo("ActorMigrationTestRcActorService,PublicKey=00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0")] -[assembly: InternalsVisibleTo("ActorMigrationTestKvsActorService,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: InternalsVisibleTo("ActorMigrationTestRcActorService,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: InternalsVisibleTo("FabActTest.ClientWorkload, PublicKey=00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0")] -[assembly: InternalsVisibleTo("FabActTest.ClientWorkload, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: InternalsVisibleTo("Microsoft.ServiceFabric.Actors.StateMigration.Tests,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: InternalsVisibleTo("Microsoft.ServiceFabric.Actors.StateMigration.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0")] -[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/HttpCommunicationClient.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/HttpCommunicationClient.cs deleted file mode 100644 index 3d470d05..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/HttpCommunicationClient.cs +++ /dev/null @@ -1,52 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Fabric; - using System.Net.Http; - using Microsoft.ServiceFabric.Services.Communication.Client; - - internal class HttpCommunicationClient : ICommunicationClient - { - private Uri endpointUri; - private HttpClient httpClient; - - public HttpCommunicationClient(string address) - { - this.endpointUri = new Uri(address.EndsWith("/") ? address : $"{address}/"); -#if !DotNetCoreClr - var handler = new WinHttpHandler(); - this.httpClient = new HttpClient(handler) - { - BaseAddress = this.endpointUri, - }; -#endif -#if DotNetCoreClr - this.httpClient = new HttpClient() - { - BaseAddress = this.endpointUri, - }; -#endif - } - - public HttpCommunicationClient(HttpClient httpClient) - { - this.endpointUri = httpClient.BaseAddress; - this.httpClient = httpClient; - } - - public Uri EndpointUri { get => this.endpointUri; } - - public HttpClient HttpClient { get => this.httpClient; } - - public ResolvedServicePartition ResolvedServicePartition { get; set; } - - public string ListenerName { get; set; } - - public ResolvedServiceEndpoint Endpoint { get; set; } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/HttpCommunicationClientFactory.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/HttpCommunicationClientFactory.cs deleted file mode 100644 index 24275cc0..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/HttpCommunicationClientFactory.cs +++ /dev/null @@ -1,46 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System.Collections.Generic; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Services.Client; - using Microsoft.ServiceFabric.Services.Communication.Client; - - internal class HttpCommunicationClientFactory : CommunicationClientFactoryBase - { - public HttpCommunicationClientFactory( - IServicePartitionResolver servicePartitionResolver = null, - IEnumerable exceptionHandlers = null, - string traceId = null) - : base(servicePartitionResolver, exceptionHandlers, traceId) - { - } - - protected override void AbortClient(HttpCommunicationClient client) - { - // Do nothing - } - - protected override Task CreateClientAsync(string endpoint, CancellationToken cancellationToken) - { - return Task.FromResult(new HttpCommunicationClient(endpoint)); - } - - protected override bool ValidateClient(HttpCommunicationClient client) - { - // Do nothing - return true; - } - - protected override bool ValidateClient(string endpoint, HttpCommunicationClient client) - { - // Do nothing - return true; - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/HttpExceptionHandler.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/HttpExceptionHandler.cs deleted file mode 100644 index da4afd20..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/HttpExceptionHandler.cs +++ /dev/null @@ -1,71 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System.Fabric; - using System.Net.Http; - using System.Net.Sockets; - using Microsoft.ServiceFabric.Services.Communication.Client; - - internal class HttpExceptionHandler : Services.Communication.Client.IExceptionHandler - { - public bool TryHandleException(ExceptionInformation exceptionInformation, OperationRetrySettings retrySettings, out ExceptionHandlingResult result) - { - ExceptionHandlingResult tempResult = new ExceptionHandlingThrowResult - { - ExceptionToThrow = exceptionInformation.Exception, - }; - - bool handled = false; - if (exceptionInformation.Exception is FabricException) - { - var fabricEx = exceptionInformation.Exception as FabricException; - switch (fabricEx.ErrorCode) - { - case FabricErrorCode.NotPrimary: - case FabricErrorCode.NotReadable: - case FabricErrorCode.FabricEndpointNotFound: - tempResult = new ExceptionHandlingRetryResult(fabricEx, false, retrySettings, retrySettings.DefaultMaxRetryCountForTransientErrors); - handled = true; - break; - default: - handled = false; - break; - } - - if (fabricEx is FabricTransientException - || (fabricEx.Data.Contains("ActualExceptionType") && (string)fabricEx.Data["ActualExceptionType"] == typeof(FabricTransientException).FullName)) - { - switch (fabricEx.ErrorCode) - { - case FabricErrorCode.DatabaseMigrationInProgress: - handled = true; - new ExceptionHandlingThrowResult { ExceptionToThrow = fabricEx }; - break; - default: - new ExceptionHandlingRetryResult(fabricEx, true, retrySettings, retrySettings.DefaultMaxRetryCountForNonTransientErrors); - handled = true; - break; - } - } - } - else if (exceptionInformation.Exception is HttpRequestException) - { - if (exceptionInformation.Exception.InnerException != null && exceptionInformation.Exception.InnerException is SocketException) - { - if (((SocketException)exceptionInformation.Exception.InnerException).SocketErrorCode == SocketError.ConnectionRefused) - { - tempResult = new ExceptionHandlingRetryResult(exceptionInformation.Exception, false, retrySettings, retrySettings.DefaultMaxRetryCountForNonTransientErrors); - handled = true; - } - } - } - - result = tempResult; - return handled; - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/IAmbiguousActorIdHandler.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/IAmbiguousActorIdHandler.cs deleted file mode 100644 index fedbfa72..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/IAmbiguousActorIdHandler.cs +++ /dev/null @@ -1,40 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System.Threading; - using System.Threading.Tasks; - - /// - /// ActorId Handler. - /// - public interface IAmbiguousActorIdHandler - { - /// - /// Resolves actor id for a give storage key. - /// - /// State storage key. - /// Token to cancel asynchronous operation. - /// Conditional value with resolved actor id. - public Task TryResolveActorIdAsync(string stateStorageKey, CancellationToken cancellationToken); - - /// - /// Condtional Value. - /// - public class ConditionalValue - { - /// - /// Gets or sets the Value. - /// - public string Value { get; set; } - - /// - /// Gets or sets a value indicating whether the ConditionalValue.Value exists. - /// - public bool HasValue { get; set; } - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/IMigrationPhaseWorkload.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/IMigrationPhaseWorkload.cs deleted file mode 100644 index 5b9dbd9d..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/IMigrationPhaseWorkload.cs +++ /dev/null @@ -1,29 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.Migration; - - /// - /// Interface definition for migration workload by phase. - /// - internal interface IMigrationPhaseWorkload - { - /// - /// Gets the current migration phase. - /// - MigrationPhase Phase { get; } - - /// - /// Starts a new phase or resumes the current migration phase after failover. - /// - /// Token to cancel the task. - /// Returns the migration result. - Task StartOrResumeMigrationAsync(CancellationToken cancellationToken); - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/IWorker.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/IWorker.cs deleted file mode 100644 index 0f0dbd3e..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/IWorker.cs +++ /dev/null @@ -1,30 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System.Threading; - using System.Threading.Tasks; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.PhaseInput; - using static Microsoft.ServiceFabric.Actors.Migration.PhaseResult; - - /// - /// Interface definition for workers. - /// - internal interface IWorker - { - /// - /// Gets the worker input information. - /// - public WorkerInput Input { get; } - - /// - /// Starts a new worker. - /// - /// Token to cancel the task. - /// Returns the worker result. - Task StartWorkAsync(CancellationToken cancellationToken); - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/KVSAmbiguousActorIdHandler.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/KVSAmbiguousActorIdHandler.cs deleted file mode 100644 index 862f378d..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/KVSAmbiguousActorIdHandler.cs +++ /dev/null @@ -1,64 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.Runtime; - - internal class KVSAmbiguousActorIdHandler : AmbiguousActorIdHandlerBase - { - private const string ActorStorageKeyPrefix = "Actor"; - private KvsActorStateProvider stateProvider; - - public KVSAmbiguousActorIdHandler(KvsActorStateProvider stateProvider) - : base(stateProvider.GetActorStateProviderHelper()) - { - this.stateProvider = stateProvider; - } - - public override async Task TryResolveActorIdAsync(string stateStorageKey, CancellationToken cancellationToken) - { - if (!stateStorageKey.StartsWith($"{ActorStorageKeyPrefix}_")) - { - return new IAmbiguousActorIdHandler.ConditionalValue - { - HasValue = false, - }; - } - - var actorIdMatch = this.StripPrefixAndSuffixTokens(stateStorageKey); - var matchList = this.GetActorIdsToResolve(actorIdMatch); - if (matchList.Count == 1) - { - return new IAmbiguousActorIdHandler.ConditionalValue - { - HasValue = true, - Value = matchList[0], - }; - } - - return await this.TryResolveActorIdAsync( - matchList, - (match, _) => - { - using (var txn = this.stateProvider.GetStoreReplica().CreateTransaction()) - { - var contains = this.stateProvider.GetStoreReplica().Contains(txn, $"@@_String_{match}"); - - return Task.FromResult(contains); - } - }, - cancellationToken); - } - - protected override string StripPrefixAndSuffixTokens(string stateStorageKey) - { - var remaining = stateStorageKey.Substring(stateStorageKey.IndexOf('_') + 1); - return base.StripPrefixAndSuffixTokens(remaining); - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/KVStoRCMigrationActorStateProvider.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/KVStoRCMigrationActorStateProvider.cs deleted file mode 100644 index 25d3ded6..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/KVStoRCMigrationActorStateProvider.cs +++ /dev/null @@ -1,698 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Collections.Generic; - using System.Fabric; - using System.Globalization; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration.Models; - using Microsoft.ServiceFabric.Actors.Migration; - using Microsoft.ServiceFabric.Actors.Query; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Data; - using Microsoft.ServiceFabric.Data.Collections; - using Microsoft.ServiceFabric.Services; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.MigrationConstants; - - /// - /// Provides an implementation of which - /// uses to store and persist the actor state. - /// - internal class KVStoRCMigrationActorStateProvider : - IActorStateProvider, VolatileLogicalTimeManager.ISnapshotHandler, IActorStateProviderInternal - { - private string traceId; - private IReliableCollectionsActorStateProviderInternal rcStateProvider; - private IStatefulServicePartition servicePartition; - private IReliableDictionary2 metadataDictionary; - private bool isMetadataDictInitialized = false; - private Task stateProviderInitTask; - private StatefulServiceInitializationParameters initParams; - private CancellationTokenSource stateProviderInitCts; - private RCAmbiguousActorIdHandler ambiguousActorIdHandler; - - /// - /// Initializes a new instance of the class. - /// - public KVStoRCMigrationActorStateProvider() - : this(new ReliableCollectionsActorStateProvider()) - { - } - - /// - /// Initializes a new instance of the class with specified reliableCollectionsActorStateProvider - /// - /// - /// The that carries out regular operations of state provider. - /// - public KVStoRCMigrationActorStateProvider(IReliableCollectionsActorStateProviderInternal reliableCollectionsActorStateProvider) - { - this.rcStateProvider = reliableCollectionsActorStateProvider; - this.ambiguousActorIdHandler = new RCAmbiguousActorIdHandler(this.rcStateProvider); - } - - /// - public Func OnRestoreCompletedAsync { set => ((IStateProviderReplica2)this.rcStateProvider).OnRestoreCompletedAsync = value; } - - /// - public Func> OnDataLossAsync { set => ((IStateProviderReplica)this.rcStateProvider).OnDataLossAsync = value; } - - /// - public string TraceType - { - get { return "KVStoRCMigrationActorStateProvider"; } - } - - /// - public string TraceId { get => ((IActorStateProviderInternal)this.rcStateProvider).TraceId; } - - /// - public ReplicaRole CurrentReplicaRole { get => ((IActorStateProviderInternal)this.rcStateProvider).CurrentReplicaRole; } - - /// - public TimeSpan TransientErrorRetryDelay { get => ((IActorStateProviderInternal)this.rcStateProvider).TransientErrorRetryDelay; } - - /// - public TimeSpan OperationTimeout { get => ((IActorStateProviderInternal)this.rcStateProvider).OperationTimeout; } - - /// - public TimeSpan CurrentLogicalTime { get => ((IActorStateProviderInternal)this.rcStateProvider).CurrentLogicalTime; } - - /// - public long RoleChangeTracker { get => ((IActorStateProviderInternal)this.rcStateProvider).RoleChangeTracker; } - - internal IStatefulServicePartition StatefulServicePartition { get => this.servicePartition; } - - /// - public void Initialize(ActorTypeInformation actorTypeInformation) - { - ((IActorStateProvider)this.rcStateProvider).Initialize(actorTypeInformation); - } - - /// - public Task ActorActivatedAsync(ActorId actorId, CancellationToken cancellationToken = default) - { - return ((IActorStateProvider)this.rcStateProvider).ActorActivatedAsync(actorId, cancellationToken); - } - - /// - public Task ReminderCallbackCompletedAsync(ActorId actorId, IActorReminder reminder, CancellationToken cancellationToken = default) - { - return ((IActorStateProvider)this.rcStateProvider).ReminderCallbackCompletedAsync(actorId, reminder, cancellationToken); - } - - /// - public Task LoadStateAsync(ActorId actorId, string stateName, CancellationToken cancellationToken = default) - { - return ((IActorStateProvider)this.rcStateProvider).LoadStateAsync(actorId, stateName, cancellationToken); - } - - /// - public Task SaveStateAsync(ActorId actorId, IReadOnlyCollection stateChanges, CancellationToken cancellationToken = default) - { - return ((IActorStateProvider)this.rcStateProvider).SaveStateAsync(actorId, stateChanges, cancellationToken); - } - - /// - public Task ContainsStateAsync(ActorId actorId, string stateName, CancellationToken cancellationToken = default) - { - return ((IActorStateProvider)this.rcStateProvider).ContainsStateAsync(actorId, stateName, cancellationToken); - } - - /// - public Task RemoveActorAsync(ActorId actorId, CancellationToken cancellationToken = default) - { - return ((IActorStateProvider)this.rcStateProvider).RemoveActorAsync(actorId, cancellationToken); - } - - /// - public Task> EnumerateStateNamesAsync(ActorId actorId, CancellationToken cancellationToken = default) - { - return ((IActorStateProvider)this.rcStateProvider).EnumerateStateNamesAsync(actorId, cancellationToken); - } - - /// - public Task> GetActorsAsync(int numItemsToReturn, ContinuationToken continuationToken, CancellationToken cancellationToken) - { - return ((IActorStateProvider)this.rcStateProvider).GetActorsAsync(numItemsToReturn, continuationToken, cancellationToken); - } - - /// - public Task>>> GetRemindersAsync(int numItemsToReturn, ActorId actorId, ContinuationToken continuationToken, CancellationToken cancellationToken) - { - return ((IActorStateProvider)this.rcStateProvider).GetRemindersAsync(numItemsToReturn, actorId, continuationToken, cancellationToken); - } - - /// - public Task SaveReminderAsync(ActorId actorId, IActorReminder reminder, CancellationToken cancellationToken = default) - { - return ((IActorStateProvider)this.rcStateProvider).SaveReminderAsync(actorId, reminder, cancellationToken); - } - - /// - public Task DeleteReminderAsync(ActorId actorId, string reminderName, CancellationToken cancellationToken = default) - { - return ((IActorStateProvider)this.rcStateProvider).DeleteReminderAsync(actorId, reminderName, cancellationToken); - } - - /// - public Task DeleteRemindersAsync(IReadOnlyDictionary> reminderNames, CancellationToken cancellationToken = default) - { - return ((IActorStateProvider)this.rcStateProvider).DeleteRemindersAsync(reminderNames, cancellationToken); - } - - /// - public Task LoadRemindersAsync(CancellationToken cancellationToken = default) - { - return ((IActorStateProvider)this.rcStateProvider).LoadRemindersAsync(cancellationToken); - } - - /// - public void Initialize(StatefulServiceInitializationParameters initializationParameters) - { - this.traceId = ActorTrace.GetTraceIdForReplica(initializationParameters.PartitionId, initializationParameters.ReplicaId); - this.initParams = initializationParameters; - ((IStateProviderReplica)this.rcStateProvider).Initialize(initializationParameters); - } - - /// - public Task OpenAsync(ReplicaOpenMode openMode, IStatefulServicePartition partition, CancellationToken cancellationToken) - { - this.servicePartition = partition; - return ((IStateProviderReplica)this.rcStateProvider).OpenAsync(openMode, partition, cancellationToken); - } - - /// - async Task IStateProviderReplica.ChangeRoleAsync(ReplicaRole newRole, CancellationToken cancellationToken) - { - await ((IStateProviderReplica)this.rcStateProvider).ChangeRoleAsync(newRole, cancellationToken); - if (newRole == ReplicaRole.Primary) - { - this.stateProviderInitCts = new CancellationTokenSource(); - this.stateProviderInitTask = this.StartStateProviderInitialization(this.stateProviderInitCts.Token); - } - else - { - await this.CancelStateProviderInitializationAsync(); - } - } - - /// - public Task CloseAsync(CancellationToken cancellationToken) - { - return ((IStateProviderReplica)this.rcStateProvider).CloseAsync(cancellationToken); - } - - /// - public void Abort() - { - ((IStateProviderReplica)this.rcStateProvider).Abort(); - } - - /// - public Task BackupAsync(Func> backupCallback) - { - return ((IStateProviderReplica)this.rcStateProvider).BackupAsync(backupCallback); - } - - /// - public Task BackupAsync(BackupOption option, TimeSpan timeout, CancellationToken cancellationToken, Func> backupCallback) - { - return ((IStateProviderReplica)this.rcStateProvider).BackupAsync(option, timeout, cancellationToken, backupCallback); - } - - /// - public Task RestoreAsync(string backupFolderPath) - { - return ((IStateProviderReplica)this.rcStateProvider).RestoreAsync(backupFolderPath); - } - - /// - public Task RestoreAsync(string backupFolderPath, RestorePolicy restorePolicy, CancellationToken cancellationToken) - { - return ((IStateProviderReplica)this.rcStateProvider).RestoreAsync(backupFolderPath, restorePolicy, cancellationToken); - } - - /// - public Task OnSnapshotAsync(TimeSpan currentLogicalTime) - { - return ((VolatileLogicalTimeManager.ISnapshotHandler)this.rcStateProvider).OnSnapshotAsync(currentLogicalTime); - } - - /// - /// Modifies data from KVS store into a suitable format for RC. Saves the modified data in RC store. - /// - /// - /// Data from KVS store that needs to be modified and saved in RC - /// - /// - /// Cancellation token - /// - /// If true, attempts to resolve the actorid(ambiguous) from user resolver implementation. - /// If false, then local presence dictionary is used before user resolvers. - /// A representing the result of the asynchronous operation. - public virtual async Task SaveStateAsync(List kvsData, CancellationToken cancellationToken, bool skipPresenceDictResolve = false) - { - List keysMigrated = new List(); - int presenceKeyCount = 0, reminderCompletedKeyCount = 0, logicalTimeCount = 0, actorStateCount = 0, reminderCount = 0; - long lastAppliedSN = -1; - return await this.rcStateProvider.GetActorStateProviderHelper().ExecuteWithRetriesAsync( - async () => - { - using (var tx = this.GetStateManager().CreateTransaction()) - { - try - { - foreach (var data in kvsData) - { - byte[] rcValue = { }; - var dictionary = await this.GetDictionaryFromKVSKeyAsync(data, tx, skipPresenceDictResolve, cancellationToken); - if (dictionary == null) - { - continue; - } - - var rcKey = this.TransformKVSKeyToRCFormat(data.Key); - if (!data.IsDeleted) - { - rcValue = data.Value; - if (data.Key.StartsWith(ActorPresenceKeyPrefix)) - { - presenceKeyCount++; - } - else if (data.Key.StartsWith(ActorStorageKeyPrefix)) - { - actorStateCount++; - } - else if (data.Key.StartsWith(ReminderCompletedeStorageKeyPrefix)) - { - ReminderCompletedData reminderCompletedData = MigrationUtility.KVS.DeserializeReminderCompletedData(data.Key, data.Value, this.TraceId); - rcValue = MigrationUtility.RC.SerializeReminderCompletedData(data.Key, reminderCompletedData, this.TraceId); - reminderCompletedKeyCount++; - } - else if (data.Key.StartsWith(ReminderStorageKeyPrefix)) - { - ActorReminderData reminderCompletedData = MigrationUtility.KVS.DeserializeReminder(data.Key, data.Value, this.TraceId); - rcValue = MigrationUtility.RC.SerializeReminder(data.Key, reminderCompletedData, this.TraceId); - reminderCount++; - } - - cancellationToken.ThrowIfCancellationRequested(); - await dictionary.AddOrUpdateAsync(tx, rcKey, rcValue, (k, v) => rcValue); - } - else - { - if (!(await dictionary.TryRemoveAsync(tx, rcKey)).HasValue) - { - // It should be fine, if we are unable to delete the entry, since the data validation would catch any abnormallity. - ActorTrace.Source.WriteInfoWithId( - this.TraceType, - this.traceId, - $"Failed to apply tombstone. Common cause for this behavior could be a failover."); - } - } - - keysMigrated.Add(data.Key); - lastAppliedSN = data.Version; - } - - await tx.CommitAsync(); - } - catch (Exception ex) - { - await this.metadataDictionary.TryAddAsync( - tx, - MigrationConstants.MigrationEndDateTimeUTC, - DateTime.UtcNow.ToString(), - MigrationConstants.DefaultRCTimeout, - cancellationToken); - - await this.metadataDictionary.AddOrUpdateAsync( - tx, - MigrationConstants.MigrationCurrentStatus, - MigrationState.Aborted.ToString(), - (_, __) => MigrationState.Aborted.ToString(), - MigrationConstants.DefaultRCTimeout, - cancellationToken); - - // Commit with the same transaction to avoid race condition during failover. - await tx.CommitAsync(); - - throw ex; - } - - ActorTrace.Source.WriteNoiseWithId(this.TraceType, this.traceId, string.Join(MigrationConstants.DefaultDelimiter.ToString(), keysMigrated)); - - string infoLevelMessage = "Migrated " + presenceKeyCount + " presence keys, " - + reminderCompletedKeyCount + " reminder completed keys, " - + logicalTimeCount + " logical timestamps, " - + actorStateCount + " actor states and " - + reminderCount + " reminders."; - ActorTrace.Source.WriteInfoWithId(this.TraceType, this.traceId, infoLevelMessage); - return keysMigrated.Count; - } - }, - "KVSToRCMigrationActorStateProvide.SaveStateAsync", - cancellationToken); - } - - internal virtual async Task> GetMetadataDictionaryAsync() - { - await this.stateProviderInitTask; - return this.metadataDictionary; - } - - internal StatefulServiceInitializationParameters GetInitParams() - { - return this.initParams; - } - - internal IReliableStateManagerReplica2 GetStateManager() - { - return this.rcStateProvider.GetStateManager(); - } - - internal virtual async Task ValidateDataPostMigrationAsync(List kvsData, string hashToCompare, bool skipPresenceDictResolve, CancellationToken cancellationToken) - { - var values = new List(); - foreach (var data in kvsData) - { - if (MigrationUtility.IgnoreKey(data.Key)) - { - continue; - } - - using (var tx = this.GetStateManager().CreateTransaction()) - { - var rcKey = this.TransformKVSKeyToRCFormat(data.Key); - var dictionary = await this.GetDictionaryFromKVSKeyAsync(data, tx, skipPresenceDictResolve, cancellationToken); - if (dictionary == null) - { - continue; - } - - var condValue = await dictionary.TryGetValueAsync(tx, rcKey); - if (condValue.HasValue) - { - if (data.IsDeleted) - { - ActorTrace.Source.WriteErrorWithId( - this.TraceType, - this.traceId, - $"{data.Key} exists while it is expected to be deleted"); - - throw new MigrationDataValidationException("Post migration validation checks failed."); - } - else - { - var rcValue = condValue.Value; - if (data.Key.StartsWith(ReminderStorageKeyPrefix)) - { - var reminderdata = MigrationUtility.RC.DeserializeReminder(rcKey, rcValue, this.TraceId); - rcValue = MigrationUtility.KVS.SerializeReminder(data.Key, reminderdata, this.TraceId); - } - else if (data.Key.StartsWith(ReminderCompletedeStorageKeyPrefix)) - { - var remCompletedData = MigrationUtility.RC.DeserializeReminderCompletedData(rcKey, rcValue, this.TraceId); - rcValue = MigrationUtility.KVS.SerializeReminderCompletedData(data.Key, remCompletedData, this.TraceId); - var temp = MigrationUtility.KVS.DeserializeReminderCompletedData(data.Key, rcValue, this.TraceId); - var rcValue1 = MigrationUtility.KVS.SerializeReminderCompletedData(data.Key, remCompletedData, this.TraceId); - } - - values.Add(rcValue); - } - } - else - { - if (!data.IsDeleted) - { - ActorTrace.Source.WriteErrorWithId( - this.TraceType, - this.traceId, - $"{data.Key} is not found."); - - throw new MigrationDataValidationException("Post migration validation checks failed."); - } - } - } - } - - var computedHash = CRC64.ToCRC64(values.ToArray()).ToString("X", CultureInfo.InvariantCulture); - if (!computedHash.Equals(hashToCompare, StringComparison.InvariantCulture)) - { - ActorTrace.Source.WriteErrorWithId( - this.TraceType, - this.traceId, - "Migration data hashes do not compare to equal"); - - throw new MigrationDataValidationException("Post migration validation checks failed."); - } - } - - internal IReliableCollectionsActorStateProviderInternal GetInternalStateProvider() - { - return this.rcStateProvider; - } - - internal string TransformKVSKeyToRCFormat(string key) - { - int firstUnderscorePosition = key.IndexOf("_"); - if (key.StartsWith("@@")) - { - return key.Substring(firstUnderscorePosition + 1) + "_"; - } - - return key.Substring(firstUnderscorePosition + 1); - } - - private async Task> GetDictionaryFromKVSKeyAsync(KeyValuePair data, Data.ITransaction tx, bool skipPresenceDictResolve, CancellationToken cancellationToken) - { - var key = data.Key; - IReliableDictionary2 temp = null; - if (key.StartsWith(ActorPresenceKeyPrefix)) - { - temp = this.rcStateProvider.GetActorPresenceDictionary(); - } - else if (key.StartsWith(ActorStorageKeyPrefix)) - { - ActorId actorId; - if (string.IsNullOrEmpty(data.ActorId)) - { - var rcKey = this.TransformKVSKeyToRCFormat(data.Key); - actorId = await this.ambiguousActorIdHandler.ResolveActorIdAsync(rcKey, tx, cancellationToken, skipPresenceDictResolve); - } - else - { - actorId = new ActorId(data.ActorId); - } - - temp = this.rcStateProvider.GetActorStateDictionary(actorId); - } - else if (key.StartsWith(ReminderCompletedeStorageKeyPrefix)) - { - temp = this.rcStateProvider.GetReminderCompletedDictionary(); - } - else if (key.StartsWith(ReminderStorageKeyPrefix)) - { - temp = this.rcStateProvider.GetReminderDictionary(this.GetActorIdFromStorageKey(key)); - } - else if (key.Equals(LogicalTimestampKey) - || key.StartsWith(MigrationConstants.RejectWritesKey)) - { - ActorTrace.Source.WriteInfoWithId( - this.TraceType, - this.traceId, - $"Ignoring KVS key - {key}", - key); - } - else - { - var message = "Migration Error: Failed to parse the KVS key - " + key; - - ActorTrace.Source.WriteWarningWithId( - this.TraceType, - this.traceId, - message); - } - - return temp; - } - - private ActorId GetActorIdFromStorageKey(string key) - { - // It is not right to assume the ActorId wouldn't have underscores. - // TODO: Handle this in ambiguous ActorId PR - var startIndex = this.GetNthIndex(key, '_', 2); - var endIndex = this.GetNthIndex(key, '_', 3); - var actorId = new ActorId(key.Substring(startIndex + 1, endIndex - startIndex - 1)); - - ActorTrace.Source.WriteNoiseWithId( - this.TraceType, - this.traceId, - $"GetActorIdFromStorageKey - ActorId: {actorId}, Key : {key}"); - - return actorId; - } - - private int GetNthIndex(string s, char t, int n) - { - int count = 0; - for (int i = 0; i < s.Length; i++) - { - if (s[i] == t) - { - count++; - if (count == n) - { - return i; - } - } - } - - return -1; - } - - private async Task InitializeMetadataDictAsync(CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - ActorTrace.Source.WriteInfoWithId(this.TraceType, this.traceId, "Initializing metadata dictionary"); - - if (this.isMetadataDictInitialized) - { - ActorTrace.Source.WriteInfoWithId(this.TraceType, this.traceId, "Metadata dictionary already registered."); - return; - } - - IReliableDictionary2 metadataDict = null; - - using (var tx = this.rcStateProvider.GetStateManager().CreateTransaction()) - { - try - { - metadataDict = await this.GetOrAddDictionaryAsync(tx, MigrationConstants.MetadataDictionaryName); - cancellationToken.ThrowIfCancellationRequested(); - await tx.CommitAsync(); - } - catch (Exception e) - { - ActorTrace.Source.WriteInfoWithId(this.TraceType, this.traceId, e.Message); - } - } - - this.metadataDictionary = metadataDict; - - Volatile.Write(ref this.isMetadataDictInitialized, true); - ActorTrace.Source.WriteInfoWithId(this.TraceType, this.traceId, "Registering Metadata dictionary SUCCEEDED."); - } - - private Task> GetOrAddDictionaryAsync(ITransaction tx, string dictionaryName) - { - return this.rcStateProvider.GetStateManager().GetOrAddAsync>(tx, dictionaryName); - } - - private async Task WaitForWriteStatusAsync(CancellationToken cancellationToken) - { - var retryCount = 0; - - while (!cancellationToken.IsCancellationRequested && - this.servicePartition.WriteStatus != PartitionAccessStatus.Granted) - { - retryCount++; - await Task.Delay(retryCount * 500, cancellationToken); - } - } - - private async Task StartStateProviderInitialization(CancellationToken cancellationToken) - { - Exception unexpectedException = null; - try - { - var stateProviderHelper = new ActorStateProviderHelper(this); - cancellationToken.ThrowIfCancellationRequested(); - await stateProviderHelper.ExecuteWithRetriesAsync( - async () => - { - await this.WaitForWriteStatusAsync(cancellationToken); - await this.InitializeMetadataDictAsync(cancellationToken); - }, - "StartStateProviderInitialization", - cancellationToken); - } - catch (OperationCanceledException opEx) - { - if (!cancellationToken.IsCancellationRequested) - { - unexpectedException = opEx; - } - } - catch (FabricObjectClosedException) - { - // This can happen when replica is closing. CancellationToken should get signaled. - // Fall through and let the task check for CancellationToken. - } - catch (FabricNotPrimaryException) - { - // This replica is no more primary. CancellationToken should get signaled. - // Fall through and let the task check for CancellationToken. - } - catch (Exception ex) - { - unexpectedException = ex; - } - - if (unexpectedException != null) - { - var msgFormat = "StartStateProviderInitialization() failed due to " + - "an unexpected Exception causing replica to fault: {0}"; - - ActorTrace.Source.WriteErrorWithId( - this.TraceType, - this.traceId, - string.Format(msgFormat, unexpectedException.ToString())); - - this.servicePartition.ReportFault(FaultType.Transient); - } - } - - private async Task CancelStateProviderInitializationAsync() - { - if (this.stateProviderInitCts != null - && this.stateProviderInitTask != null - && this.stateProviderInitCts.IsCancellationRequested == false) - { - try - { - ActorTrace.Source.WriteInfoWithId(this.TraceType, this.traceId, "Canceling state provider initialization"); - - this.stateProviderInitCts.Cancel(); - - await this.stateProviderInitTask; - } - catch (Exception ex) - { - var msgFormat = "StartStateProviderInitialization() failed due to " + - "an unexpected Exception causing replica to fault: {0}"; - - ActorTrace.Source.WriteErrorWithId( - this.TraceType, - this.traceId, - string.Format(msgFormat, ex.ToString())); - - this.servicePartition.ReportFault(FaultType.Transient); - } - finally - { - this.stateProviderInitCts = null; - this.stateProviderInitTask = null; - } - } - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Microsoft.ServiceFabric.Actors.KVSToRCMigration.csproj b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Microsoft.ServiceFabric.Actors.KVSToRCMigration.csproj deleted file mode 100644 index 7d6180d0..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Microsoft.ServiceFabric.Actors.KVSToRCMigration.csproj +++ /dev/null @@ -1,34 +0,0 @@ - - - - - {B5E3B9D7-E91E-4B76-959D-D418E973FCAF} - Microsoft.ServiceFabric.Actors.KVSToRCMigration - $(AssemblyName) - $(AssemblyName) - $(OutputPath)\$(AssemblyName).xml - net462 - true - 1591 - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Middleware/DefaultMigrationExceptionMiddleware.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Middleware/DefaultMigrationExceptionMiddleware.cs deleted file mode 100644 index b22b5f56..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Middleware/DefaultMigrationExceptionMiddleware.cs +++ /dev/null @@ -1,63 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration.Middleware -{ - using System; - using System.Fabric; - using System.Net; - using System.Runtime.Serialization.Json; - using System.Threading.Tasks; - using Microsoft.AspNetCore.Http; - using Microsoft.ServiceFabric.Actors.Migration; - - internal class DefaultMigrationExceptionMiddleware - { - private static readonly DataContractJsonSerializer Serializer = new DataContractJsonSerializer(typeof(ErrorResponse)); - private readonly RequestDelegate next; - - public DefaultMigrationExceptionMiddleware(RequestDelegate next) - { - this.next = next; - } - - public async Task Invoke(HttpContext context) - { - try - { - await this.next.Invoke(context); - } - catch (Exception ex) - { - await this.HandleExceptionAsync(context, ex); - } - } - - private async Task HandleExceptionAsync(HttpContext context, Exception exception) - { - var response = context.Response; - var error = new ErrorResponse - { - Message = exception.Message, - ErrorCode = 0, - ExceptionType = exception.GetType().FullName, - IsFabricError = false, - }; - - if (exception is FabricException) - { - var fabEx = exception as FabricException; - error.IsFabricError = true; - error.ErrorCode = fabEx.ErrorCode; - } - - response.ContentType = "application/json; charset=utf-8"; - response.StatusCode = (int)HttpStatusCode.InternalServerError; - var buffer = SerializationUtility.Serialize(Serializer, error); - await response.Body.WriteAsync(buffer, 0, buffer.Length); - await response.Body.FlushAsync(); - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Middleware/ServiceFabricIntegrationOptions.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Middleware/ServiceFabricIntegrationOptions.cs deleted file mode 100644 index c5e5bfba..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Middleware/ServiceFabricIntegrationOptions.cs +++ /dev/null @@ -1,26 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - - /// - /// Integration options for method when used with Microsoft.AspNetCore.Hosting.IWebHostBuilder. - /// - [Flags] - internal enum ServiceFabricIntegrationOptions - { - /// - /// This option will not configure the to add any suffix to url when providing the url to Service Fabric Runtime from its method. - /// - None = 0x00, - - /// - /// This option will configure the to add a url suffix containing and - /// to url when providing the url to Service Fabric Runtime from its method. - /// - UseUniqueServiceUrl = 0x01, - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Middleware/ServiceFabricMiddleware.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Middleware/ServiceFabricMiddleware.cs deleted file mode 100644 index 19e92ef7..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Middleware/ServiceFabricMiddleware.cs +++ /dev/null @@ -1,64 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Threading.Tasks; - using Microsoft.AspNetCore.Http; - - /// - /// A middleware to be used with Service Fabric stateful and stateless services hosted in Kestrel or HttpSys. - /// This middleware examines the Microsoft.AspNetCore.Http.HttpRequest.Path in request to determine if the request is intended for this replica. - /// - /// - /// This middleware when used with Kestrel and HttpSys based Service Fabric Communication Listeners allows handling of scenarios when - /// the Replica1 listening on Node1 and por11 has moved and another Replica2 is opened on Node1 got Port1. - /// A client which has resolved Replica1 before it moved, will send the request to Node1:Port1. Using this middleware - /// Replica2 can reject calls which were meant for Replica1 by examining the Path in incoming request. - /// - internal class ServiceFabricMiddleware - { - private readonly RequestDelegate next; - private readonly string urlSuffix; - - /// - /// Initializes a new instance of the class. - /// - /// Next request handler in pipeline. - /// Url suffix to determine if the request is meant for current partition and replica. - public ServiceFabricMiddleware(RequestDelegate next, string urlSuffix) - { - if (next == null) - { - throw new ArgumentNullException("next"); - } - - if (urlSuffix == null) - { - throw new ArgumentNullException("urlSuffix"); - } - - this.urlSuffix = urlSuffix; - this.next = next; - } - - /// - /// Invoke. - /// - /// Context. - /// Task for the execution by next middleware in pipeline. - public async Task Invoke(HttpContext context) - { - // TODO: According to public documentation - // 1. SF HttpSysCommunicationListener does not support port sharing - // "Multiple HTTP.sys instances can share a port by using the underlying HTTP.sys port sharing feature. - // But it's not supported by HttpSysCommunicationListener due to the complications it introduces for client requests." - // 2. Since the unique url with partitionid + replicaid + random guid is given as prefix to http.sys host, the request lands on this replica only if the unique base path match. - // This middleware is probably no longer needed. - await this.next(context); - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Middleware/ServiceFabricSetupFilter.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Middleware/ServiceFabricSetupFilter.cs deleted file mode 100644 index afd0c41d..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Middleware/ServiceFabricSetupFilter.cs +++ /dev/null @@ -1,35 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using Microsoft.AspNetCore.Builder; - using Microsoft.AspNetCore.Hosting; - - internal class ServiceFabricSetupFilter : IStartupFilter - { - private readonly string urlSuffix; - private readonly ServiceFabricIntegrationOptions options; - - internal ServiceFabricSetupFilter(string urlSuffix, ServiceFabricIntegrationOptions options) - { - this.urlSuffix = urlSuffix; - this.options = options; - } - - public Action Configure(Action next) - { - return app => - { - if (!string.IsNullOrEmpty(this.urlSuffix)) - { - app.UseServiceFabricMiddleware(this.urlSuffix); - } - - next(app); - }; - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationConstants.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationConstants.cs deleted file mode 100644 index ab15d917..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationConstants.cs +++ /dev/null @@ -1,81 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - - internal static class MigrationConstants - { - internal static readonly TimeSpan MaxBackoffForTransientErrors = TimeSpan.FromSeconds(1); - internal static readonly int MaxRetryCountForTransientErrors = 4; - internal static readonly TimeSpan DefaultOperationTimeout = TimeSpan.FromMinutes(5); - - internal static readonly TimeSpan DefaultRCTimeout = TimeSpan.FromMinutes(5); - internal static readonly int DefaultRetryCount = 4; - internal static readonly TimeSpan ConstantBackoffInterval = TimeSpan.FromSeconds(1); - internal static readonly char DefaultDelimiter = ','; - internal static readonly string KVSMigrationControllerName = "KvsMigration"; - internal static readonly string MetadataDictionaryName = "store://kvsrcmigration//metadata"; - internal static readonly string AbortMigrationEndpoint = "AbortMigration"; - internal static readonly string StartDowntimeEndpoint = "StartDowntime"; - internal static readonly string GetStartSNEndpoint = "GetFirstSequenceNumber"; - internal static readonly string GetEndSNEndpoint = "GetLastSequenceNumber"; - internal static readonly string EnumeratebySNEndpoint = "EnumerateBySequenceNumber"; - internal static readonly string GetDisableTCSEndpoint = "IsTombstoneCleanupDisabled"; - - internal static readonly string RejectWritesKey = "_RejectWrites_"; - internal static readonly string IsDowntimeInvoked = "_IsDowntimeInvoked_"; - - #region Actor Key constants - internal static readonly string ActorPresenceKeyPrefix = "@@"; - internal static readonly string ActorStorageKeyPrefix = "Actor"; - internal static readonly string ReminderStorageKeyPrefix = "Reminder"; - internal static readonly string ReminderCompletedeStorageKeyPrefix = "RC@@"; - internal static readonly string LogicalTimestampKey = "Timestamp_VLTM"; - #endregion - - #region Global Migration constants - internal static readonly string MigrationStartDateTimeUTC = "_MigrationStartDateTimeUTC_"; - internal static readonly string MigrationEndDateTimeUTC = "_MigrationEndDateTimeUTC_"; - internal static readonly string MigrationCurrentStatus = "_MigrationCurrentStatus_"; - internal static readonly string MigrationNoOfKeysMigrated = "_MigrationNoOfKeysMigrated_"; - internal static readonly string MigrationKeysMigrated = "_MigrationKeysMigrated_{0}_"; - internal static readonly string MigrationKeysMigratedChunksCount = "_MigrationKeysMigratedChunksCount_"; - internal static readonly string MigrationCurrentPhase = "_MigrationCurrentPhase_"; - internal static readonly string MigrationStartSeqNum = "_MigrationStartSeqNum_"; - internal static readonly string MigrationEndSeqNum = "_MigrationEndSeqNum_"; - internal static readonly string MigrationLastAppliedSeqNum = "_MigrationLastAppliedSeqNum_"; - internal static readonly string AbortMigrationInvokedOnSource = "_AbortMigrationInvokedOnSource_"; - #endregion Global Migration constants - - #region Phase constants - internal static readonly string PhaseStartDateTimeUTC = "_{0}Phase_Iteration-{1}_StartDateTimeUTC_"; - internal static readonly string PhaseEndDateTimeUTC = "_{0}Phase_Iteration-{1}_EndDateTimeUTC_"; - internal static readonly string PhaseCurrentStatus = "_{0}Phase_Iteration-{1}_CurrentStatus_"; - internal static readonly string PhaseStartSeqNum = "_{0}Phase_Iteration-{1}_StartSeqNum_"; - internal static readonly string PhaseEndSeqNum = "_{0}Phase_Iteration-{1}_EndSeqNum_"; - internal static readonly string PhaseLastAppliedSeqNum = "_{0}Phase_Iteration-{1}_LastAppliedSeqNum_"; - internal static readonly string PhaseNoOfKeysMigrated = "_{0}Phase_Iteration-{1}_NoOfKeysMigrated_"; - internal static readonly string PhaseWorkerCount = "_{0}Phase_Iteration-{1}_WorkerCount_"; - internal static readonly string PhaseIterationCount = "_{0}Phase_IterationCount_"; - #endregion Phase constants - - #region Worker constants - internal static readonly string PhaseWorkerStartDateTimeUTC = "_{0}Phase_Iteration-{1}_Worker{2}_StartDateTimeUTC_"; - internal static readonly string PhaseWorkerEndDateTimeUTC = "_{0}Phase_Iteration-{1}_Worker{2}_EndDateTimeUTC_"; - internal static readonly string PhaseWorkerCurrentStatus = "_{0}Phase_Iteration-{1}_Worker{2}_CurrentStatus_"; - internal static readonly string PhaseWorkerStartSeqNum = "_{0}Phase_Iteration-{1}_Worker{2}_StartSeqNum_"; - internal static readonly string PhaseWorkerEndSeqNum = "_{0}Phase_Iteration-{1}_Worker{2}_EndSeqNum_"; - internal static readonly string PhaseWorkerLastAppliedSeqNum = "_{0}Phase_Iteration-{1}_Worker{2}_LastAppliedSeqNum_"; - internal static readonly string PhaseWorkerNoOfKeysMigrated = "_{0}Phase_Iteration-{1}_Worker{2}_NoOfKeysMigrated_"; - #endregion Worker constants - - public static string Key(string format, params object[] args) - { - return string.Format(format, args); - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationDataValidationException.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationDataValidationException.cs deleted file mode 100644 index 1d58f2ef..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationDataValidationException.cs +++ /dev/null @@ -1,35 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Fabric; - using System.Runtime.Serialization; - - [Serializable] - internal sealed class MigrationDataValidationException : FabricException - { - public MigrationDataValidationException() - : base() - { - } - - public MigrationDataValidationException(string message) - : base(message) - { - } - - public MigrationDataValidationException(string message, Exception inner) - : base(message, inner) - { - } - - private MigrationDataValidationException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationOrchestratorBase.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationOrchestratorBase.cs deleted file mode 100644 index 07bc41ad..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationOrchestratorBase.cs +++ /dev/null @@ -1,197 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Fabric; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.AspNetCore.Hosting; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.ServiceFabric.Actors.Generator; - using Microsoft.ServiceFabric.Actors.Migration; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Actors.Runtime.Migration; - using Microsoft.ServiceFabric.Services.Client; - using Microsoft.ServiceFabric.Services.Communication.Client; - using Microsoft.ServiceFabric.Services.Communication.Runtime; - using Microsoft.ServiceFabric.Services.Remoting.V2.Runtime; - - /// - /// Base class for migration orchestration. - /// - internal abstract class MigrationOrchestratorBase : IMigrationOrchestrator - { - private static readonly string TraceType = typeof(MigrationOrchestratorBase).Name; - - private StatefulServiceContext serviceContext; - private ActorTypeInformation actorTypeInformation; - private string traceId; - private MigrationSettings migrationSettings; - private Func completionCallback; - - /// - /// Initializes a new instance of the class. - /// - /// The type information of the Actor. - /// Service context the actor service is operating under. - /// Migration settings. - /// Trace Id. - public MigrationOrchestratorBase(StatefulServiceContext serviceContext, ActorTypeInformation actorTypeInformation, Actors.Runtime.Migration.MigrationSettings migrationSettings, string traceId = null) - { - this.actorTypeInformation = actorTypeInformation; - this.serviceContext = serviceContext; - this.traceId = string.IsNullOrEmpty(traceId) ? this.serviceContext.TraceId : traceId; - if (migrationSettings != null && migrationSettings is MigrationSettings) - { - this.migrationSettings = (MigrationSettings)migrationSettings; - } - else - { - this.migrationSettings = new MigrationSettings(); - this.migrationSettings.LoadFrom( - this.StatefulServiceContext.CodePackageActivationContext, - ActorNameFormat.GetMigrationConfigSectionName(this.actorTypeInformation.ImplementationType)); - } - } - - internal ActorTypeInformation ActorTypeInformation { get => this.actorTypeInformation; } - - internal StatefulServiceContext StatefulServiceContext { get => this.serviceContext; } - - internal string TraceId { get => this.traceId; } - - internal MigrationSettings MigrationSettings { get => this.migrationSettings; } - - internal Func CompletionCallback { get => this.completionCallback; } - - /// - public abstract bool AreActorCallsAllowed(); - - /// - public abstract IActorStateProvider GetMigrationActorStateProvider(); - - /// - public ICommunicationListener GetMigrationCommunicationListener() - { - var endpointName = this.GetMigrationEndpointName(); - - return new HttpSysCommunicationListener(this.serviceContext, endpointName, (url, listener) => - { - try - { - var endpoint = this.serviceContext.CodePackageActivationContext.GetEndpoint(endpointName); - - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"Starting Kestrel on url: {url} host: {FabricRuntime.GetNodeContext().IPAddressOrFQDN} endpointPort: {endpoint.Port}"); - - var webHostBuilder = - new WebHostBuilder() - .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl) - .UseHttpSys(options => - { - options.UrlPrefixes.Add(listener.GetListenerUrl()); - }) - .ConfigureServices( - services => services - .AddSingleton(this)) - .UseStartup() - .Build(); - - return webHostBuilder; - } - catch (Exception ex) - { - ActorTrace.Source.WriteErrorWithId( - TraceType, - this.TraceId, - "Error encountered while creating WebHostBuilder: " + ex); - - throw; - } - }); - } - - /// - public IServiceRemotingMessageHandler GetMessageHandler(ActorService actorService, IServiceRemotingMessageHandler messageHandler, Func requestForwarderFactory) - { - var forwardServiceUri = this.GetForwardServiceUri(); - if (forwardServiceUri == null) - { - // Service is not configured to forward requests. - return messageHandler; - } - - var partitionInformation = this.GetInt64RangePartitionInformation(); - var lowKey = partitionInformation.LowKey; - - return new RequestForwardableRemotingDispatcher( - actorService, - messageHandler, - requestForwarderFactory.Invoke(new RequestForwarderContext - { - ServiceUri = forwardServiceUri, - ServicePartitionKey = new ServicePartitionKey(lowKey), - ReplicaSelector = TargetReplicaSelector.PrimaryReplica, - TraceId = this.StatefulServiceContext.TraceId, - })); - } - - /// - /// Gets the migration start mode. - /// - /// Return true if the MigrationMode is Auto, false otherwise. - public virtual bool IsAutoStartMigration() - { - return this.MigrationSettings.MigrationMode == MigrationMode.Auto; - } - - public void RegisterCompletionCallback(Func completionCallback) - { - this.completionCallback = completionCallback; - } - - /// - public abstract Task StartDowntimeAsync(bool userTriggered, CancellationToken cancellationToken); - - /// - public abstract Task StartMigrationAsync(bool userTriggered, CancellationToken cancellationToken); - - /// - public abstract Task AbortMigrationAsync(bool userTriggered, CancellationToken cancellationToken); - - public abstract bool IsActorCallToBeForwarded(); - - public abstract void ThrowIfActorCallsDisallowed(); - - protected Task InvokeCompletionCallback(bool actorCallsAllowed, CancellationToken cancellationToken) - { - if (this.completionCallback != null) - { - return this.completionCallback.Invoke(actorCallsAllowed, cancellationToken); - } - - ActorTrace.Source.WriteWarningWithId( - TraceType, - this.TraceId, - "Completion callback not registered. Ignoriing callback invocation."); - - return Task.CompletedTask; - } - - /// - /// Gets the migration endpoint name. - /// - /// Migration endpoint name. - protected abstract string GetMigrationEndpointName(); - - protected abstract Int64RangePartitionInformation GetInt64RangePartitionInformation(); - - protected abstract Uri GetForwardServiceUri(); - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationPhaseWorkloadBase.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationPhaseWorkloadBase.cs deleted file mode 100644 index ab054c9c..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationPhaseWorkloadBase.cs +++ /dev/null @@ -1,543 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Collections.Generic; - using System.Fabric; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration.Extensions; - using Microsoft.ServiceFabric.Actors.Migration; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Actors.Runtime.Migration; - using Microsoft.ServiceFabric.Data.Collections; - using Microsoft.ServiceFabric.Services.Communication.Client; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.MigrationConstants; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.MigrationUtility; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.PhaseInput; - using static Microsoft.ServiceFabric.Actors.Migration.PhaseResult; - - internal abstract class MigrationPhaseWorkloadBase : IMigrationPhaseWorkload - { - private static readonly string TraceType = typeof(MigrationPhaseWorkloadBase).Name; - private MigrationPhase migrationPhase; - private IReliableDictionary2 metadataDict; - private ServicePartitionClient servicePartitionClient; - private StatefulServiceContext statefulServiceContext; - private MigrationSettings migrationSettings; - private KVStoRCMigrationActorStateProvider stateProvider; - private string traceId; - private ActorTypeInformation actorTypeInformation; - private int currentIteration; - private int workerCount; - private ActorStateProviderHelper stateProviderHelper; - - public MigrationPhaseWorkloadBase( - MigrationPhase migrationPhase, - int currentIteration, - int workerCount, - KVStoRCMigrationActorStateProvider stateProvider, - ServicePartitionClient servicePartitionClient, - StatefulServiceContext statefulServiceContext, - MigrationSettings migrationSettings, - ActorTypeInformation actorTypeInfo, - string traceId) - { - this.migrationPhase = migrationPhase; - this.servicePartitionClient = servicePartitionClient; - this.migrationSettings = migrationSettings; - this.statefulServiceContext = statefulServiceContext; - this.stateProvider = stateProvider; - this.actorTypeInformation = actorTypeInfo; - this.currentIteration = currentIteration; - this.workerCount = workerCount; - this.traceId = traceId; - this.metadataDict = this.stateProvider.GetMetadataDictionaryAsync().ConfigureAwait(false).GetAwaiter().GetResult(); - this.stateProviderHelper = this.stateProvider.GetInternalStateProvider().GetActorStateProviderHelper(); - } - - public IReliableDictionary2 MetaDataDictionary { get => this.metadataDict; } - - public ServicePartitionClient ServicePartitionClient { get => this.servicePartitionClient; } - - public StatefulServiceContext StatefulServiceContext { get => this.statefulServiceContext; } - - public MigrationSettings MigrationSettings { get => this.migrationSettings; } - - public KVStoRCMigrationActorStateProvider StateProvider { get => this.stateProvider; } - - public ActorTypeInformation ActorTypeInformation { get => this.actorTypeInformation; } - - public string TraceId { get => this.traceId; } - - public Data.ITransaction Transaction { get => this.stateProvider.GetStateManager().CreateTransaction(); } - - public MigrationPhase Phase { get => this.migrationPhase; } - - public static async Task GetResultAsync( - ActorStateProviderHelper stateProviderHelper, - Func txFactory, - IReliableDictionary2 metadataDict, - MigrationPhase migrationPhase, - int currentIteration, - string traceId, - CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - var status = await ParseMigrationStateAsync( - () => GetValueOrDefaultAsync(stateProviderHelper, txFactory, metadataDict, Key(PhaseCurrentStatus, migrationPhase, currentIteration), cancellationToken), - traceId); - - if (status == MigrationState.None) - { - return new PhaseResult - { - Phase = migrationPhase, - Iteration = currentIteration, - Status = MigrationState.None, - }; - } - - var result = new PhaseResult(); - result.Phase = migrationPhase; - result.Iteration = currentIteration; - result.Status = status; - - result.StartDateTimeUTC = (await ParseDateTimeAsync( - () => GetValueAsync(stateProviderHelper, txFactory, metadataDict, Key(PhaseStartDateTimeUTC, migrationPhase, currentIteration), cancellationToken), - traceId)).Value; - - result.EndDateTimeUTC = await ParseDateTimeAsync( - () => GetValueOrDefaultAsync(stateProviderHelper, txFactory, metadataDict, Key(PhaseEndDateTimeUTC, migrationPhase, currentIteration), cancellationToken), - traceId); - - result.StartSeqNum = (await ParseLongAsync( - () => GetValueAsync(stateProviderHelper, txFactory, metadataDict, Key(PhaseStartSeqNum, migrationPhase, currentIteration), cancellationToken), - traceId)).Value; - - result.EndSeqNum = (await ParseLongAsync( - () => GetValueAsync(stateProviderHelper, txFactory, metadataDict, Key(PhaseEndSeqNum, migrationPhase, currentIteration), cancellationToken), - traceId)).Value; - - result.LastAppliedSeqNum = await ParseLongAsync( - () => GetValueOrDefaultAsync(stateProviderHelper, txFactory, metadataDict, Key(PhaseLastAppliedSeqNum, migrationPhase, currentIteration), cancellationToken), - traceId); - - result.NoOfKeysMigrated = await ParseLongAsync( - () => GetValueOrDefaultAsync(stateProviderHelper, txFactory, metadataDict, Key(PhaseNoOfKeysMigrated, migrationPhase, currentIteration), cancellationToken), - traceId); - - result.WorkerCount = await ParseIntAsync( - () => GetValueAsync(stateProviderHelper, txFactory, metadataDict, Key(PhaseWorkerCount, migrationPhase, currentIteration), cancellationToken), - traceId); - - var workerResults = new List(); - - for (int i = 1; i <= result.WorkerCount; i++) - { - cancellationToken.ThrowIfCancellationRequested(); - var workerResult = await MigrationWorker.GetResultAsync(stateProviderHelper, txFactory, metadataDict, migrationPhase, currentIteration, i, traceId, cancellationToken); - if (workerResult.Status != MigrationState.None) - { - workerResults.Add(workerResult); - } - } - - result.WorkerResults = workerResults.ToArray(); - - return result; - } - - public async Task StartOrResumeMigrationAsync(CancellationToken cancellationToken) - { - PhaseInput input = null; - - try - { - input = await this.GetOrAddInputAsync(cancellationToken); - if (input.Status == MigrationState.Completed) - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.traceId, - $"Phase already completed \n Input: {input.ToString()}"); - - return await GetResultAsync( - this.stateProviderHelper, - () => this.Transaction, - this.MetaDataDictionary, - this.migrationPhase, - this.currentIteration, - this.TraceId, - cancellationToken); - } - - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.traceId, - $"Starting or resuming {this.migrationPhase} - {this.currentIteration} Phase\n Input: {input.ToString()}"); - MigrationTelemetry.MigrationPhaseStartEvent(this.StatefulServiceContext, input.ToString()); - - var workers = this.CreateMigrationWorkers(input, cancellationToken); - var tasks = new List>(); - foreach (var worker in workers) - { - cancellationToken.ThrowIfCancellationRequested(); - if (worker.Input.Status != MigrationState.Completed) - { - tasks.Add(worker.StartWorkAsync(cancellationToken)); - } - } - - var results = await Task.WhenAll(tasks); - await this.AddOrUpdateResultAsync(input, results, cancellationToken); - PhaseResult phaseResult = await GetResultAsync( - this.stateProviderHelper, - () => this.Transaction, - this.MetaDataDictionary, - this.migrationPhase, - this.currentIteration, - this.TraceId, - cancellationToken); - - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.traceId, - $"Completed Migration phase\n Result: {phaseResult.ToString()}"); - MigrationTelemetry.MigrationPhaseEndEvent(this.StatefulServiceContext, phaseResult.ToString()); - - return phaseResult; - } - catch (Exception ex) - { - var inputString = input == null ? null : input.ToString(); - ActorTrace.Source.WriteErrorWithId( - TraceType, - this.traceId, - $"Migration phase failed with error: {ex} \n Input: {inputString}"); - - throw ex; - } - } - - protected virtual async Task GetEndSequenceNumberAsync(CancellationToken cancellationToken) - { - var response = await this.servicePartitionClient.InvokeWebRequestWithRetryAsync( - async client => - { - return await client.HttpClient.GetAsync($"{KVSMigrationControllerName}/{GetEndSNEndpoint}"); - }, - "GetEndSequenceNumberAsync", - cancellationToken); - return (await ParseLongAsync(async () => await response.Content.ReadAsStringAsync(), this.TraceId)).Value; - } - - protected virtual async Task GetStartSequenceNumberAsync(CancellationToken cancellationToken) - { - return (await ParseLongAsync( - () => GetValueAsync(this.stateProviderHelper, () => this.Transaction, this.MetaDataDictionary, MigrationLastAppliedSeqNum, cancellationToken), - this.TraceId)).Value; - } - - protected virtual async Task GetOrAddInputAsync(CancellationToken token) - { - token.ThrowIfCancellationRequested(); - - var input = new PhaseInput(); - await this.stateProviderHelper.ExecuteWithRetriesAsync( - async () => - { - using (var tx = this.Transaction) - { - input.Phase = this.migrationPhase; - - await this.MetaDataDictionary.AddOrUpdateAsync( - tx, - MigrationCurrentPhase, - this.migrationPhase.ToString(), - (_, __) => this.migrationPhase.ToString(), - DefaultRCTimeout, - token); - - input.StartDateTimeUTC = (await ParseDateTimeAsync( - () => this.MetaDataDictionary.GetOrAddAsync( - tx, - Key(PhaseStartDateTimeUTC, this.migrationPhase, this.currentIteration), - DateTime.UtcNow.ToString(), - DefaultRCTimeout, - token), - this.TraceId)).Value; - - input.EndDateTimeUTC = await ParseDateTimeAsync( - () => this.MetaDataDictionary.GetValueOrDefaultAsync( - tx, - Key(PhaseStartDateTimeUTC, this.migrationPhase, this.currentIteration), - DefaultRCTimeout, - token), - this.TraceId); - - input.Status = await ParseMigrationStateAsync( - () => this.MetaDataDictionary.GetOrAddAsync( - tx, - Key(PhaseCurrentStatus, this.migrationPhase, this.currentIteration), - MigrationState.InProgress.ToString(), - DefaultRCTimeout, - token), - this.TraceId); - - input.StartSeqNum = (await ParseLongAsync( - () => this.MetaDataDictionary.GetOrAddAsync( - tx, - Key(PhaseStartSeqNum, this.migrationPhase, this.currentIteration), - this.GetStartSequenceNumberAsync(token).ConfigureAwait(false).GetAwaiter().GetResult().ToString(), - DefaultRCTimeout, - token), - this.TraceId)).Value; - - // Update Migration seq num if it not present(first time) - await this.MetaDataDictionary.GetOrAddAsync( - tx, - MigrationStartSeqNum, - input.StartSeqNum.ToString(), - DefaultRCTimeout, - token); - - input.EndSeqNum = (await ParseLongAsync( - () => this.MetaDataDictionary.GetOrAddAsync( - tx, - Key(PhaseEndSeqNum, this.migrationPhase, this.currentIteration), - this.GetEndSequenceNumberAsync(token).ConfigureAwait(false).GetAwaiter().GetResult().ToString(), - DefaultRCTimeout, - token), - this.TraceId)).Value; - - input.LastAppliedSeqNum = await ParseLongAsync( - () => this.MetaDataDictionary.GetValueOrDefaultAsync( - tx, - Key(PhaseLastAppliedSeqNum, this.migrationPhase, this.currentIteration), - DefaultRCTimeout, - token), - this.TraceId); - - input.IterationCount = await ParseIntAsync( - () => this.MetaDataDictionary.AddOrUpdateAsync( - tx, - Key(PhaseIterationCount, this.migrationPhase), - this.currentIteration.ToString(), - (_, __) => this.currentIteration.ToString(), - DefaultRCTimeout, - token), - this.TraceId); - - input.WorkerCount = await ParseIntAsync( - () => this.MetaDataDictionary.GetOrAddAsync( - tx, - Key(PhaseWorkerCount, this.migrationPhase, this.currentIteration), - this.workerCount.ToString(), - DefaultRCTimeout, - token), - this.TraceId); - - long perWorker = (input.EndSeqNum - input.StartSeqNum) / this.workerCount; - var perWorkerStartSN = input.StartSeqNum; - var perWorkerEndSN = input.StartSeqNum + perWorker; - var workerInputs = new List(); - for (int i = 1; i <= this.workerCount; i++) - { - token.ThrowIfCancellationRequested(); - - var workerInput = new WorkerInput - { - WorkerId = i, - Phase = this.migrationPhase, - Iteration = this.currentIteration, - }; - - workerInput.StartDateTimeUTC = (await ParseDateTimeAsync( - () => this.MetaDataDictionary.GetOrAddAsync( - tx, - Key(PhaseWorkerStartDateTimeUTC, this.migrationPhase, this.currentIteration, i), - DateTime.UtcNow.ToString(), - DefaultRCTimeout, - token), - this.TraceId)).Value; - - workerInput.EndDateTimeUTC = await ParseDateTimeAsync( - () => this.MetaDataDictionary.GetValueOrDefaultAsync( - tx, - Key(PhaseWorkerEndDateTimeUTC, this.migrationPhase, this.currentIteration, i), - DefaultRCTimeout, - token), - this.TraceId); - - workerInput.Status = await ParseMigrationStateAsync( - () => this.MetaDataDictionary.GetOrAddAsync( - tx, - Key(PhaseWorkerCurrentStatus, this.migrationPhase, this.currentIteration, i), - MigrationState.InProgress.ToString(), - DefaultRCTimeout, - token), - this.TraceId); - - workerInput.StartSeqNum = (await ParseLongAsync( - () => this.MetaDataDictionary.GetOrAddAsync( - tx, - Key(PhaseWorkerStartSeqNum, this.migrationPhase, this.currentIteration, i), - perWorkerStartSN.ToString(), - DefaultRCTimeout, - token), - this.TraceId)).Value; - - workerInput.EndSeqNum = (await ParseLongAsync( - () => this.MetaDataDictionary.GetOrAddAsync( - tx, - Key(PhaseWorkerEndSeqNum, this.migrationPhase, this.currentIteration, i), - perWorkerEndSN.ToString(), - DefaultRCTimeout, - token), - this.TraceId)).Value; - - workerInput.LastAppliedSeqNum = await ParseLongAsync( - () => this.MetaDataDictionary.GetValueOrDefaultAsync( - tx, - Key(PhaseWorkerLastAppliedSeqNum, this.migrationPhase, this.currentIteration, i), - DefaultRCTimeout, - token), - this.TraceId); - - workerInputs.Add(workerInput); - - if (perWorkerEndSN == input.EndSeqNum) - { - break; - } - - perWorkerStartSN = perWorkerEndSN + 1; - perWorkerEndSN = (perWorkerStartSN + perWorker) < input.EndSeqNum ? (perWorkerStartSN + perWorker) : input.EndSeqNum; - } - - input.WorkerInputs = workerInputs.ToArray(); - - await tx.CommitAsync(); - } - }, - "MigrationPhaseWorkloadBase.GetOrAddInputAsync", - token); - - return input; - } - - protected virtual List CreateMigrationWorkers(PhaseInput input, CancellationToken cancellationToken) - { - var workers = new List(); - - foreach (var workerInput in input.WorkerInputs) - { - cancellationToken.ThrowIfCancellationRequested(); - - workers.Add(new MigrationWorker( - this.StateProvider, - this.ActorTypeInformation, - this.ServicePartitionClient, - this.MigrationSettings, - workerInput, - this.TraceId)); - } - - return workers; - } - - protected virtual async Task AddOrUpdateResultAsync(PhaseInput phaseInput, WorkerResult[] workerResults, CancellationToken token) - { - token.ThrowIfCancellationRequested(); - - long? keysMigratedByPhase = null; - DateTime? endTime = DateTime.UtcNow; - long keysMigratedByWorkers = 0L; - foreach (var workerResult in workerResults) - { - keysMigratedByWorkers += workerResult.NoOfKeysMigrated.HasValue ? workerResult.NoOfKeysMigrated.Value : 0L; - } - - await this.stateProviderHelper.ExecuteWithRetriesAsync( - async () => - { - using (var tx = this.Transaction) - { - endTime = await ParseDateTimeAsync( - () => this.MetaDataDictionary.AddOrUpdateAsync( - tx, - Key(PhaseEndDateTimeUTC, this.migrationPhase, this.currentIteration), - endTime.ToString(), - (_, __) => endTime.ToString(), - DefaultRCTimeout, - token), - this.TraceId); - - await this.MetaDataDictionary.AddOrUpdateAsync( - tx, - Key(PhaseLastAppliedSeqNum, this.migrationPhase, this.currentIteration), - phaseInput.EndSeqNum.ToString(), - (_, __) => phaseInput.EndSeqNum.ToString(), - DefaultRCTimeout, - token); - - keysMigratedByPhase = await ParseLongAsync( - () => this.MetaDataDictionary.AddOrUpdateAsync( - tx, - Key(PhaseNoOfKeysMigrated, this.migrationPhase, this.currentIteration), - keysMigratedByWorkers.ToString(), - (k, v) => - { - long currVal = ParseLong(v, this.TraceId); - long newVal = currVal + keysMigratedByWorkers; - - return newVal.ToString(); - }, - DefaultRCTimeout, - token), - this.TraceId); - - await this.MetaDataDictionary.AddOrUpdateAsync( - tx, - Key(PhaseCurrentStatus, this.migrationPhase, this.currentIteration), - MigrationState.Completed.ToString(), - (_, __) => MigrationState.Completed.ToString(), - DefaultRCTimeout, - token); - - await this.MetaDataDictionary.AddOrUpdateAsync( - tx, - MigrationLastAppliedSeqNum, - phaseInput.EndSeqNum.ToString(), - (_, __) => phaseInput.EndSeqNum.ToString(), - DefaultRCTimeout, - token); - - await this.MetaDataDictionary.AddOrUpdateAsync( - tx, - MigrationNoOfKeysMigrated, - keysMigratedByWorkers.ToString(), - (k, v) => - { - var currentVal = ParseLong(v, this.TraceId); - var newVal = currentVal + keysMigratedByPhase; - - return newVal.ToString(); - }, - DefaultRCTimeout, - token); - - await tx.CommitAsync(); - } - }, - "MigrationPhaseWorkloadBase.AddOrUpdateResultAsync", - token); - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationSettings.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationSettings.cs deleted file mode 100644 index 8befa908..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationSettings.cs +++ /dev/null @@ -1,110 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Fabric; - using System.IO; - using System.Runtime.Serialization; - using System.Runtime.Serialization.Json; - using System.Text; - using Microsoft.ServiceFabric.Actors.Generator; - - [DataContract] - [KnownType(typeof(Actors.Runtime.Migration.MigrationSettings))] - internal class MigrationSettings : Actors.Runtime.Migration.MigrationSettings - { - private static readonly string TraceType = typeof(MigrationSettings).ToString(); - - private static DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(MigrationSettings), new DataContractJsonSerializerSettings - { - UseSimpleDictionaryFormat = true, - }); - - [DataMember] - public int CopyPhaseParallelism { get; set; } - - [DataMember] - public long DowntimeThreshold { get; set; } - - [DataMember] - public int ChunksPerEnumeration { get; set; } = 1; - - [DataMember] - public long KeyValuePairsPerChunk { get; set; } - - [DataMember] - public bool EnableDataIntegrityChecks { get; set; } - - // A comma separated list of exception full name(including namespace) for which abort should not be called. - // A partition error will still be reported - [DataMember] - public string ExceptionExclusionListForAbort { get; set; } - - public override string ToString() - { - using (var stream = new MemoryStream()) - { - serializer.WriteObject(stream, this); - - var returnVal = Encoding.UTF8.GetString(stream.GetBuffer()); - - return returnVal; - } - } - - internal override void LoadFrom(ICodePackageActivationContext codePackageActivationContext, string configSectionName = "MigrationConfig") - { - base.LoadFrom(codePackageActivationContext, configSectionName); - - this.CopyPhaseParallelism = Environment.ProcessorCount; - this.DowntimeThreshold = 1024; - this.EnableDataIntegrityChecks = true; - var configPackageName = ActorNameFormat.GetConfigPackageName(); - try - { - var configPackageObj = codePackageActivationContext.GetConfigurationPackageObject(configPackageName); - if (configPackageObj.Settings.Sections.Contains(configSectionName)) - { - var migrationSettings = configPackageObj.Settings.Sections[configSectionName]; - if (migrationSettings.Parameters.Contains("CopyPhaseParallelism")) - { - this.CopyPhaseParallelism = int.Parse(migrationSettings.Parameters["CopyPhaseParallelism"].Value); - } - - if (migrationSettings.Parameters.Contains("DowntimeThreshold")) - { - this.DowntimeThreshold = int.Parse(migrationSettings.Parameters["DowntimeThreshold"].Value); - } - - if (migrationSettings.Parameters.Contains("ChunksPerEnumeration")) - { - this.ChunksPerEnumeration = int.Parse(migrationSettings.Parameters["ChunksPerEnumeration"].Value); - } - - if (migrationSettings.Parameters.Contains("KeyValuePairsPerChunk")) - { - this.KeyValuePairsPerChunk = long.Parse(migrationSettings.Parameters["KeyValuePairsPerChunk"].Value); - } - - if (migrationSettings.Parameters.Contains("EnableDataIntegrityChecks")) - { - this.EnableDataIntegrityChecks = bool.Parse(migrationSettings.Parameters["EnableDataIntegrityChecks"].Value); - } - } - } - catch (Exception e) - { - ActorTrace.Source.WriteError(TraceType, $"Failed to load Migration settings from config package : {e.Message}"); - throw e; // TODO: consider throwing SF Exception. - } - } - - internal override void Validate(bool isSource) - { - base.Validate(isSource); - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationUtility.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationUtility.cs deleted file mode 100644 index 2e078cd0..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationUtility.cs +++ /dev/null @@ -1,564 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using System.Runtime.Serialization; - using System.Threading; - using System.Threading.Tasks; - using System.Xml; - using Microsoft.ServiceFabric.Actors.Migration; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Data.Collections; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.MigrationConstants; - - internal static class MigrationUtility - { - private static readonly string TraceType = typeof(MigrationUtility).ToString(); - - public static bool ShouldRetryOperation( - string currentExceptionId, - int maxRetryCount, - ref string lastSeenExceptionId, - ref int currentRetryCount) - { - if (maxRetryCount == 0) - { - return false; - } - - if (currentExceptionId == lastSeenExceptionId) - { - if (currentRetryCount >= maxRetryCount) - { - // We have retried max number of times. - return false; - } - - ++currentRetryCount; - return true; - } - - // The current retriable exception is different from the exception that was last seen, - // reset the retry tracking variables - lastSeenExceptionId = currentExceptionId; - currentRetryCount = 1; - return true; - } - - public static async Task GetValueOrDefaultAsync(ActorStateProviderHelper stateProviderHelper, Func txFactory, IReliableDictionary2 metadataDict, string key, CancellationToken cancellationToken) - { - return await stateProviderHelper.ExecuteWithRetriesAsync( - async () => - { - using (var tx = txFactory.Invoke()) - { - var res = await metadataDict.TryGetValueAsync( - tx, - key, - DefaultRCTimeout, - cancellationToken); - return res.HasValue ? res.Value : null; - } - }, - $"MigrationPhaseWorkloadBase.TryGetValueAsync.{key}", - cancellationToken); - } - - public static async Task GetValueAsync(ActorStateProviderHelper stateProviderHelper, Func txFactory, IReliableDictionary2 metadataDict, string key, CancellationToken cancellationToken) - { - return await stateProviderHelper.ExecuteWithRetriesAsync( - async () => - { - using (var tx = txFactory.Invoke()) - { - var res = await metadataDict.TryGetValueAsync( - tx, - key, - DefaultRCTimeout, - cancellationToken); - if (res.HasValue) - { - return res.Value; - } - - throw new KeyNotFoundException(key); - } - }, - $"MigrationPhaseWorkloadBase.TryGetValueAsync.{key}", - cancellationToken); - } - - public static async Task ParseDateTimeAsync(Func> func, string traceId) - { - string valueString = await func(); - if (string.IsNullOrEmpty(valueString)) - { - return null; - } - - if (!DateTime.TryParse(valueString, out var value)) - { - TraceAndThrowException(valueString, traceId); - } - - return value; - } - - public static async Task ParseLongAsync(Func> func, string traceId) - { - string valueString = await func(); - if (string.IsNullOrEmpty(valueString)) - { - return null; - } - - if (!long.TryParse(valueString, out var value)) - { - TraceAndThrowException(valueString, traceId); - } - - return value; - } - - public static long ParseLong(string valueString, string traceId) - { - if (!long.TryParse(valueString, out var value)) - { - TraceAndThrowException(valueString, traceId); - } - - return value; - } - - public static async Task ParseIntAsync(Func> func, string traceId) - { - string valueString = await func(); - if (!int.TryParse(valueString, out var value)) - { - TraceAndThrowException(valueString, traceId); - } - - return value; - } - - public static async Task ParseIntAsync(Func> func, int defaultValue, string traceId) - { - string valueString = await func(); - if (string.IsNullOrEmpty(valueString)) - { - return defaultValue; - } - - if (!int.TryParse(valueString, out var value)) - { - TraceAndThrowException(valueString, traceId); - } - - return value; - } - - public static async Task ParseMigrationPhaseAsync(Func> func, string traceId) - { - string valueString = await func(); - if (string.IsNullOrEmpty(valueString)) - { - return MigrationPhase.None; - } - - if (!Enum.TryParse(valueString, out var value)) - { - TraceAndThrowException(valueString, traceId); - } - - return value; - } - - public static async Task ParseMigrationStateAsync(Func> func, string traceId) - { - string valueString = await func(); - if (string.IsNullOrEmpty(valueString)) - { - return MigrationState.None; - } - - if (!Enum.TryParse(valueString, out var value)) - { - TraceAndThrowException(valueString, traceId); - } - - return value; - } - - public static async Task ParseBoolAsync(Func> func, string traceId) - { - string valueString = await func(); - if (string.IsNullOrEmpty(valueString)) - { - return false; - } - - if (!bool.TryParse(valueString, out var value)) - { - TraceAndThrowException(valueString, traceId); - } - - return value; - } - - public static async Task ExecuteWithRetriesAsync(Func> asyncFunc, string traceId, string funcTag, int retryCount = 0, IEnumerable retryableExceptions = null) - { - try - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - traceId, - $"Invoking migration func - {funcTag}"); - return await ExecuteWithRetriesInternalAsync(asyncFunc, traceId, funcTag, retryCount); - } - finally - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - traceId, - $"Migration func - {funcTag} completed"); - } - } - - public static T ExecuteWithRetries(Func func, string traceId, string funcTag, int retryCount = 0, IEnumerable retryableExceptions = null) - { - try - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - traceId, - $"Invoking migration func - {funcTag}"); - return ExecuteWithRetriesInternal(func, traceId, funcTag, retryCount); - } - finally - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - traceId, - $"Migration func - {funcTag} completed"); - } - } - - public static async Task ExecuteWithRetriesAsync(Func asyncFunc, string traceId, string funcTag, int retryCount = 0, IEnumerable retryableExceptions = null) - { - await ExecuteWithRetriesAsync( - async () => - { - await asyncFunc.Invoke(); - return (object)null; - }, - traceId, - funcTag, - retryCount, - retryableExceptions); - } - - public static bool IgnoreKey(string key) - { - return key == MigrationConstants.RejectWritesKey - || key == MigrationConstants.LogicalTimestampKey; - } - - private static async Task ExecuteWithRetriesInternalAsync(Func> func, string traceId, string funcTag, int retriesLeft = 0, IEnumerable retryableExceptions = null) - { - Exception exToThrow = null; - try - { - return await func.Invoke(); - } - catch (Exception ex) - { - ActorTrace.Source.WriteErrorWithId( - TraceType, - traceId, - $"Migration func - {funcTag} failed with exception - {ex}, retries left - {retriesLeft}"); - - exToThrow = ex; - } - - if (exToThrow != null) - { - var exMatch = retryableExceptions != null ? retryableExceptions.FirstOrDefault(type => type.IsAssignableFrom(exToThrow.GetType())) : default(Type); - if (exMatch == default(Type) || retriesLeft <= 0) - { - throw exToThrow; - } - } - - await Task.Delay(MigrationConstants.ConstantBackoffInterval); - - return await ExecuteWithRetriesInternalAsync(func, traceId, funcTag, retriesLeft - 1); - } - - private static T ExecuteWithRetriesInternal(Func func, string traceId, string funcTag, int retriesLeft = 0, IEnumerable retryableExceptions = null) - { - Exception exToThrow = null; - try - { - return func.Invoke(); - } - catch (Exception ex) - { - ActorTrace.Source.WriteErrorWithId( - TraceType, - traceId, - $"Migration func - {funcTag} failed with exception - {ex}, retries left - {retriesLeft}"); - - exToThrow = ex; - } - - if (exToThrow != null) - { - var exMatch = retryableExceptions != null ? retryableExceptions.FirstOrDefault(type => type.IsAssignableFrom(exToThrow.GetType())) : default(Type); - if (exMatch == default(Type) || retriesLeft <= 0) - { - throw exToThrow; - } - } - - return ExecuteWithRetriesInternal(func, traceId, funcTag, retriesLeft - 1); - } - - private static void TraceAndThrowException(TData data, string traceId) - { - ActorTrace.Source.WriteErrorWithId( - TraceType, - traceId, - $"Failed to parse {data}"); - - throw new Exception($"Failed to parse {data}"); // TODO: SFException. - } - - internal static class RC - { - private static readonly string TraceType = "MigrationUtility.RC"; - - internal static byte[] SerializeReminderCompletedData(string key, ReminderCompletedData data, string traceId) - { - try - { - var res = ReminderCompletedDataSerializer.Serialize(data); - ActorTrace.Source.WriteNoiseWithId( - TraceType, - traceId, - $"Successfully serialized Reminder Completed Data - Key : {key}"); - - return res; - } - catch (Exception ex) - { - ActorTrace.Source.WriteErrorWithId( - TraceType, - traceId, - $"Failed to serialize Reminder Completed Data - Key : {key}, ErrorMessage : {ex.Message}"); - - throw ex; - } - } - - internal static ReminderCompletedData DeserializeReminderCompletedData(string key, byte[] data, string traceId) - { - try - { - var res = ReminderCompletedDataSerializer.Deserialize(data); - ActorTrace.Source.WriteNoiseWithId( - TraceType, - traceId, - $"Successfully deserialized Reminder Completed Data - Key : {key}"); - - return res; - } - catch (Exception ex) - { - ActorTrace.Source.WriteErrorWithId( - TraceType, - traceId, - $"Failed to deserialize Reminder Completed Data - Key : {key}, ErrorMessage : {ex.Message}"); - - throw ex; - } - } - - internal static byte[] SerializeReminder(string key, ActorReminderData data, string traceId) - { - try - { - var res = ActorReminderDataSerializer.Serialize(data); - ActorTrace.Source.WriteNoiseWithId( - TraceType, - traceId, - $"Successfully serialized Reminder - Key : {key}"); - - return res; - } - catch (Exception ex) - { - ActorTrace.Source.WriteErrorWithId( - TraceType, - traceId, - $"Failed to serialize Reminder - Key : {key}, ErrorMessage : {ex.Message}"); - - throw ex; - } - } - - internal static ActorReminderData DeserializeReminder(string key, byte[] data, string traceId) - { - try - { - var res = ActorReminderDataSerializer.Deserialize(data); - ActorTrace.Source.WriteNoiseWithId( - TraceType, - traceId, - $"Successfully deserialized Reminder - Key : {key}"); - - return res; - } - catch (Exception ex) - { - ActorTrace.Source.WriteErrorWithId( - TraceType, - traceId, - $"Failed to deserialize Reminder - Key : {key}, ErrorMessage : {ex.Message}"); - - throw ex; - } - } - } - - internal static class KVS - { - private static readonly string TraceType = "MigrationUtility.KVS"; - - private static DataContractSerializer reminderSerializer = new DataContractSerializer(typeof(ActorReminderData)); - private static DataContractSerializer reminderCompletedDataSerializer = new DataContractSerializer(typeof(ReminderCompletedData)); - - internal static byte[] SerializeReminder(string key, ActorReminderData reminder, string traceId) - { - try - { - var res = Serialize(reminderSerializer, reminder); - ActorTrace.Source.WriteNoiseWithId( - TraceType, - traceId, - $"Successfully serialized Reminder - Key : {key}"); - - return res; - } - catch (Exception ex) - { - ActorTrace.Source.WriteErrorWithId( - TraceType, - traceId, - $"Failed to deserialize Reminder - Key : {key}, ActorId : {reminder.ActorId}, DueTime : {reminder.DueTime}, IsReadOnly : {reminder.IsReadOnly}, LogicalCreationTime : {reminder.LogicalCreationTime}, Name : {reminder.Name}, Period : {reminder.Period}, ErrorMessage : {ex.Message}"); - - throw ex; - } - } - - internal static byte[] SerializeReminderCompletedData(string key, ReminderCompletedData reminderCompletedData, string traceId) - { - try - { - var res = Serialize(reminderCompletedDataSerializer, reminderCompletedData); - ActorTrace.Source.WriteNoiseWithId( - TraceType, - traceId, - $"Successfully serialized Reminder Completed data - Key : {key}"); - - return res; - } - catch (Exception ex) - { - ActorTrace.Source.WriteErrorWithId( - TraceType, - traceId, - $"Failed to deserialize Reminder Completed data - Key : {key}, {reminderCompletedData}, ErrorMessage : {ex.Message}"); - - throw ex; - } - } - - internal static ActorReminderData DeserializeReminder(string key, byte[] reminder, string traceId) - { - try - { - var res = Deserialize(reminderSerializer, reminder) as ActorReminderData; - ActorTrace.Source.WriteNoiseWithId( - TraceType, - traceId, - $"Successfully deserialized Reminder - Key : {key}"); - - return res; - } - catch (Exception ex) - { - ActorTrace.Source.WriteErrorWithId( - TraceType, - traceId, - $"Failed to deserialize Reminder ErrorMessage : {ex.Message}"); - - throw ex; - } - } - - internal static ReminderCompletedData DeserializeReminderCompletedData(string key, byte[] reminder, string traceId) - { - try - { - var res = Deserialize(reminderCompletedDataSerializer, reminder) as ReminderCompletedData; - ActorTrace.Source.WriteNoiseWithId( - TraceType, - traceId, - $"Successfully deserialized Reminder Completed data - Key : {key}"); - - return res; - } - catch (Exception ex) - { - ActorTrace.Source.WriteErrorWithId( - TraceType, - traceId, - $"Failed to deserialize Reminder Completed Data - {key}, ErrorMessage : {ex.Message}"); - - throw ex; - } - } - - private static byte[] Serialize(DataContractSerializer serializer, T data) - { - using (var memoryStream = new MemoryStream()) - { - var binaryWriter = XmlDictionaryWriter.CreateBinaryWriter(memoryStream); - serializer.WriteObject(binaryWriter, data); - binaryWriter.Flush(); - - return memoryStream.ToArray(); - } - } - - private static object Deserialize(DataContractSerializer serializer, byte[] data) - { - using (var memoryStream = new MemoryStream(data)) - { - var binaryReader = XmlDictionaryReader.CreateBinaryReader( - memoryStream, - XmlDictionaryReaderQuotas.Max); - - return serializer.ReadObject(binaryReader); - } - } - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationWorker.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationWorker.cs deleted file mode 100644 index 92b1ff91..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/MigrationWorker.cs +++ /dev/null @@ -1,310 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Net.Http; - using System.Net.Http.Headers; - using System.Runtime.Serialization.Json; - using System.Text; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration.Extensions; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration.Models; - using Microsoft.ServiceFabric.Actors.Migration; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Services.Communication.Client; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.MigrationConstants; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.MigrationUtility; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.PhaseInput; - using static Microsoft.ServiceFabric.Actors.Migration.PhaseResult; - - internal class MigrationWorker : WorkerBase - { - private static readonly string TraceType = typeof(MigrationWorker).Name; - private static readonly DataContractJsonSerializer ResponseSerializer = new DataContractJsonSerializer(typeof(EnumerationResponse), new[] { typeof(List) }); - private static readonly DataContractJsonSerializer Requestserializer = new DataContractJsonSerializer(typeof(EnumerationRequest)); - private ServicePartitionClient servicePartitionClient; - private MigrationSettings migrationSettings; - private ActorStateProviderHelper stateProviderHelper; - - public MigrationWorker( - KVStoRCMigrationActorStateProvider stateProvider, - ActorTypeInformation actorTypeInfo, - ServicePartitionClient servicePartitionClient, - MigrationSettings migrationSettings, - WorkerInput workerInput, - string traceId) - : base(stateProvider, workerInput, traceId) - { - this.servicePartitionClient = servicePartitionClient; - this.migrationSettings = migrationSettings; - this.stateProviderHelper = this.StateProvider.GetInternalStateProvider().GetActorStateProviderHelper(); - } - - public override async Task StartWorkAsync(CancellationToken cancellationToken) - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"Starting or resuming migration worker\n Input: {this.Input.ToString()}"); - - try - { - var startSN = this.Input.StartSeqNum; - if (this.Input.LastAppliedSeqNum.HasValue) - { - startSN = this.Input.LastAppliedSeqNum.Value + 1; - if (startSN > this.Input.EndSeqNum) - { - await this.stateProviderHelper.ExecuteWithRetriesAsync( - async () => - { - using (var tx = this.StateProvider.GetStateManager().CreateTransaction()) - { - await this.CompleteWorkerAsync(tx, cancellationToken); - await tx.CommitAsync(); - } - }, - "MigrationWorker.StartWorkAsync", - cancellationToken); - - return await GetResultAsync( - this.stateProviderHelper, - () => this.StateProvider.GetStateManager().CreateTransaction(), - this.MetadataDict, - this.Input.Phase, - this.Input.Iteration, - this.Input.WorkerId, - this.TraceId, - cancellationToken); - } - } - - long keysMigrated = 0L; - while (startSN <= this.Input.EndSeqNum) - { - cancellationToken.ThrowIfCancellationRequested(); - var fetchAndSaveResponse = await this.FetchAndSaveAsync(startSN, cancellationToken); - startSN = fetchAndSaveResponse.LastAppliedSequenceNumber + 1; - keysMigrated += fetchAndSaveResponse.NumberOfKeysApplied; - } - - var result = await GetResultAsync( - this.stateProviderHelper, - () => this.StateProvider.GetStateManager().CreateTransaction(), - this.MetadataDict, - this.Input.Phase, - this.Input.Iteration, - this.Input.WorkerId, - this.TraceId, - cancellationToken); - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"Completed migration worker\n Result: {result.ToString()} "); - - return result; - } - catch (Exception ex) - { - ActorTrace.Source.WriteErrorWithId( - TraceType, - this.TraceId, - $"Migration worker failed with error: {ex} \n Input: /*Dump input*/"); - - throw ex; - } - } - - private async Task FetchAndSaveAsync(long startSN, CancellationToken cancellationToken) - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"Enumerating from KVS - StartSN: {startSN}"); - - long keysMigrated = 0L; - long laSN = -1; - EnumerationResponse enumerationResponse = null; - - try - { - cancellationToken.ThrowIfCancellationRequested(); - var response = await this.servicePartitionClient.InvokeWebRequestWithRetryAsync( - async client => - { - var response = await client.HttpClient.SendAsync( - this.CreateKvsApiRequestMessage(client.EndpointUri, startSN), - HttpCompletionOption.ResponseHeadersRead, - cancellationToken); - - return response; - }, - "FetchAndSaveAsync", - cancellationToken); - - using (var stream = await response.Content.ReadAsStreamAsync()) - { - using (var streamReader = new StreamReader(stream)) - { - string responseLine = await streamReader.ReadLineAsync(); - cancellationToken.ThrowIfCancellationRequested(); - while (responseLine != null) - { - cancellationToken.ThrowIfCancellationRequested(); - enumerationResponse = SerializationUtility.Deserialize(ResponseSerializer, Encoding.UTF8.GetBytes(responseLine)); - var kvsData = enumerationResponse.KeyValuePairs; - if (kvsData.Count > 0) - { - laSN = kvsData[kvsData.Count - 1].Version; - var keysMigratedInChunk = await this.StateProvider.SaveStateAsync(kvsData, cancellationToken, this.Input.Phase == MigrationPhase.Copy); - keysMigrated += keysMigratedInChunk; - await this.PostHydrationValidationAsync(enumerationResponse, cancellationToken); - await this.stateProviderHelper.ExecuteWithRetriesAsync( - async () => - { - using (var tx = this.StateProvider.GetStateManager().CreateTransaction()) - { - await this.MetadataDict.AddOrUpdateAsync( - tx, - Key(PhaseWorkerNoOfKeysMigrated, this.Input.Phase, this.Input.Iteration, this.Input.WorkerId), - keysMigrated.ToString(), - (k, v) => - { - long currVal = ParseLong(v, this.TraceId); - return (currVal + keysMigratedInChunk).ToString(); - }, - DefaultRCTimeout, - cancellationToken); - - await this.MetadataDict.AddOrUpdateAsync( - tx, - Key(PhaseWorkerLastAppliedSeqNum, this.Input.Phase, this.Input.Iteration, this.Input.WorkerId), - laSN.ToString(), - (_, __) => laSN.ToString(), - DefaultRCTimeout, - cancellationToken); - - if (laSN == this.Input.EndSeqNum) - { - await this.CompleteWorkerAsync(tx, cancellationToken); - } - - await tx.CommitAsync(); - } - }, - "MigrationWorker.FetchAndSaveAsync", - cancellationToken); - - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"KeysFetched in chunk : {kvsData.Count}, KeysMigrated in chunk: {keysMigrated}"); - } - - responseLine = streamReader.ReadLine(); - } - } - } - - if (enumerationResponse != null && enumerationResponse.EndSequenceNumberReached) - { - await this.stateProviderHelper.ExecuteWithRetriesAsync( - async () => - { - using (var tx = this.StateProvider.GetStateManager().CreateTransaction()) - { - await this.MetadataDict.AddOrUpdateAsync( - tx, - Key(PhaseWorkerLastAppliedSeqNum, this.Input.Phase, this.Input.Iteration, this.Input.WorkerId), - this.Input.EndSeqNum.ToString(), - (_, __) => this.Input.EndSeqNum.ToString(), - DefaultRCTimeout, - cancellationToken); - - await this.CompleteWorkerAsync(tx, cancellationToken); - await tx.CommitAsync(); - } - }, - "MigrationWorker.FetchAndSaveAsync", - cancellationToken); - } - - return new FetchAndSaveResponse - { - LastAppliedSequenceNumber = enumerationResponse == null || enumerationResponse.EndSequenceNumberReached ? this.Input.EndSeqNum : laSN, - NumberOfKeysApplied = keysMigrated, - }; - } - catch (Exception ex) - { - ActorTrace.Source.WriteErrorWithId( - TraceType, - this.TraceId, - "Error occured while enumerating and saving data - StartSN: {0}, Exception: {1}", - startSN, - ex); - throw ex; - } - } - - private EnumerationRequest CreateEnumerationRequestObject(long startSN) - { - var req = new EnumerationRequest - { - StartSequenceNumber = startSN, - EndSequenceNumber = this.Input.EndSeqNum, - ChunkSize = this.migrationSettings.KeyValuePairsPerChunk, - NumberOfChunksPerEnumeration = this.migrationSettings.ChunksPerEnumeration, - IncludeDeletes = this.Input.Phase != MigrationPhase.Copy, - ResolveActorIdsForStateKVPairs = this.Input.Phase == MigrationPhase.Copy, - ComputeHash = this.migrationSettings.EnableDataIntegrityChecks, - }; - - return req; - } - - private HttpRequestMessage CreateKvsApiRequestMessage(Uri baseUri, long startSN) - { - var enumerationRequestContent = this.CreateEnumerationRequestObject(startSN); - - var requestBuffer = new ByteArrayContent(SerializationUtility.Serialize(Requestserializer, enumerationRequestContent)); - requestBuffer.Headers.ContentType = new MediaTypeHeaderValue("application/json") - { - CharSet = Encoding.UTF8.WebName, - }; - - return new HttpRequestMessage - { - Method = HttpMethod.Get, - RequestUri = new Uri(baseUri, $"{MigrationConstants.KVSMigrationControllerName}/{MigrationConstants.EnumeratebySNEndpoint}"), - Content = requestBuffer, - }; - } - - private async Task PostHydrationValidationAsync(EnumerationResponse enumerationResponse, CancellationToken cancellationToken) - { - if (this.migrationSettings.EnableDataIntegrityChecks) - { - await this.StateProvider.ValidateDataPostMigrationAsync( - enumerationResponse.KeyValuePairs, - enumerationResponse.ValueHash, - this.Input.Phase == MigrationPhase.Copy, - cancellationToken); - } - } - - internal class FetchAndSaveResponse - { - public long LastAppliedSequenceNumber { get; set; } - - public long NumberOfKeysApplied { get; set; } - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Models/EnumerationRequest.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Models/EnumerationRequest.cs deleted file mode 100644 index 11f69a44..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Models/EnumerationRequest.cs +++ /dev/null @@ -1,66 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration.Models -{ - using System.ComponentModel.DataAnnotations; - using System.Runtime.Serialization; - - /// - /// EnumerationRequest - /// - [DataContract] - public class EnumerationRequest - { - /// - /// Gets or Sets start sequence number per enumeration. - /// - [DataMember] - [Required] - public long StartSequenceNumber { get; set; } - - /// - /// Gets or Sets end sequence number per enumeration. - /// - [DataMember] - [Required] - public long EndSequenceNumber { get; set; } - - /// - /// Gets or Sets ChunkSize - /// - [DataMember] - [Required] - public long ChunkSize { get; set; } - - /// - /// Gets or Sets number of chunks per enumeration. - /// - [DataMember] - [Required] - public int NumberOfChunksPerEnumeration { get; set; } - - /// - /// Gets or sets a value indicating whether to include tombstones in the response. - /// - [DataMember] - [Required] - public bool IncludeDeletes { get; set; } - - /// - /// Gets or sets a value indicating whether data intergrity checks are enabled. - /// - [DataMember] - [Required] - public bool ComputeHash { get; set; } - - /// - /// Gets or sets a value indicating whether to include actorids for actor state KV pairs. - /// - [DataMember] - [Required] - public bool ResolveActorIdsForStateKVPairs { get; set; } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Models/EnumerationResponse.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Models/EnumerationResponse.cs deleted file mode 100644 index d4677255..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Models/EnumerationResponse.cs +++ /dev/null @@ -1,41 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration.Models -{ - using System.Collections.Generic; - using System.Runtime.Serialization; - - /// - /// Migration state response. - /// - [DataContract] - public class EnumerationResponse - { - /// - /// Gets the key value pairs. - /// - [DataMember] - public List KeyValuePairs { get; internal set; } - - /// - /// Gets or sets a value indicating whether the end of response is reached or not. - /// - [DataMember] - public bool EndSequenceNumberReached { get; set; } = false; - - /// - /// Gets or sets a value indicating whether the actorids are resolved from state storage key. - /// - [DataMember] - public bool ResolveActorIdsForStateKVPairs { get; set; } - - /// - /// Gets the hash for the values in the response. - /// - [DataMember] - public string ValueHash { get; internal set; } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Models/KeyValuePair.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Models/KeyValuePair.cs deleted file mode 100644 index 72bed3a7..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Models/KeyValuePair.cs +++ /dev/null @@ -1,49 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration.Models -{ - using System.IO; - using System.Runtime.Serialization; - using System.Runtime.Serialization.Json; - using System.Text; - - /// - /// KeyValuePair - /// - [DataContract] - public class KeyValuePair - { - /// - /// Gets or Sets Version - /// - [DataMember] - public long Version { get; set; } - - /// - /// Gets or Sets Key - /// - [DataMember] - public string Key { get; set; } - - /// - /// Gets or Sets Value - /// - [DataMember] - public byte[] Value { get; set; } - - /// - /// Gets or sets a value indicating whether IsDeleted - /// - [DataMember] - public bool IsDeleted { get; set; } - - /// - /// Gets or sets the actor id for the key value pair. - /// - [DataMember] - public string ActorId { get; set; } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/PartitionHealthExceptionFilter.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/PartitionHealthExceptionFilter.cs deleted file mode 100644 index d98fded2..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/PartitionHealthExceptionFilter.cs +++ /dev/null @@ -1,170 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Collections.Generic; - using System.Fabric; - using System.Fabric.Health; - - internal class PartitionHealthExceptionFilter - { - private const int MaxHealthDescriptionLength = (4 * 1024) - 1; - private Dictionary exceptions; - private MigrationSettings migrationSettings; - - public PartitionHealthExceptionFilter(MigrationSettings migrationSettings) - { - this.migrationSettings = migrationSettings; - - // All the exceptions with out an entry will be reported with health state warning and migration is aborted. - this.exceptions = new Dictionary() - { - // Ignore - { typeof(FabricNotPrimaryException).FullName, new ExceptionInfo(typeof(FabricNotPrimaryException).FullName, HealthState.Ok, false, false) }, - { typeof(OperationCanceledException).FullName, new ExceptionInfo(typeof(OperationCanceledException).FullName, HealthState.Ok, false, false) }, - - // Warning - //// Add warning list - - // Error - //// Add error list - }; - - this.PopulateExceptionListFromMigrationSettings(); - } - - public virtual void ReportPartitionHealth(Exception exception, IStatefulServicePartition partition, string healthMessage) - { - var actual = exception; - if (exception is AggregateException) - { - actual = ((AggregateException)exception).InnerException; - } - - var healthInfo = new HealthInformation("ActorStateMigration", "MigrationUnhandledException", HealthState.Warning) - { - TimeToLive = TimeSpan.MaxValue, - RemoveWhenExpired = true, - Description = this.GetPartitionHealthMesssage(actual, false, healthMessage), - }; - - partition.ReportPartitionHealth(healthInfo); - } - - public virtual void ReportPartitionHealthIfNeeded(Exception exception, IStatefulServicePartition partition, out bool abortMigration, out bool rethrow) - { - var actual = exception; - if (exception is AggregateException) - { - actual = ((AggregateException)exception).InnerException; - } - - var exceptionInfo = this.GetExceptionInfo(actual, out var rethrowT); - var healthInfo = new HealthInformation("ActorStateMigration", "MigrationUnhandledException", exceptionInfo.HealthState) - { - TimeToLive = exceptionInfo.IsPermanentError ? TimeSpan.MaxValue : TimeSpan.FromMinutes(2), - RemoveWhenExpired = true, - Description = this.GetPartitionHealthMesssage(actual, exceptionInfo.AbortMigration, null), - }; - - partition.ReportPartitionHealth(healthInfo); - abortMigration = exceptionInfo.AbortMigration; - rethrow = rethrowT; - } - - private void PopulateExceptionListFromMigrationSettings() - { - if (!string.IsNullOrWhiteSpace(this.migrationSettings.ExceptionExclusionListForAbort)) - { - var tokens = this.migrationSettings.ExceptionExclusionListForAbort.Trim().Split(','); - foreach (var token in tokens) - { - var type = token.Trim(); - this.exceptions.Add(type, new ExceptionInfo(type, HealthState.Error, false, false)); - } - } - } - - private string GetPartitionHealthMesssage(Exception exception, bool abortMigration, string healthMessage) - { - string healthDesc = string.Empty; - if (abortMigration) - { - healthDesc = "Aborting migration. "; - } - - if (!string.IsNullOrEmpty(healthMessage)) - { - healthDesc += $" {healthMessage}."; - } - - healthDesc += $"Exception message : {exception.Message}"; - - return healthDesc.Length <= MaxHealthDescriptionLength ? healthDesc : healthDesc.Substring(0, MaxHealthDescriptionLength); - } - - private ExceptionInfo GetExceptionInfo(Exception exception, out bool rethrow) - { - ExceptionInfo exceptionInfo = null; - rethrow = true; - if (!this.exceptions.TryGetValue(exception.GetType().FullName, out exceptionInfo)) - { - if (exception.Data.Contains("ActualExceptionType")) - { - if (!this.exceptions.TryGetValue((string)exception.Data["ActualExceptionType"], out exceptionInfo)) - { - exceptionInfo = new ExceptionInfo - { - ExceptionType = (string)exception.Data["ActualExceptionType"], - AbortMigration = true, - HealthState = HealthState.Warning, - IsPermanentError = true, - }; - } - - // Exception at source. Need not rethrow - rethrow = false; - } - else - { - exceptionInfo = new ExceptionInfo - { - ExceptionType = exception.GetType().FullName, - AbortMigration = true, - HealthState = HealthState.Warning, - IsPermanentError = true, - }; - } - } - - return exceptionInfo; - } - - public class ExceptionInfo - { - public ExceptionInfo() - { - } - - public ExceptionInfo(string exceptionType, HealthState healthState, bool abortMigration, bool isPermanentError) - { - this.ExceptionType = exceptionType; - this.HealthState = healthState; - this.AbortMigration = abortMigration; - this.IsPermanentError = isPermanentError; - } - - public string ExceptionType { get; set; } - - public HealthState HealthState { get; set; } - - public bool AbortMigration { get; set; } - - public bool IsPermanentError { get; set; } - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/PhaseInput.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/PhaseInput.cs deleted file mode 100644 index 9993ef88..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/PhaseInput.cs +++ /dev/null @@ -1,113 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.IO; - using System.Runtime.Serialization; - using System.Runtime.Serialization.Json; - using System.Text; - using Microsoft.ServiceFabric.Actors.Migration; - - [DataContract] - internal class PhaseInput - { - private static DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(PhaseInput), new DataContractJsonSerializerSettings - { - UseSimpleDictionaryFormat = true, - }); - - [DataMember] - public DateTime StartDateTimeUTC { get; set; } - - [DataMember] - public DateTime? EndDateTimeUTC { get; set; } - - [DataMember] - public long StartSeqNum { get; set; } - - [DataMember] - public long EndSeqNum { get; set; } - - [DataMember] - public long? LastAppliedSeqNum { get; set; } - - [DataMember] - public MigrationState Status { get; set; } - - [DataMember] - public int WorkerCount { get; set; } - - [DataMember] - public int IterationCount { get; set; } - - [DataMember] - public MigrationPhase Phase { get; set; } - - [DataMember] - public WorkerInput[] WorkerInputs { get; set; } - - public override string ToString() - { - using (var stream = new MemoryStream()) - { - serializer.WriteObject(stream, this); - - var returnVal = Encoding.ASCII.GetString(stream.GetBuffer()); - - return returnVal; - } - } - - [DataContract] - public class WorkerInput - { - private static DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(WorkerInput), new DataContractJsonSerializerSettings - { - UseSimpleDictionaryFormat = true, - }); - - [DataMember] - public int WorkerId { get; set; } - - [DataMember] - public int Iteration { get; set; } - - [DataMember] - public DateTime StartDateTimeUTC { get; set; } - - [DataMember] - public DateTime? EndDateTimeUTC { get; set; } - - [DataMember] - public long StartSeqNum { get; set; } - - [DataMember] - public long EndSeqNum { get; set; } - - [DataMember] - public long? LastAppliedSeqNum { get; set; } - - [DataMember] - public MigrationPhase Phase { get; set; } - - [DataMember] - public MigrationState Status { get; set; } - - public override string ToString() - { - using (var stream = new MemoryStream()) - { - serializer.WriteObject(stream, this); - - var returnVal = Encoding.ASCII.GetString(stream.GetBuffer()); - - return returnVal; - } - } - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Properties/AssemblyInfo.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Properties/AssemblyInfo.cs deleted file mode 100644 index 0c8aa27b..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -[assembly: System.CLSCompliant(true)] diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/RCAmbiguousActorIdHandler.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/RCAmbiguousActorIdHandler.cs deleted file mode 100644 index 7d2c756c..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/RCAmbiguousActorIdHandler.cs +++ /dev/null @@ -1,109 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Collections.Generic; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.Migration.Exceptions; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Actors.Runtime.Migration; - - internal class RCAmbiguousActorIdHandler : AmbiguousActorIdHandlerBase - { - private IReliableCollectionsActorStateProviderInternal stateProvider; - private List resolvers; - - public RCAmbiguousActorIdHandler(IReliableCollectionsActorStateProviderInternal stateProvider) - : base(stateProvider.GetActorStateProviderHelper()) - { - this.stateProvider = stateProvider; - this.resolvers = new List(); - foreach (var type in AmbiguousActorIdResolverAttribute.GetTypesWithAttribute()) - { - this.resolvers.Add((IAmbiguousActorIdResolver)Activator.CreateInstance(type)); - } - } - - public override Task TryResolveActorIdAsync(string stateStorageKey, CancellationToken cancellationToken) - { - throw new System.NotImplementedException(); - } - - public async Task ResolveActorIdAsync(string stateStorageKey, Data.ITransaction tx, CancellationToken cancellationToken, bool skipPresenceDictResolve = false) - { - var actorIdMatch = this.StripPrefixAndSuffixTokens(stateStorageKey); - var matchList = this.GetActorIdsToResolve(actorIdMatch); - if (matchList.Count == 1) - { - var kind = GetActorIdKind(stateStorageKey); - ActorId result; - switch (kind) - { - case ActorIdKind.Long: - result = new ActorId(long.Parse(matchList[0])); - break; - case ActorIdKind.Guid: - result = new ActorId(Guid.Parse(matchList[0])); - break; - default: - result = new ActorId(matchList[0]); - break; - } - - return result; - } - - if (!skipPresenceDictResolve) - { - var presenceDict = this.stateProvider.GetActorPresenceDictionary(); - var cv = await this.TryResolveActorIdAsync( - matchList, - async (match, token) => - { - return await presenceDict.ContainsKeyAsync(tx, $"String_{match}_", MigrationConstants.DefaultRCTimeout, token); - }, - cancellationToken); - - if (cv.HasValue) - { - return new ActorId(cv.Value); - } - } - - var toResolve = stateStorageKey.Substring(stateStorageKey.IndexOf("_") + 1); - foreach (var resolver in this.resolvers) - { - cancellationToken.ThrowIfCancellationRequested(); - if (resolver.TryResolveActorIdAndStateName(toResolve, out var resolvedId)) - { - return new ActorId(resolvedId); - } - } - - throw new AmbiguousActorIdDetectedException($"Ambiguous actor id detected - _ : {toResolve}. Implement Microsoft.ServiceFabric.Actors.Runtime.Migration.IAmbiguousActorIdResolver to resolve ambiguity."); - } - - private static ActorIdKind GetActorIdKind(string key) - { - var prefix = key.Substring(0, key.IndexOf('_')); - - if (prefix == ActorIdKind.Guid.ToString()) - { - return ActorIdKind.Guid; - } - else if (prefix == ActorIdKind.Long.ToString()) - { - return ActorIdKind.Long; - } - else - { - return ActorIdKind.String; - } - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/ReliableDictionaryExtensions.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/ReliableDictionaryExtensions.cs deleted file mode 100644 index a7ebeea8..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/ReliableDictionaryExtensions.cs +++ /dev/null @@ -1,48 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Collections.Generic; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Data.Collections; - - internal static class ReliableDictionaryExtensions - { - public static async Task GetAsync( - this IReliableDictionary2 dict, - Data.ITransaction tx, - string key, - TimeSpan timeout, - CancellationToken cancellationToken) - { - var result = await dict.TryGetValueAsync(tx, key, timeout, cancellationToken); - if (result.HasValue) - { - return result.Value; - } - - throw new KeyNotFoundException(key.ToString()); // TODO consider throwing SF exception. - } - - public static async Task GetValueOrDefaultAsync( - this IReliableDictionary2 dict, - Data.ITransaction tx, - string key, - TimeSpan timeout, - CancellationToken cancellationToken) - { - var result = await dict.TryGetValueAsync(tx, key, timeout, cancellationToken); - if (result.HasValue) - { - return result.Value; - } - - return null; - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/SerializationUtility.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/SerializationUtility.cs deleted file mode 100644 index 8aa2b3ae..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/SerializationUtility.cs +++ /dev/null @@ -1,61 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System.IO; - using System.Runtime.Serialization; - using System.Runtime.Serialization.Json; - using System.Xml; - - internal static class SerializationUtility - { - public static byte[] Serialize(DataContractSerializer serializer, T obj) - { - using (var memoryStream = new MemoryStream()) - { - using (var binaryWriter = XmlDictionaryWriter.CreateTextWriter(memoryStream)) - { - serializer.WriteObject(binaryWriter, obj); - binaryWriter.Flush(); - - return memoryStream.ToArray(); - } - } - } - - public static T Deserialize(DataContractSerializer serializer, byte[] buffer) - { - using (Stream memoryStream = new MemoryStream()) - { - memoryStream.Write(buffer, 0, buffer.Length); - memoryStream.Position = 0; - - using (var reader = XmlDictionaryReader.CreateTextReader(memoryStream, XmlDictionaryReaderQuotas.Max)) - { - return (T)serializer.ReadObject(reader); - } - } - } - - public static byte[] Serialize(DataContractJsonSerializer serializer, T obj) - { - using (var memoryStream = new MemoryStream()) - { - serializer.WriteObject(memoryStream, obj); - - return memoryStream.ToArray(); - } - } - - public static T Deserialize(DataContractJsonSerializer serializer, byte[] buffer) - { - using (var memoryStream = new MemoryStream(buffer)) - { - return (T)serializer.ReadObject(memoryStream); - } - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/SourceMigrationOrchestrator.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/SourceMigrationOrchestrator.cs deleted file mode 100644 index cfae07fe..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/SourceMigrationOrchestrator.cs +++ /dev/null @@ -1,188 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Fabric; - using System.Fabric.Health; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.Generator; - using Microsoft.ServiceFabric.Actors.Migration.Exceptions; - using Microsoft.ServiceFabric.Actors.Runtime; - - /// - /// Migration orchestrator for source(KVS based) service. - /// - internal class SourceMigrationOrchestrator : MigrationOrchestratorBase - { - private static readonly string TraceType = typeof(SourceMigrationOrchestrator).Name; - private KvsActorStateProvider migrationActorStateProvider; - private bool actorCallsAllowed; - private bool forwardRequest; - private ActorStateProviderHelper stateProviderHelper; - - /// - /// Initializes a new instance of the class. - /// - /// KVS actor state provider. - /// The type information of the Actor. - /// Service context the actor service is operating under. - /// Migration settings. - public SourceMigrationOrchestrator(IActorStateProvider stateProvider, ActorTypeInformation actorTypeInfo, StatefulServiceContext serviceContext, Actors.Runtime.Migration.MigrationSettings migrationSettings) - : base(serviceContext, actorTypeInfo, migrationSettings) - { - if (stateProvider.GetType() != typeof(KvsActorStateProvider)) - { - var errorMsg = $"{stateProvider.GetType()} not a valid state provider type for source of migration. {typeof(KvsActorStateProvider)} is the valid type."; - ActorTrace.Source.WriteErrorWithId( - TraceType, - this.TraceId, - errorMsg); - - throw new InvalidMigrationStateProviderException(errorMsg); - } - - this.actorCallsAllowed = false; - this.forwardRequest = false; - this.migrationActorStateProvider = stateProvider as KvsActorStateProvider; - this.stateProviderHelper = new ActorStateProviderHelper(this.migrationActorStateProvider); - } - - /// - public override async Task AbortMigrationAsync(bool userTriggered, CancellationToken cancellationToken) - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - "Aborting Migration"); - - await this.migrationActorStateProvider.ResumeWritesAsync(this.TraceId, cancellationToken); - this.actorCallsAllowed = true; - this.forwardRequest = false; - await this.InvokeCompletionCallback(this.actorCallsAllowed, cancellationToken); - } - - /// - public override bool AreActorCallsAllowed() - { - return this.actorCallsAllowed; - } - - /// - public override IActorStateProvider GetMigrationActorStateProvider() - { - return this.migrationActorStateProvider; - } - - /// - public override async Task StartDowntimeAsync(bool userTriggered, CancellationToken cancellationToken) - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - "Starting Downtime"); - - await this.migrationActorStateProvider.RejectWritesAsync(this.TraceId, cancellationToken); - this.actorCallsAllowed = false; - this.forwardRequest = true; - - await this.InvokeCompletionCallback(this.actorCallsAllowed, cancellationToken); - } - - /// - public override async Task StartMigrationAsync(bool userTriggered, CancellationToken cancellationToken) - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - "Starting Migration"); - - await this.StartOrResumeMigrationAsync(cancellationToken); - } - - public override bool IsActorCallToBeForwarded() - { - return this.forwardRequest && this.MigrationSettings.TargetServiceUri != null; - } - - public override void ThrowIfActorCallsDisallowed() - { - if (this.actorCallsAllowed) - { - return; - } - - var errorMsg = $"Actor calls are not allowed on the service."; - if (this.MigrationSettings.TargetServiceUri == null) - { - errorMsg += $" Configure TargetServiceUri in {this.MigrationSettings.MigrationConfigSectionName} section of settings file to forward the request."; - } - - throw new ActorCallsDisallowedException(errorMsg); - } - - public override bool IsAutoStartMigration() - { - return true; - } - - protected override Uri GetForwardServiceUri() - { - return this.MigrationSettings.TargetServiceUri; - } - - protected override Int64RangePartitionInformation GetInt64RangePartitionInformation() - { - var servicePartition = this.migrationActorStateProvider.StatefulServicePartition; - return servicePartition.PartitionInfo as Int64RangePartitionInformation; - } - - /// - protected override string GetMigrationEndpointName() - { - // TODO: Validate migration EP in service manifest - return ActorNameFormat.GetMigrationSourceEndpointName(this.ActorTypeInformation.ImplementationType); - } - - private async Task AreActorCallsAllowedInternalAsync(CancellationToken cancellationToken) - { - return await this.stateProviderHelper.ExecuteWithRetriesAsync( - async () => !(await this.migrationActorStateProvider.GetRejectWriteStateAsync(this.TraceId, cancellationToken)), - "KVSActorStateProvider.GetRejectWriteState", - CancellationToken.None); - } - - private async Task StartOrResumeMigrationAsync(CancellationToken cancellationToken) - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - "Starting or resuming Migration"); - - this.actorCallsAllowed = await this.AreActorCallsAllowedInternalAsync(cancellationToken); - this.forwardRequest = !this.actorCallsAllowed; - if (!this.migrationActorStateProvider.IsTombstoneCleanupDisabled()) - { - ActorTrace.Source.WriteWarningWithId( - TraceType, - this.TraceId, - "Tombstone cleanup is not enabled."); - - var healthInfo = new HealthInformation("ActorStateMigration", "ActorStateMigrationChecks", HealthState.Warning) - { - TimeToLive = TimeSpan.MaxValue, - RemoveWhenExpired = false, - Description = KvsActorStateProviderExtensions.TombstoneCleanupMessage, - }; - - this.migrationActorStateProvider.ReportPartitionHealth(healthInfo); - } - - await this.InvokeCompletionCallback(this.actorCallsAllowed, cancellationToken); - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Startup.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Startup.cs deleted file mode 100644 index 9240df2b..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Startup.cs +++ /dev/null @@ -1,49 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using Microsoft.AspNetCore.Builder; - using Microsoft.AspNetCore.Hosting; - using Microsoft.AspNetCore.Mvc; - using Microsoft.AspNetCore.Mvc.Infrastructure; - using Microsoft.Extensions.Configuration; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration.Controllers; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration.Middleware; - - internal class Startup - { - public Startup(IConfiguration configuration) - { - this.Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - public void ConfigureServices(IServiceCollection services) - { - services.AddMvc() - .SetCompatibilityVersion(CompatibilityVersion.Version_2_0) - .ConfigureApplicationPartManager(manager => - { - // load internal migration controllers - manager.FeatureProviders.Add(new MigrationControllerFeatureProvider()); - }); - } - - public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime applicationLifetime, IActionDescriptorCollectionProvider actionDescriptorCollectionProvider) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseStatusCodePages(); - app.UseMiddleware(); - app.UseMvc(); - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/TargetMigrationOrchestrator.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/TargetMigrationOrchestrator.cs deleted file mode 100644 index 1ad1eba4..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/TargetMigrationOrchestrator.cs +++ /dev/null @@ -1,999 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Collections.Generic; - using System.Fabric; - using System.Fabric.Description; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.Generator; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration.Extensions; - using Microsoft.ServiceFabric.Actors.Migration; - using Microsoft.ServiceFabric.Actors.Migration.Exceptions; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Actors.Runtime.Migration; - using Microsoft.ServiceFabric.Data.Collections; - using Microsoft.ServiceFabric.Services.Client; - using Microsoft.ServiceFabric.Services.Communication.Client; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.MigrationConstants; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.MigrationUtility; - - /// - /// Orchestrator for Target(RC based) service. - /// - internal class TargetMigrationOrchestrator : MigrationOrchestratorBase - { - private static readonly string TraceType = typeof(TargetMigrationOrchestrator).Name; - private volatile int isReadyForMigrationOperations = 0; - private volatile int isMigrationWorkflowRunning = 0; - private MigrationPhase currentPhase; - private KVStoRCMigrationActorStateProvider migrationActorStateProvider; - private IReliableDictionary2 metadataDict; - private ServicePartitionClient partitionClient; - private volatile MigrationState currentMigrationState; - private CancellationTokenSource childCancellationTokenSource; - private PartitionHealthExceptionFilter exceptionFilter; - private ActorStateProviderHelper stateProviderHelper; - private volatile int validationComplete = 0; - - /// - /// Initializes a new instance of the class. - /// - /// KVS actor state provider. - /// The type information of the Actor. - /// Service context the actor service is operating under. - /// Migration settings. - public TargetMigrationOrchestrator(IActorStateProvider stateProvider, ActorTypeInformation actorTypeInfo, StatefulServiceContext serviceContext, Actors.Runtime.Migration.MigrationSettings migrationSettings) - : base(serviceContext, actorTypeInfo, migrationSettings) - { - if (stateProvider.GetType() != typeof(ReliableCollectionsActorStateProvider)) - { - var errorMsg = $"{stateProvider.GetType()} not a valid state provider type for source of migration. {typeof(ReliableCollectionsActorStateProvider)} is the valid type."; - ActorTrace.Source.WriteErrorWithId( - TraceType, - this.TraceId, - errorMsg); - - throw new InvalidMigrationStateProviderException(errorMsg); - } - - this.currentPhase = MigrationPhase.None; - this.currentMigrationState = MigrationState.None; - this.migrationActorStateProvider = new KVStoRCMigrationActorStateProvider(stateProvider as ReliableCollectionsActorStateProvider); - this.stateProviderHelper = (stateProvider as IReliableCollectionsActorStateProviderInternal).GetActorStateProviderHelper(); - this.exceptionFilter = new PartitionHealthExceptionFilter(this.MigrationSettings); - } - - // Constructor for UTs. - public TargetMigrationOrchestrator( - KVStoRCMigrationActorStateProvider migrationActorStateProviderProvider, - ActorTypeInformation actorTypeInfo, - StatefulServiceContext serviceContext, - Actors.Runtime.Migration.MigrationSettings migrationSettings, - PartitionHealthExceptionFilter exceptionFilter, - ServicePartitionClient partitionClient, - string traceId) - : base(serviceContext, actorTypeInfo, migrationSettings, traceId) - { - this.currentPhase = MigrationPhase.None; - this.currentMigrationState = MigrationState.None; - this.migrationActorStateProvider = migrationActorStateProviderProvider; - this.stateProviderHelper = migrationActorStateProviderProvider.GetInternalStateProvider().GetActorStateProviderHelper(); - this.exceptionFilter = exceptionFilter; - this.partitionClient = partitionClient; - } - - internal Data.ITransaction Transaction { get => this.migrationActorStateProvider.GetStateManager().CreateTransaction(); } - - internal IReliableDictionary2 MetaDataDictionary { get => this.metadataDict; } - - internal ServicePartitionClient ServicePartitionClient - { - get - { - if (this.partitionClient == null) - { //// TODO: Operation retry settings - var partitionInformation = this.GetInt64RangePartitionInformation(); - this.partitionClient = new ServicePartitionClient( - new HttpCommunicationClientFactory(null, new List() { new HttpExceptionHandler() }), - this.MigrationSettings.SourceServiceUri, - new ServicePartitionKey(partitionInformation.LowKey), - TargetReplicaSelector.PrimaryReplica, - Constants.MigrationListenerName); - } - - return this.partitionClient; - } - } - - internal KVStoRCMigrationActorStateProvider StateProvider { get => this.migrationActorStateProvider; } - - public async override Task StartMigrationAsync(bool isUserTriggered, CancellationToken cancellationToken) - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"StartMigrationAsync isUserTriggered : {isUserTriggered}, MigrationMode : {this.MigrationSettings.MigrationMode}"); - - if (Interlocked.CompareExchange(ref this.validationComplete, 1, 0) == 0) - { - await this.ValidateConfigForMigrationAsync(cancellationToken); - } - - try - { - if (!isUserTriggered) - { - this.metadataDict = await this.migrationActorStateProvider.GetMetadataDictionaryAsync(); - this.childCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); - this.currentMigrationState = await this.GetCurrentMigrationStateAsync(this.childCancellationTokenSource.Token); - Interlocked.CompareExchange(ref this.isReadyForMigrationOperations, 1, 0); - this.childCancellationTokenSource.Token.Register(() => - { - // Interlocked.CompareExchange(ref this.isReadyForMigrationOperations, 0, 1); - Interlocked.CompareExchange(ref this.isMigrationWorkflowRunning, 0, 1); - }); - } - else - { - if (this.MigrationSettings.MigrationMode == MigrationMode.Auto) - { - throw new InvalidMigrationOperationException("MigrationMode is set to Auto. Manual migration starts are not allowed."); - } - else - { - this.ThrowIfNotReady(); - } - } - - var childToken = this.childCancellationTokenSource.Token; - if (this.currentMigrationState == MigrationState.Aborted) - { - var abortInvokedOnSource = await ParseBoolAsync( - () => GetValueOrDefaultAsync(this.stateProviderHelper, () => this.Transaction, this.MetaDataDictionary, AbortMigrationInvokedOnSource, cancellationToken), - this.TraceId); - - if (!abortInvokedOnSource) - { - await this.AbortMigrationAsync(false, childToken); - } - - return; - } - - if (this.MigrationSettings.MigrationMode == MigrationMode.Auto) - { - if (this.currentMigrationState == MigrationState.None) - { - await this.InitializeAsync(childToken); - } - - await this.StartOrResumeMigrationAsync(childToken); - } - else - { - if (isUserTriggered) - { - if (this.currentMigrationState == MigrationState.None) - { - await this.InitializeAsync(childToken); - - // TODO: Bug fix: 15538471 - StartOrResumeMigrationAsync should not be awaited for Manual Mode Migration - await this.StartOrResumeMigrationAsync(childToken); - } - else - { - throw new InvalidMigrationOperationException("Migration is either in progress or already completed"); - } - } - else - { - if (this.currentMigrationState == MigrationState.InProgress) - { - await this.StartOrResumeMigrationAsync(childToken); - } - else - { - return; - } - } - } - } - catch (Exception ex) - { - ActorTrace.Source.WriteErrorWithId( - TraceType, - this.TraceId, - $"Migration {this.currentPhase} Phase failed with error: {ex}"); - MigrationTelemetry.MigrationFailureEvent(this.StatefulServiceContext, this.currentPhase.ToString(), ex.Message); - //// TODO: Emit exception type in telemetry - - this.exceptionFilter.ReportPartitionHealthIfNeeded(ex, this.StateProvider.StatefulServicePartition, out var abortMigration, out var rethrow); - if (abortMigration) - { - await this.AbortMigrationAsync(userTriggered: false, this.GetToken()); - } - - if (rethrow) - { - throw ex; - } - } - finally - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"StartMigrationAsync Completed - isUserTriggered : {isUserTriggered}, MigrationMode : {this.MigrationSettings.MigrationMode}"); - - await this.InvokeCompletionCallback(this.AreActorCallsAllowed(), this.GetToken()); - } - } - - public async override Task AbortMigrationAsync(bool userTriggered, CancellationToken cancellationToken) - { - this.ThrowIfNotReady(); - if (userTriggered) - { - this.ThrowIfInvalidOperation(); - if (this.childCancellationTokenSource != null) - { - this.childCancellationTokenSource.Cancel(); - } - } - - try - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"Aborting Migration. UserTriggered : {userTriggered}"); - MigrationTelemetry.MigrationAbortEvent(this.StatefulServiceContext, userTriggered); - - await this.stateProviderHelper.ExecuteWithRetriesAsync( - async () => - { - using (var tx = this.Transaction) - { - await this.metadataDict.TryAddAsync( - tx, - MigrationEndDateTimeUTC, - DateTime.UtcNow.ToString(), - DefaultRCTimeout, - cancellationToken); - - await this.metadataDict.AddOrUpdateAsync( - tx, - MigrationCurrentStatus, - MigrationState.Aborted.ToString(), - (_, __) => MigrationState.Aborted.ToString(), - DefaultRCTimeout, - cancellationToken); - - await tx.CommitAsync(); - } - }, - "TargetMigrationOrchestrator.AbortMigrationAsync", - cancellationToken); - this.currentMigrationState = MigrationState.Aborted; - - await this.InvokeResumeWritesAsync(cancellationToken); - } - catch (Exception ex) - { - this.exceptionFilter.ReportPartitionHealth(ex, this.StateProvider.StatefulServicePartition, "Aborting Migration workflow failed."); - - throw ex; - } - } - - /// - public override bool AreActorCallsAllowed() - { - return this.currentMigrationState == MigrationState.Completed; - } - - /// - public override IActorStateProvider GetMigrationActorStateProvider() - { - return this.migrationActorStateProvider; - } - - /// - public override async Task StartDowntimeAsync(bool userTriggered, CancellationToken cancellationToken) - { - this.ThrowIfNotReady(); - this.ThrowIfInvalidOperation(); - await this.stateProviderHelper.ExecuteWithRetriesAsync( - async () => - { - using (var tx = this.Transaction) - { - await this.metadataDict.TryAddAsync( - tx, - IsDowntimeInvoked, - true.ToString(), - DefaultRCTimeout, - cancellationToken); - - await tx.CommitAsync(); - } - }, - "TargetMigrationOrchestrator.StartDowntimeAsync", - cancellationToken); - } - - public override bool IsActorCallToBeForwarded() - { - this.ThrowIfNotReady(); - - // No reason to forward the call in downtime phase as the KVS service also cannot service the request. - return (this.currentPhase < MigrationPhase.Downtime || this.currentMigrationState == MigrationState.Aborted) && this.MigrationSettings.SourceServiceUri != null; - } - - public override void ThrowIfActorCallsDisallowed() - { - if (this.AreActorCallsAllowed()) - { - return; - } - - var errorMsg = $"Actor calls are not allowed on the service."; - if (this.MigrationSettings.SourceServiceUri == null) - { - errorMsg += $" Configure SourceServiceUri in {this.MigrationSettings.MigrationConfigSectionName} section of settings file to forward the request."; - } - - throw new ActorCallsDisallowedException(errorMsg); - } - - internal async Task GetResultAsync(CancellationToken cancellationToken) - { - this.ThrowIfNotReady(); - - ActorTrace.Source.WriteNoiseWithId( - TraceType, - this.TraceId, - $"Getting migration result."); - - var startSN = await this.GetStartSequenceNumberAsync(cancellationToken); - var endSN = await this.GetEndSequenceNumberAsync(cancellationToken); - var status = await this.GetCurrentMigrationStateAsync(cancellationToken); - if (status == MigrationState.None) - { - return new MigrationResult - { - MigrationMode = this.MigrationSettings.MigrationMode, - CurrentPhase = MigrationPhase.None, - Status = MigrationState.None, - StartSeqNum = startSN, - EndSeqNum = endSN, - }; - } - - var result = new MigrationResult - { - MigrationMode = this.MigrationSettings.MigrationMode, - Status = status, - EndSeqNum = endSN, - }; - - result.CurrentPhase = await this.GetCurrentMigrationPhaseAsync(cancellationToken); - - result.StartDateTimeUTC = await ParseDateTimeAsync( - () => GetValueOrDefaultAsync(this.stateProviderHelper, () => this.Transaction, this.MetaDataDictionary, MigrationStartDateTimeUTC, cancellationToken), - this.TraceId); - - result.EndDateTimeUTC = await ParseDateTimeAsync( - () => GetValueOrDefaultAsync(this.stateProviderHelper, () => this.Transaction, this.MetaDataDictionary, MigrationEndDateTimeUTC, cancellationToken), - this.TraceId); - - result.StartSeqNum = await ParseLongAsync( - () => GetValueOrDefaultAsync(this.stateProviderHelper, () => this.Transaction, this.MetaDataDictionary, MigrationStartSeqNum, cancellationToken), - this.TraceId); - - result.LastAppliedSeqNum = await ParseLongAsync( - () => GetValueOrDefaultAsync(this.stateProviderHelper, () => this.Transaction, this.MetaDataDictionary, MigrationLastAppliedSeqNum, cancellationToken), - this.TraceId); - - result.NoOfKeysMigrated = await ParseLongAsync( - () => GetValueOrDefaultAsync(this.stateProviderHelper, () => this.Transaction, this.MetaDataDictionary, MigrationNoOfKeysMigrated, cancellationToken), - this.TraceId); - - var currentPhase = MigrationPhase.Copy; - var phaseResults = new List(); - while (currentPhase <= result.CurrentPhase) - { - var currentIteration = await ParseIntAsync( - () => GetValueOrDefaultAsync(this.stateProviderHelper, () => this.Transaction, this.MetaDataDictionary, Key(PhaseIterationCount, currentPhase), cancellationToken), - 0, - this.TraceId); - for (int i = 1; i <= currentIteration; i++) - { - phaseResults.Add(await MigrationPhaseWorkloadBase.GetResultAsync( - this.stateProviderHelper, - () => this.Transaction, - this.MetaDataDictionary, - currentPhase, - i, - this.TraceId, - cancellationToken)); - } - - currentPhase++; - } - - result.PhaseResults = phaseResults.ToArray(); - - return result; - } - - internal virtual IMigrationPhaseWorkload GetMigrationPhaseWorkload(MigrationPhase currentPhase, int currentIteration) - { - IMigrationPhaseWorkload migrationWorkload = null; - switch (currentPhase) - { - case MigrationPhase.None: - case MigrationPhase.Copy: - migrationWorkload = new CopyPhaseWorkload( - this.StateProvider, - this.ServicePartitionClient, - this.StatefulServiceContext, - this.MigrationSettings, - this.ActorTypeInformation, - this.TraceId); - break; - case MigrationPhase.Catchup: - migrationWorkload = new CatchupPhaseWorkload( - currentIteration, - this.StateProvider, - this.ServicePartitionClient, - this.StatefulServiceContext, - this.MigrationSettings, - this.ActorTypeInformation, - this.TraceId); - break; - case MigrationPhase.Downtime: - migrationWorkload = new DowntimeWorkload( - this.StateProvider, - this.ServicePartitionClient, - this.StatefulServiceContext, - this.MigrationSettings, - this.ActorTypeInformation, - this.TraceId); - break; - default: - migrationWorkload = null; - break; - } - - return migrationWorkload; - } - - internal virtual async Task ValidateConfigForMigrationAsync(CancellationToken cancellationToken) - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"Validating Migration config."); - - var migrationConfigSectionName = this.MigrationSettings.MigrationConfigSectionName; - - this.MigrationSettings.Validate(isSource: false); - var fabricClient = new FabricClient(); - var kvsServiceDescription = await fabricClient.ServiceManager.GetServiceDescriptionAsync(this.MigrationSettings.SourceServiceUri); - if (kvsServiceDescription == null) - { - var errorMsg = $"Unable to load service description for migration service name - {this.MigrationSettings.SourceServiceUri}."; - ActorTrace.Source.WriteErrorWithId( - TraceType, - this.TraceId, - errorMsg); - - throw new InvalidMigrationConfigException(errorMsg); - } - - var kvsServicePartitionCount = this.GetServicePartitionCount(kvsServiceDescription); - var rcServiceDescription = await fabricClient.ServiceManager.GetServiceDescriptionAsync(this.StatefulServiceContext.ServiceName); - var rcServicePartitionCount = this.GetServicePartitionCount(rcServiceDescription); - var isDisableTombstoneCleanup = await this.GetKVSDisableTombstoneCleanupSettingAsync(cancellationToken); - - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - "kvsServiceDescription.PartitionSchemeDescription.Scheme = {0}; kvsServicePartitionCount = {1}; rcServiceDescription.PartitionSchemeDescription.Scheme = {2}; rcServicePartitionCount = {3}; isDisableTombstoneCleanup = {4}", - kvsServiceDescription.PartitionSchemeDescription.Scheme, - kvsServicePartitionCount, - rcServiceDescription.PartitionSchemeDescription.Scheme, - rcServicePartitionCount, - isDisableTombstoneCleanup); - - if (kvsServiceDescription.PartitionSchemeDescription.Scheme != rcServiceDescription.PartitionSchemeDescription.Scheme) - { - var errorMsg = $"Source migration service({this.MigrationSettings.SourceServiceUri}) partition scheme({kvsServiceDescription.PartitionSchemeDescription.Scheme}) does not match with target migration service({this.MigrationSettings.TargetServiceUri}) partition scheme({rcServiceDescription.PartitionSchemeDescription.Scheme})"; - ActorTrace.Source.WriteErrorWithId( - TraceType, - this.TraceId, - errorMsg); - - throw new InvalidMigrationConfigException(errorMsg); - } - - if (kvsServicePartitionCount != rcServicePartitionCount) - { - var errorMsg = $"Source migration service({this.MigrationSettings.SourceServiceUri}) partition count({kvsServicePartitionCount}) does not match with target migration service({this.MigrationSettings.TargetServiceUri}) partition count({rcServicePartitionCount})"; - ActorTrace.Source.WriteErrorWithId( - TraceType, - this.TraceId, - errorMsg); - - throw new InvalidMigrationConfigException(errorMsg); - } - - if (!isDisableTombstoneCleanup) - { - var errorMsg = $"DisableTombstoneCleanup is not disabled in source migration service({this.MigrationSettings.SourceServiceUri})"; - ActorTrace.Source.WriteErrorWithId( - TraceType, - this.TraceId, - errorMsg); - - throw new InvalidMigrationConfigException(errorMsg); - } - //// TODO: Emit telemetry - } - - protected override Uri GetForwardServiceUri() - { - return this.MigrationSettings.SourceServiceUri; - } - - protected override Int64RangePartitionInformation GetInt64RangePartitionInformation() - { - var servicePartition = this.migrationActorStateProvider.StatefulServicePartition; - if (servicePartition == null) - { - // TODO throw - } - - return servicePartition.PartitionInfo as Int64RangePartitionInformation; - } - - /// - protected override string GetMigrationEndpointName() - { - // TODO: Validate migration EP in service manifest - return ActorNameFormat.GetMigrationTargetEndpointName(this.ActorTypeInformation.ImplementationType); - } - - private CancellationToken GetToken() - { - var token = CancellationToken.None; - if (this.childCancellationTokenSource != null && !this.childCancellationTokenSource.IsCancellationRequested) - { - var token1 = this.childCancellationTokenSource.Token; - if (!token1.IsCancellationRequested) - { - return token1; - } - } - - return token; - } - - private async Task StartOrResumeMigrationAsync(CancellationToken cancellationToken) - { - if (Interlocked.CompareExchange(ref this.isMigrationWorkflowRunning, 1, 0) != 0) - { - ActorTrace.Source.WriteWarningWithId( - TraceType, - this.TraceId, - "Migration workflow already running. Ignoring the request."); - - return; - } - - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - "Starting or resuming migration Migration."); - MigrationTelemetry.MigrationStartEvent(this.StatefulServiceContext, this.MigrationSettings.ToString()); - - var migrationCurrentPhase = await this.GetCurrentMigrationPhaseAsync(cancellationToken); - var workloadRunner = await this.NextWorkloadRunnerAsync(migrationCurrentPhase, cancellationToken); - - PhaseResult currentResult = null; - while (workloadRunner != null) - { - this.currentPhase = workloadRunner.Phase; - currentResult = await workloadRunner.StartOrResumeMigrationAsync(cancellationToken); - workloadRunner = await this.NextWorkloadRunnerAsync(currentResult, cancellationToken); - } - - if (currentResult != null) - { - await this.CompleteMigrationAsync(currentResult, cancellationToken); - this.currentPhase = MigrationPhase.Completed; - - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"Migration successfully completed - {currentResult.ToString()}"); - MigrationTelemetry.MigrationEndEvent(this.StatefulServiceContext, currentResult.ToString()); - } - } - - private async Task GetCurrentMigrationPhaseAsync(CancellationToken cancellationToken) - { - return await ParseMigrationPhaseAsync( - () => GetValueOrDefaultAsync(this.stateProviderHelper, () => this.Transaction, this.MetaDataDictionary, MigrationCurrentPhase, cancellationToken), - this.TraceId); - } - - private async Task GetCurrentMigrationStateAsync(CancellationToken cancellationToken) - { - return await ParseMigrationStateAsync( - () => GetValueOrDefaultAsync(this.stateProviderHelper, () => this.Transaction, this.MetaDataDictionary, MigrationCurrentStatus, cancellationToken), - this.TraceId); - } - - private async Task CompleteMigrationAsync(PhaseResult result, CancellationToken cancellationToken) - { - await this.stateProviderHelper.ExecuteWithRetriesAsync( - async () => - { - using (var tx = this.Transaction) - { - await this.metadataDict.TryAddAsync( - tx, - MigrationEndDateTimeUTC, - DateTime.UtcNow.ToString(), - DefaultRCTimeout, - cancellationToken); - - await this.metadataDict.TryAddAsync( - tx, - MigrationEndSeqNum, - result.EndSeqNum.ToString(), - DefaultRCTimeout, - cancellationToken); - - await this.metadataDict.AddOrUpdateAsync( - tx, - MigrationCurrentStatus, - MigrationState.Completed.ToString(), - (_, __) => MigrationState.Completed.ToString(), - DefaultRCTimeout, - cancellationToken); - - await this.metadataDict.AddOrUpdateAsync( - tx, - MigrationCurrentPhase, - MigrationPhase.Completed.ToString(), - (_, __) => MigrationPhase.Completed.ToString(), - DefaultRCTimeout, - cancellationToken); - - await tx.CommitAsync(); - } - }, - "TargetMigrationOrchestrator.CompleteMigrationAsync", - cancellationToken); - - this.currentMigrationState = MigrationState.Completed; - Interlocked.CompareExchange(ref this.isMigrationWorkflowRunning, 0, 1); - } - - private async Task GetEndSequenceNumberAsync(CancellationToken cancellationToken) - { - ActorTrace.Source.WriteNoiseWithId( - TraceType, - this.TraceId, - $"Getting End Seq num."); - var response = await this.ServicePartitionClient.InvokeWebRequestWithRetryAsync( - async client => - { - return await client.HttpClient.GetAsync($"{KVSMigrationControllerName}/{GetEndSNEndpoint}"); - }, - "GetEndSequenceNumberAsync", - cancellationToken); - return (await ParseLongAsync(async () => await response.Content.ReadAsStringAsync(), this.TraceId)).Value; - } - - private async Task GetStartSequenceNumberAsync(CancellationToken cancellationToken) - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"Gettting start seq num."); - - var response = await this.ServicePartitionClient.InvokeWebRequestWithRetryAsync( - async client => - { - return await client.HttpClient.GetAsync($"{KVSMigrationControllerName}/{GetStartSNEndpoint}"); - }, - "GetStartSequenceNumberAsync", - cancellationToken); - return (await ParseLongAsync(async () => await response.Content.ReadAsStringAsync(), this.TraceId)).Value; - } - - private async Task InvokeRejectWritesAsync(CancellationToken cancellationToken) - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"Invoking reject writes in source migration service."); - - try - { - var response = await this.ServicePartitionClient.InvokeWebRequestWithRetryAsync( - async client => - { - return await client.HttpClient.PutAsync($"{KVSMigrationControllerName}/{StartDowntimeEndpoint}", null); - }, - "InvokeRejectWritesAsync", - cancellationToken); - } - catch (FabricException ex) - { - if (ex.ErrorCode == FabricErrorCode.DatabaseMigrationInProgress) - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"Downtime is already invoked on source migration service."); - } - else - { - throw ex; - } - } - } - - private async Task InvokeResumeWritesAsync(CancellationToken cancellationToken) - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"Invoking resume writes in source migration service."); - - try - { - var response = await this.ServicePartitionClient.InvokeWebRequestWithRetryAsync( - async client => - { - return await client.HttpClient.PutAsync($"{KVSMigrationControllerName}/{AbortMigrationEndpoint}", null); - }, - "InvokeResumeWritesAsync", - cancellationToken); - } - catch (FabricException ex) - { - if (ex.ErrorCode == FabricErrorCode.DatabaseMigrationInProgress) - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"Source migration service is rejecting writes."); - - await this.RestartPrimaryAndInvokeResumeWritesAsync(cancellationToken); - } - else - { - throw ex; - } - } - - await this.stateProviderHelper.ExecuteWithRetriesAsync( - async () => - { - using (var tx = this.Transaction) - { - await this.MetaDataDictionary.AddOrUpdateAsync( - tx, - AbortMigrationInvokedOnSource, - bool.TrueString, - (_, __) => bool.TrueString, - DefaultRCTimeout, - cancellationToken); - - await tx.CommitAsync(); - } - }, - $"TargetMigrationOrchestrator.NextWorkloadRunnerAsync.{Key(PhaseIterationCount, MigrationPhase.Catchup)}", - cancellationToken); - } - - private async Task RestartPrimaryAndInvokeResumeWritesAsync(CancellationToken cancellationToken) - { - await this.RestartPrimaryReplicaAsync(cancellationToken); - - var response = await this.ServicePartitionClient.InvokeWebRequestWithRetryAsync( - async client => - { - return await client.HttpClient.PutAsync($"{KVSMigrationControllerName}/{AbortMigrationEndpoint}", null); - }, - "InvokeResumeWritesAsync", - cancellationToken); - } - - private async Task NextWorkloadRunnerAsync(PhaseResult currentResult, CancellationToken cancellationToken) - { - var endSN = await this.GetEndSequenceNumberAsync(cancellationToken); - var delta = endSN - currentResult.EndSeqNum; - var isDowntimeInvoked = false; - - if (currentResult.Phase == MigrationPhase.Catchup) - { - if (!this.IsAutoStartMigration()) - { - isDowntimeInvoked = await ParseBoolAsync( - () => GetValueOrDefaultAsync(this.stateProviderHelper, () => this.Transaction, this.MetaDataDictionary, IsDowntimeInvoked, cancellationToken), - this.TraceId); - } - else if (delta < this.MigrationSettings.DowntimeThreshold) - { - isDowntimeInvoked = true; - } - - if (isDowntimeInvoked) - { - await this.InvokeRejectWritesAsync(cancellationToken); - return await this.NextWorkloadRunnerAsync(MigrationPhase.Downtime, cancellationToken); - } - else - { - return await this.NextWorkloadRunnerAsync(MigrationPhase.Catchup, cancellationToken); - } - } - - return await this.NextWorkloadRunnerAsync(currentResult.Phase + 1, cancellationToken); - } - - private async Task NextWorkloadRunnerAsync(MigrationPhase currentPhase, CancellationToken cancellationToken) - { - var currentIteration = 0; - if (currentPhase == MigrationPhase.Catchup) - { - currentIteration = await ParseIntAsync( - () => this.stateProviderHelper.ExecuteWithRetriesAsync( - async () => - { - using (var tx = this.Transaction) - { - var res = await this.MetaDataDictionary.GetOrAddAsync( - tx, - Key(PhaseIterationCount, MigrationPhase.Catchup), - "1", - DefaultRCTimeout, - cancellationToken); - await tx.CommitAsync(); - - return res; - } - }, - $"TargetMigrationOrchestrator.NextWorkloadRunnerAsync.{Key(PhaseIterationCount, MigrationPhase.Catchup)}", - cancellationToken), - this.TraceId); - - var status = await ParseMigrationStateAsync( - () => GetValueOrDefaultAsync(this.stateProviderHelper, () => this.Transaction, this.MetaDataDictionary, Key(PhaseCurrentStatus, MigrationPhase.Catchup, currentIteration), cancellationToken), - this.TraceId); - if (status == MigrationState.Completed) - { - currentIteration++; - } - } - - return this.GetMigrationPhaseWorkload(currentPhase, currentIteration); - } - - private async Task InitializeAsync(CancellationToken cancellationToken) - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"Initializing Migration."); - - await this.stateProviderHelper.ExecuteWithRetriesAsync( - async () => - { - using (var tx = this.Transaction) - { - await this.MetaDataDictionary.TryAddAsync( - tx, - MigrationStartDateTimeUTC, - DateTime.UtcNow.ToString(), - DefaultRCTimeout, - cancellationToken); - - await this.MetaDataDictionary.TryAddAsync( - tx, - MigrationCurrentStatus, - MigrationState.InProgress.ToString(), - DefaultRCTimeout, - cancellationToken); - - await this.MetaDataDictionary.TryAddAsync( - tx, - MigrationCurrentPhase, - MigrationPhase.None.ToString(), - DefaultRCTimeout, - cancellationToken); - - await tx.CommitAsync(); - } - }, - "TargetMigrationOrchestrator.InitializeAsync", - cancellationToken); - - this.currentMigrationState = MigrationState.InProgress; - } - - private async Task RestartPrimaryReplicaAsync(CancellationToken cancellationToken) - { - var partitionInformation = this.GetInt64RangePartitionInformation(); - var lowkey = partitionInformation.LowKey; - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"Attempting to restart primary replica of partition - {partitionInformation}"); - var faultManagementClient = new FabricClient().FaultManager; - await faultManagementClient.RestartReplicaAsync(ReplicaSelector.PrimaryOf(PartitionSelector.PartitionKeyOf(this.MigrationSettings.SourceServiceUri, lowkey)), CompletionMode.Verify, cancellationToken); - } - - private int GetServicePartitionCount(ServiceDescription serviceDescription) - { - switch (serviceDescription.PartitionSchemeDescription.Scheme) - { - case PartitionScheme.Singleton: - return 1; - case PartitionScheme.UniformInt64Range: - return (serviceDescription.PartitionSchemeDescription as UniformInt64RangePartitionSchemeDescription).PartitionCount; - case PartitionScheme.Named: - return (serviceDescription.PartitionSchemeDescription as NamedPartitionSchemeDescription).PartitionNames.Count; - case PartitionScheme.Invalid: - default: - return 0; - } - } - - private async Task GetKVSDisableTombstoneCleanupSettingAsync(CancellationToken cancellationToken) - { - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.TraceId, - $"Getting tombstone cleanup setting"); - - var response = await this.ServicePartitionClient.InvokeWebRequestWithRetryAsync( - async client => - { - return await client.HttpClient.GetAsync($"{KVSMigrationControllerName}/{GetDisableTCSEndpoint}"); - }, - "GetDisableTCSEndpoint", - cancellationToken); - return (await ParseBoolAsync(async () => await response.Content.ReadAsStringAsync(), this.TraceId)); - } - - private void ThrowIfNotReady() - { - if (this.isReadyForMigrationOperations != 1) - { - throw new MigrationFrameworkNotInitializedException("MigrationFramework not initialized. Retry the request"); - } - } - - private void ThrowIfInvalidOperation() - { - if (this.currentMigrationState == MigrationState.Completed || this.currentMigrationState == MigrationState.Aborted) - { - throw new InvalidMigrationOperationException($"Operation not allowed when current nigration state is {this.currentMigrationState}"); - } - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/WorkerBase.cs b/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/WorkerBase.cs deleted file mode 100644 index 9c288e75..00000000 --- a/src/Microsoft.ServiceFabric.Actors.KVSToRCMigration/WorkerBase.cs +++ /dev/null @@ -1,141 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.KVSToRCMigration -{ - using System; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.Migration; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Data; - using Microsoft.ServiceFabric.Data.Collections; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.MigrationConstants; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.MigrationUtility; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.PhaseInput; - using static Microsoft.ServiceFabric.Actors.Migration.PhaseResult; - - internal class WorkerBase : IWorker - { - private static readonly string TraceType = typeof(WorkerBase).Name; - private KVStoRCMigrationActorStateProvider stateProvider; - private IReliableDictionary2 metadataDict; - private WorkerInput workerInput; - private string traceId; - - public WorkerBase( - KVStoRCMigrationActorStateProvider stateProvider, - WorkerInput workerInput, - string traceId) - { - this.stateProvider = stateProvider; - this.workerInput = workerInput; - this.metadataDict = this.stateProvider.GetMetadataDictionaryAsync().ConfigureAwait(false).GetAwaiter().GetResult(); - this.traceId = traceId; - } - - public IReliableDictionary2 MetadataDict { get => this.metadataDict; } - - public KVStoRCMigrationActorStateProvider StateProvider { get => this.stateProvider; } - - public WorkerInput Input { get => this.workerInput; } - - public string TraceId { get => this.traceId; } - - public static async Task GetResultAsync( - ActorStateProviderHelper stateProviderHelper, - Func txFactory, - IReliableDictionary2 metadataDict, - MigrationPhase migrationPhase, - int currentIteration, - int workerId, - string traceId, - CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - var status = await ParseMigrationStateAsync( - () => GetValueOrDefaultAsync(stateProviderHelper, txFactory, metadataDict, Key(PhaseWorkerCurrentStatus, migrationPhase, currentIteration, workerId), cancellationToken), - traceId); - - if (status == MigrationState.None) - { - return new WorkerResult - { - Phase = migrationPhase, - Iteration = currentIteration, - WorkerId = workerId, - Status = MigrationState.None, - }; - } - - var workerResult = new WorkerResult - { - Status = status, - Phase = migrationPhase, - Iteration = currentIteration, - WorkerId = workerId, - }; - - workerResult.StartDateTimeUTC = (await ParseDateTimeAsync( - () => GetValueAsync(stateProviderHelper, txFactory, metadataDict, Key(PhaseWorkerStartDateTimeUTC, migrationPhase, currentIteration, workerId), cancellationToken), - traceId)).Value; - - workerResult.EndDateTimeUTC = await ParseDateTimeAsync( - () => GetValueOrDefaultAsync(stateProviderHelper, txFactory, metadataDict, Key(PhaseWorkerEndDateTimeUTC, migrationPhase, currentIteration, workerId), cancellationToken), - traceId); - - workerResult.StartSeqNum = (await ParseLongAsync( - () => GetValueAsync(stateProviderHelper, txFactory, metadataDict, Key(PhaseWorkerStartSeqNum, migrationPhase, currentIteration, workerId), cancellationToken), - traceId)).Value; - - workerResult.EndSeqNum = (await ParseLongAsync( - () => GetValueAsync(stateProviderHelper, txFactory, metadataDict, Key(PhaseWorkerEndSeqNum, migrationPhase, currentIteration, workerId), cancellationToken), - traceId)).Value; - - workerResult.LastAppliedSeqNum = await ParseLongAsync( - () => GetValueOrDefaultAsync(stateProviderHelper, txFactory, metadataDict, Key(PhaseWorkerLastAppliedSeqNum, migrationPhase, currentIteration, workerId), cancellationToken), - traceId); - - workerResult.NoOfKeysMigrated = await ParseLongAsync( - () => GetValueOrDefaultAsync(stateProviderHelper, txFactory, metadataDict, Key(PhaseWorkerNoOfKeysMigrated, migrationPhase, currentIteration, workerId), cancellationToken), - traceId); - - return workerResult; - } - - public virtual Task StartWorkAsync(CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - - protected async Task CompleteWorkerAsync(ITransaction tx, CancellationToken cancellationToken) - { - await this.metadataDict.AddOrUpdateAsync( - tx, - Key(PhaseWorkerLastAppliedSeqNum, this.Input.Phase, this.Input.Iteration, this.Input.WorkerId), - this.workerInput.EndSeqNum.ToString(), - (_, __) => this.workerInput.EndSeqNum.ToString(), - DefaultRCTimeout, - cancellationToken); - - await this.metadataDict.AddOrUpdateAsync( - tx, - Key(PhaseWorkerCurrentStatus, this.Input.Phase, this.Input.Iteration, this.Input.WorkerId), - MigrationState.Completed.ToString(), - (_, __) => MigrationState.Completed.ToString(), - DefaultRCTimeout, - cancellationToken); - - await this.metadataDict.AddOrUpdateAsync( - tx, - Key(PhaseWorkerEndDateTimeUTC, this.Input.Phase, this.Input.Iteration, this.Input.WorkerId), - DateTime.UtcNow.ToString(), - (_, v) => v, - DefaultRCTimeout, - cancellationToken); - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Friend.cs b/src/Microsoft.ServiceFabric.Actors/Friend.cs index 6051413b..e985beec 100644 --- a/src/Microsoft.ServiceFabric.Actors/Friend.cs +++ b/src/Microsoft.ServiceFabric.Actors/Friend.cs @@ -14,10 +14,3 @@ [assembly: InternalsVisibleTo("BackupRestoreActorService,PublicKey=00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0")] [assembly: InternalsVisibleTo("PresenceLoadDriverLib,PublicKey=00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0")] [assembly: InternalsVisibleTo("EventsValidationTest, PublicKey=00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0")] -[assembly: InternalsVisibleTo("Microsoft.ServiceFabric.Actors.KVSToRCMigration, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: InternalsVisibleTo("ActorMigrationTestKvsActorService,PublicKey=00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0")] -[assembly: InternalsVisibleTo("ActorMigrationTestRcActorService,PublicKey=00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0")] -[assembly: InternalsVisibleTo("ActorMigrationTestKvsActorService,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: InternalsVisibleTo("ActorMigrationTestRcActorService,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: InternalsVisibleTo("Microsoft.ServiceFabric.Actors.StateMigration.Tests,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: InternalsVisibleTo("Microsoft.ServiceFabric.Actors.StateMigration.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0")] diff --git a/src/Microsoft.ServiceFabric.Services.Remoting/Friend.cs b/src/Microsoft.ServiceFabric.Services.Remoting/Friend.cs index cd1cdc70..7f16a9f0 100644 --- a/src/Microsoft.ServiceFabric.Services.Remoting/Friend.cs +++ b/src/Microsoft.ServiceFabric.Services.Remoting/Friend.cs @@ -19,4 +19,3 @@ [assembly: InternalsVisibleTo("Microsoft.ServiceFabric.Services.Remoting.Tests,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo("Microsoft.ServiceFabric.Actors.Tests,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo("Microsoft.ServiceFabric.Actors.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0")] -[assembly: InternalsVisibleTo("Microsoft.ServiceFabric.Actors.KVSToRCMigration, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] diff --git a/src/Microsoft.ServiceFabric.Services/Friend.cs b/src/Microsoft.ServiceFabric.Services/Friend.cs index c3636dff..f37646f6 100644 --- a/src/Microsoft.ServiceFabric.Services/Friend.cs +++ b/src/Microsoft.ServiceFabric.Services/Friend.cs @@ -16,6 +16,3 @@ [assembly: InternalsVisibleTo("FabActTest.ClientWorkload, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: InternalsVisibleTo("FabSrvStateManager.Test, PublicKey=00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0")] [assembly: InternalsVisibleTo("EventsValidationTest, PublicKey=00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0")] -[assembly: InternalsVisibleTo("Microsoft.ServiceFabric.Actors.KVSToRCMigration, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: InternalsVisibleTo("Microsoft.ServiceFabric.Actors.StateMigration.Tests,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: InternalsVisibleTo("Microsoft.ServiceFabric.Actors.StateMigration.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0")] diff --git a/src/netstandard/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Microsoft.ServiceFabric.Actors.KVSToRCMigration_netstandard.csproj b/src/netstandard/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Microsoft.ServiceFabric.Actors.KVSToRCMigration_netstandard.csproj deleted file mode 100644 index 2932e57f..00000000 --- a/src/netstandard/Microsoft.ServiceFabric.Actors.KVSToRCMigration/Microsoft.ServiceFabric.Actors.KVSToRCMigration_netstandard.csproj +++ /dev/null @@ -1,36 +0,0 @@ - - - - Microsoft.ServiceFabric.Actors.KVSToRCMigration Library - Microsoft.ServiceFabric.Actors.KVSToRCMigration - $(AssemblyName) - $(RepoRoot)src\Microsoft.ServiceFabric.Actors.KVSToRCMigration\ - netstandard2.0 - $(OutputPath)\$(AssemblyName).xml - false - true - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/AmbiguousActorIdTest.cs b/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/AmbiguousActorIdTest.cs deleted file mode 100644 index 6bcf4f4b..00000000 --- a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/AmbiguousActorIdTest.cs +++ /dev/null @@ -1,100 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.StateMigration.Tests -{ - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration; - using Microsoft.ServiceFabric.Actors.Migration.Exceptions; - using Microsoft.ServiceFabric.Actors.Runtime.Migration; - using Microsoft.ServiceFabric.Actors.StateMigration.Tests.MockTypes; - using Xunit; - using static Microsoft.ServiceFabric.Actors.KVSToRCMigration.IAmbiguousActorIdHandler; - - /// - /// Ambiguous actor id tests. - /// - public class AmbiguousActorIdTest - { - /// - /// Test non ambiguous actors scenario. - /// - /// Task for async operation. - [Fact] - public async Task NonAmbiguousActorIds() - { - var sp = new MockReliableCollectionsStateProvider(); - var presenceDict = sp.GetActorPresenceDictionary(); - await presenceDict.AddAsync(null, "String_MyActor1_", new byte[0]); - await presenceDict.AddAsync(null, "String_MyActor2_", new byte[0]); - await presenceDict.AddAsync(null, "String_MyActor3_MyEx1_", new byte[0]); - await presenceDict.AddAsync(null, "String_MyActor4_MyEx1_MyEx2_", new byte[0]); - - var handler = new RCAmbiguousActorIdHandler(sp); - Assert.Equal(await handler.ResolveActorIdAsync("String_MyActor1_MyState1", null, CancellationToken.None), new ActorId("MyActor1")); - Assert.Equal(await handler.ResolveActorIdAsync("String_MyActor3_MyEx1_MyState1", null, CancellationToken.None), new ActorId("MyActor3_MyEx1")); - Assert.Equal(await handler.ResolveActorIdAsync("Long_1234_MyState", null, CancellationToken.None), new ActorId(1234)); - } - - /// - /// Test ambiguous actors scenario. - /// - /// Task for async operation. - [Fact] - public async Task AmbiguousActorIds() - { - var sp = new MockReliableCollectionsStateProvider(); - var presenceDict = sp.GetActorPresenceDictionary(); - await presenceDict.AddAsync(null, "String_MyActor1_", new byte[0]); - await presenceDict.AddAsync(null, "String_MyActor1_MyEx1_", new byte[0]); - - var handler = new RCAmbiguousActorIdHandler(sp); - await Assert.ThrowsAsync(() => handler.ResolveActorIdAsync("String_MyActor1_MyEx1_MyState1", null, CancellationToken.None)); - } - - /// - /// Test ambiguous actors scenario with resolvers - /// - /// Task for async operation. - // [Fact] - internal async Task AmbiguousActorIdsWithResolvers() - { - var sp = new MockReliableCollectionsStateProvider(); - var presenceDict = sp.GetActorPresenceDictionary(); - await presenceDict.AddAsync(null, "String_MyActor1_", new byte[0]); - await presenceDict.AddAsync(null, "String_MyActor1_MyEx1_", new byte[0]); - - var handler = new RCAmbiguousActorIdHandler(sp); - Assert.Equal(await handler.ResolveActorIdAsync("String_MyActor1_MyEx1_MyState1", null, CancellationToken.None), new ActorId("MyActor1_MyEx1")); - } - - /// - /// Actor Id resolver - /// - [AmbiguousActorIdResolverAttribute] - public class ActorIdResolver : IAmbiguousActorIdHandler - { - /// - public Task TryResolveActorIdAsync(string stateStorageKey, CancellationToken cancellationToken) - { - if (stateStorageKey == "MyActor1_MyEx1_MyState1") - { - return Task.FromResult(new ConditionalValue - { - HasValue = true, - Value = "MyActor1_MyEx1", - }); - } - - return Task.FromResult(new ConditionalValue - { - HasValue = false, - Value = null, - }); - } - } - } -} diff --git a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/Microsoft.ServiceFabric.Actors.StateMigration.Tests.csproj b/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/Microsoft.ServiceFabric.Actors.StateMigration.Tests.csproj deleted file mode 100644 index 9a5b74e5..00000000 --- a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/Microsoft.ServiceFabric.Actors.StateMigration.Tests.csproj +++ /dev/null @@ -1,27 +0,0 @@ - - - - - {1BDC4681-FDBA-4E55-A247-5F779627A4D7} - Microsoft.ServiceFabric.Actors.StateMigration.Tests - $(AssemblyName) - net6.0 - $(OutputPath)\$(AssemblyName).xml - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - diff --git a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MigrationActorStateProviderTests.cs b/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MigrationActorStateProviderTests.cs deleted file mode 100644 index cbfb078d..00000000 --- a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MigrationActorStateProviderTests.cs +++ /dev/null @@ -1,279 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.StateMigration.Tests -{ - using System; - using System.Collections.Generic; - using System.Globalization; - using System.IO; - using System.Runtime.Serialization; - using System.Text; - using System.Threading; - using System.Threading.Tasks; - using System.Xml; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Services; - using Xunit; - - /// - /// Migration state provider tests. - /// - public class MigrationActorStateProviderTests - { - private DataContractSerializer reminderSerializer = new DataContractSerializer(typeof(ActorReminderData)); - private DataContractSerializer reminderCompletedDataSerializer = new DataContractSerializer(typeof(ReminderCompletedData)); - - /// - /// Save state test. - /// - /// Task to represent asynchronous operation. - [Fact] - public async Task SaveStateTypesTest() - { - var migrationSP = new KVStoRCMigrationActorStateProvider(new MockTypes.MockReliableCollectionsStateProvider()); - - var stateSerializer = new ActorStateProviderSerializer(); - var kvsData = new List(); - - int j = 0; - for (int i = 0; i < 10; i++) - { - kvsData.Add(new KVSToRCMigration.Models.KeyValuePair() - { - IsDeleted = false, - Key = $"@@_String_Actor{i}", - Value = new byte[0], - Version = i + j++, - }); - - kvsData.Add(new KVSToRCMigration.Models.KeyValuePair() - { - IsDeleted = false, - Key = $"Actor_String_Actor{i}_State{0}", - Value = stateSerializer.Serialize(typeof(string), $"Value{0}"), - Version = i + j++, - }); - - kvsData.Add(new KVSToRCMigration.Models.KeyValuePair() - { - IsDeleted = false, - Key = $"Actor_String_Actor{i}_State{1}", - Value = stateSerializer.Serialize(typeof(long), 1), - Version = i + j++, - }); - - kvsData.Add(new KVSToRCMigration.Models.KeyValuePair() - { - IsDeleted = false, - Key = $"Actor_String_Actor{i}_State{2}", - Value = stateSerializer.Serialize(typeof(Guid), Guid.NewGuid()), - Version = i + j++, - }); - - kvsData.Add(new KVSToRCMigration.Models.KeyValuePair() - { - IsDeleted = false, - Key = $"Actor_String_Actor{i}_State{3}", - Value = stateSerializer.Serialize(typeof(byte[]), Encoding.UTF8.GetBytes("ValueString")), - Version = i + j++, - }); - - kvsData.Add(new KVSToRCMigration.Models.KeyValuePair() - { - IsDeleted = false, - Key = $"Actor_String_Actor{i}_State{4}", - Value = stateSerializer.Serialize(typeof(double), 12354.1234), - Version = i + j++, - }); - - kvsData.Add(new KVSToRCMigration.Models.KeyValuePair() - { - IsDeleted = false, - Key = $"Reminder_String_Actor{i}_Reminder{i}", - Value = Serialize( - this.reminderSerializer, - new ActorReminderData( - new ActorId($"Actor{i}"), - $"Reminder{i}", - TimeSpan.FromSeconds(10), - TimeSpan.FromSeconds(10), - Encoding.UTF8.GetBytes("ReminderState"), - TimeSpan.Zero)), - Version = i + j++, - }); - - kvsData.Add(new KVSToRCMigration.Models.KeyValuePair() - { - IsDeleted = false, - Key = $"RC@@_String_Actor{i}_Reminder{i}", - Value = Serialize(this.reminderCompletedDataSerializer, new ReminderCompletedData(TimeSpan.Zero, DateTime.UtcNow)), - Version = i + j++, - }); - - kvsData.Add(new KVSToRCMigration.Models.KeyValuePair() - { - IsDeleted = false, - Key = $"Actor_String_Actor{i}_StateComplexObject", - Value = stateSerializer.Serialize(typeof(MigrationSettings), new MigrationSettings - { - ChunksPerEnumeration = 10, - CopyPhaseParallelism = 2, - DowntimeThreshold = 100, - EnableDataIntegrityChecks = true, - MigrationMode = Runtime.Migration.MigrationMode.Auto, - TargetServiceUri = new Uri("fabric:/blah/blahblah"), - }), - Version = i + j++, - }); - } - - var valueList = new List(); - foreach (var data in kvsData) - { - valueList.Add(data.Value); - } - - var sourceCRC = CRC64.ToCRC64(valueList.ToArray()); - - Assert.Equal(await migrationSP.SaveStateAsync(kvsData, CancellationToken.None), kvsData.Count); - await migrationSP.ValidateDataPostMigrationAsync(kvsData, sourceCRC.ToString("X", CultureInfo.InvariantCulture), true, CancellationToken.None); - } - - /// - /// Ignore keys test. - /// - /// Task to represent asynchronous operation. - [Fact] - public async Task IgnoreKeysTest() - { - var migrationSP = new KVStoRCMigrationActorStateProvider(new MockTypes.MockReliableCollectionsStateProvider()); - - var stateSerializer = new ActorStateProviderSerializer(); - var kvsData = new List(); - - int j = 0; - for (int i = 0; i < 1; i++) - { - kvsData.Add(new KVSToRCMigration.Models.KeyValuePair() - { - IsDeleted = false, - Key = MigrationConstants.RejectWritesKey, - Value = new byte[0], - Version = i + j++, - }); - - kvsData.Add(new KVSToRCMigration.Models.KeyValuePair() - { - IsDeleted = false, - Key = MigrationConstants.LogicalTimestampKey, - Value = stateSerializer.Serialize(typeof(TimeSpan), TimeSpan.FromSeconds(10)), - Version = i + j++, - }); - } - - var valueList = new List(); - var sourceCRC = CRC64.ToCRC64(valueList.ToArray()); - - Assert.Equal(0L, await migrationSP.SaveStateAsync(kvsData, CancellationToken.None)); - await migrationSP.ValidateDataPostMigrationAsync(kvsData, sourceCRC.ToString("X", CultureInfo.InvariantCulture), true, CancellationToken.None); - } - - /// - /// Deleted test. - /// - /// Task to represent asynchronous operation. - [Fact] - public async Task DeletedKeysTest() - { - var migrationSP = new KVStoRCMigrationActorStateProvider(new MockTypes.MockReliableCollectionsStateProvider()); - - var stateSerializer = new ActorStateProviderSerializer(); - var kvsData = new List(); - - int j = 0; - for (int i = 0; i < 10; i++) - { - kvsData.Add(new KVSToRCMigration.Models.KeyValuePair() - { - IsDeleted = false, - Key = $"@@_String_Actor{i}", - Value = new byte[0], - Version = i + j++, - }); - } - - Assert.Equal(await migrationSP.SaveStateAsync(kvsData, CancellationToken.None), kvsData.Count); - - kvsData = new List(); - kvsData.Add(new KVSToRCMigration.Models.KeyValuePair() - { - IsDeleted = true, - Key = $"@@_String_Actor2", - Value = new byte[0], - Version = 1000, - }); - - kvsData.Add(new KVSToRCMigration.Models.KeyValuePair() - { - IsDeleted = true, - Key = $"@@_String_Actor5", - Value = new byte[0], - Version = 1001, - }); - - var valueList = new List(); - var sourceCRC = CRC64.ToCRC64(valueList.ToArray()); - Assert.Equal(2, await migrationSP.SaveStateAsync(kvsData, CancellationToken.None)); - - await migrationSP.ValidateDataPostMigrationAsync(kvsData, sourceCRC.ToString("X", CultureInfo.InvariantCulture), true, CancellationToken.None); - } - - /// - /// Data validation failure test. - /// - /// Task to represent asynchronous operation. - [Fact] - public async Task DataValidationFailureTest() - { - var migrationSP = new KVStoRCMigrationActorStateProvider(new MockTypes.MockReliableCollectionsStateProvider()); - - var stateSerializer = new ActorStateProviderSerializer(); - var kvsData = new List(); - - int j = 0; - for (int i = 0; i < 10; i++) - { - kvsData.Add(new KVSToRCMigration.Models.KeyValuePair() - { - IsDeleted = false, - Key = $"@@_String_Actor{i}", - Value = new byte[0], - Version = i + j++, - }); - } - - await Assert.ThrowsAsync(() => migrationSP.ValidateDataPostMigrationAsync(kvsData, string.Empty, true, CancellationToken.None)); - Assert.Equal(await migrationSP.SaveStateAsync(kvsData, CancellationToken.None), kvsData.Count); - kvsData[0].IsDeleted = true; - await Assert.ThrowsAsync(() => migrationSP.ValidateDataPostMigrationAsync(kvsData, string.Empty, true, CancellationToken.None)); - kvsData[0].IsDeleted = false; - await Assert.ThrowsAsync(() => migrationSP.ValidateDataPostMigrationAsync(kvsData, "BLAH", true, CancellationToken.None)); - } - - private static byte[] Serialize(DataContractSerializer serializer, T data) - { - using (var memoryStream = new MemoryStream()) - { - var binaryWriter = XmlDictionaryWriter.CreateBinaryWriter(memoryStream); - serializer.WriteObject(binaryWriter, data); - binaryWriter.Flush(); - - return memoryStream.ToArray(); - } - } - } -} diff --git a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MigrationSettingsTest.cs b/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MigrationSettingsTest.cs deleted file mode 100644 index 85c5f3b2..00000000 --- a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MigrationSettingsTest.cs +++ /dev/null @@ -1,52 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.StateMigration.Tests -{ - using System; - using System.Globalization; - using Microsoft.ServiceFabric.Actors; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration; - using Microsoft.ServiceFabric.Actors.Migration.Exceptions; - using Xunit; - - /// - /// Migration Settings tests. - /// - public class MigrationSettingsTest - { - /// - /// Tests two actor ids for null equality. - /// - [Fact] - public void TestMigrationSettings() - { - var tgtSettings = new MigrationSettings - { - ChunksPerEnumeration = 10, - CopyPhaseParallelism = 2, - DowntimeThreshold = 1000, - KeyValuePairsPerChunk = 100, - MigrationMode = Runtime.Migration.MigrationMode.Auto, - TargetServiceUri = new Uri("fabric:/MyApp/MySourceSvc"), - SourceServiceUri = new Uri("fabric:/MyApp/MyTargetSvc"), - }; - - tgtSettings.Validate(isSource: false); - - tgtSettings.SourceServiceUri = null; - Assert.Throws(() => tgtSettings.Validate(isSource: false)); - - var sourceSettings = new MigrationSettings - { - TargetServiceUri = new Uri("fabric:/MyApp/MyTargetSvc"), - }; - - sourceSettings.Validate(isSource: true); - sourceSettings.TargetServiceUri = new Uri("//blah"); - Assert.Throws(() => sourceSettings.Validate(isSource: true)); - } - } -} diff --git a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MigrationWorkerTests.cs b/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MigrationWorkerTests.cs deleted file mode 100644 index 89aae998..00000000 --- a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MigrationWorkerTests.cs +++ /dev/null @@ -1,81 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.StateMigration.Tests -{ - using System; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration; - using Microsoft.ServiceFabric.Actors.StateMigration.Tests.MockTypes; - using Xunit; - - /// - /// Migration Worker Tests - /// - public class MigrationWorkerTests - { - /// - /// Worker test. - /// - /// A representing the asynchronous unit test. - [Fact] - public async Task StartWorkTest() - { - var worker = new MigrationWorker( - new MockKVStoRCMigrationActorStateProvider(new MockReliableCollectionsStateProvider()), - new Runtime.ActorTypeInformation(), - new MockServicePartitionClient(null, new Uri("fabric:/Blah/BlahBlah")), - new MigrationSettings - { - ChunksPerEnumeration = 10, - KeyValuePairsPerChunk = 100, - SourceServiceUri = new Uri("fabric:/blah/blahblah"), - }, - new PhaseInput.WorkerInput - { - StartSeqNum = 0, - EndSeqNum = 100, - Iteration = 1, - WorkerId = 1, - Phase = Migration.MigrationPhase.Copy, - Status = Migration.MigrationState.InProgress, - StartDateTimeUTC = DateTime.UtcNow, - }, - "TestTrace"); - await this.PersistInputAsync(worker); - var result = await worker.StartWorkAsync(CancellationToken.None); - - Assert.NotEqual(default(DateTime), result.StartDateTimeUTC); - Assert.NotEqual(default(DateTime), result.EndDateTimeUTC); - Assert.Equal(result.StartSeqNum, worker.Input.StartSeqNum); - Assert.Equal(result.EndSeqNum, worker.Input.EndSeqNum); - Assert.Equal(MockServicePartitionClient.EnumerationSize, result.LastAppliedSeqNum); - Assert.Equal(result.Phase, worker.Input.Phase); - Assert.Equal(Migration.MigrationState.Completed, result.Status); - } - - private async Task PersistInputAsync(MigrationWorker worker) - { - var metaDict = await worker.StateProvider.GetMetadataDictionaryAsync(); - await metaDict.AddAsync( - worker.StateProvider.GetStateManager().CreateTransaction(), - MigrationConstants.Key(MigrationConstants.PhaseWorkerStartDateTimeUTC, worker.Input.Phase, worker.Input.Iteration, worker.Input.WorkerId), - worker.Input.StartDateTimeUTC.ToString()); - await metaDict.AddAsync( - worker.StateProvider.GetStateManager().CreateTransaction(), - MigrationConstants.Key(MigrationConstants.PhaseWorkerStartSeqNum, worker.Input.Phase, worker.Input.Iteration, worker.Input.WorkerId), - worker.Input.StartSeqNum.ToString()); - await metaDict.AddAsync( - worker.StateProvider.GetStateManager().CreateTransaction(), - MigrationConstants.Key(MigrationConstants.PhaseWorkerEndSeqNum, worker.Input.Phase, worker.Input.Iteration, worker.Input.WorkerId), - worker.Input.EndSeqNum.ToString()); - await metaDict.AddAsync( - worker.StateProvider.GetStateManager().CreateTransaction(), - MigrationConstants.Key(MigrationConstants.PhaseWorkerCurrentStatus, worker.Input.Phase, worker.Input.Iteration, worker.Input.WorkerId), - worker.Input.Status.ToString()); - } - } -} diff --git a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MockTypes/MockKVStoRCMigrationActorStateProvider.cs b/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MockTypes/MockKVStoRCMigrationActorStateProvider.cs deleted file mode 100644 index 1e87680b..00000000 --- a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MockTypes/MockKVStoRCMigrationActorStateProvider.cs +++ /dev/null @@ -1,40 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.StateMigration.Tests.MockTypes -{ - using System.Collections.Generic; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Data.Collections; - - internal class MockKVStoRCMigrationActorStateProvider : KVStoRCMigrationActorStateProvider - { - private IReliableDictionary2 metaDict; - - public MockKVStoRCMigrationActorStateProvider(IReliableCollectionsActorStateProviderInternal reliableCollectionsActorStateProvider) - : base(reliableCollectionsActorStateProvider) - { - this.metaDict = new MockReliableDictionary(); - } - - public override Task SaveStateAsync(List kvsData, CancellationToken cancellationToken, bool skipPresenceDictResolve = false) - { - return Task.FromResult((long)kvsData.Count); - } - - internal override Task ValidateDataPostMigrationAsync(List kvsData, string hashToCompare, bool skipPresenceDictResolve, CancellationToken cancellationToken) - { - return Task.CompletedTask; - } - - internal override Task> GetMetadataDictionaryAsync() - { - return Task.FromResult(this.metaDict); - } - } -} diff --git a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MockTypes/MockReliableCollectionsStateProvider.cs b/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MockTypes/MockReliableCollectionsStateProvider.cs deleted file mode 100644 index 2b1a4466..00000000 --- a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MockTypes/MockReliableCollectionsStateProvider.cs +++ /dev/null @@ -1,205 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.StateMigration.Tests.MockTypes -{ - using System; - using System.Collections.Generic; - using System.Fabric; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors; - using Microsoft.ServiceFabric.Actors.Query; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Data; - using Microsoft.ServiceFabric.Data.Collections; - using Moq; - - internal class MockReliableCollectionsStateProvider : - IActorStateProvider, IActorStateProviderInternal, IReliableCollectionsActorStateProviderInternal - { - private IReliableDictionary2 presenceDict = new MockReliableDictionary(); - private IReliableDictionary2 stateDict = new MockReliableDictionary(); - private IReliableDictionary2 reminderDict = new MockReliableDictionary(); - private IReliableDictionary2 reminderCompletedDict = new MockReliableDictionary(); - private IReliableDictionary2 logicalTimeDict = new MockReliableDictionary(); - - public Func OnRestoreCompletedAsync { set => throw new NotImplementedException(); } - - public Func> OnDataLossAsync { set => throw new NotImplementedException(); } - - public string TraceType { get => "MockReliableCollectionsStateProvider"; } - - public string TraceId { get => "MockReliableCollectionsStateProvider"; } - - public ReplicaRole CurrentReplicaRole { get => ReplicaRole.Primary; } - - public TimeSpan TransientErrorRetryDelay { get => TimeSpan.FromSeconds(1); } - - public TimeSpan OperationTimeout { get => TimeSpan.FromSeconds(10); } - - public TimeSpan CurrentLogicalTime { get => TimeSpan.FromSeconds(1); } - - public long RoleChangeTracker { get => 0L; } - - public void Abort() - { - throw new NotImplementedException(); - } - - public Task ActorActivatedAsync(ActorId actorId, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public Task BackupAsync(Func> backupCallback) - { - throw new NotImplementedException(); - } - - public Task BackupAsync(BackupOption option, TimeSpan timeout, CancellationToken cancellationToken, Func> backupCallback) - { - throw new NotImplementedException(); - } - - public Task ChangeRoleAsync(ReplicaRole newRole, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - - public Task CloseAsync(CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - - public Task ContainsStateAsync(ActorId actorId, string stateName, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public Task DeleteReminderAsync(ActorId actorId, string reminderName, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public Task DeleteRemindersAsync(IReadOnlyDictionary> reminderNames, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public Task> EnumerateStateNamesAsync(ActorId actorId, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public IReliableDictionary2 GetActorPresenceDictionary() - { - return this.presenceDict; - } - - public Task> GetActorsAsync(int numItemsToReturn, ContinuationToken continuationToken, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - - public IReliableDictionary2 GetActorStateDictionary(ActorId actorId) - { - return this.stateDict; - } - - public ActorStateProviderHelper GetActorStateProviderHelper() - { - return new ActorStateProviderHelper(this); - } - - public IReliableDictionary2 GetLogicalTimeDictionary() - { - return this.logicalTimeDict; - } - - public IReliableDictionary2 GetReminderCompletedDictionary() - { - return this.reminderCompletedDict; - } - - public IReliableDictionary2 GetReminderDictionary(ActorId actorId) - { - return this.reminderDict; - } - - public Task>>> GetRemindersAsync(int numItemsToReturn, ActorId actorId, ContinuationToken continuationToken, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - - public IReliableStateManagerReplica2 GetStateManager() - { - var mockSM = new Mock(); - mockSM.Setup(sm => sm.CreateTransaction()).Returns(() => - { - var mockTx = new Mock(); - mockTx.Setup(tx => tx.CommitAsync()).Returns(Task.CompletedTask); - return mockTx.Object; - }); - - return mockSM.Object; - } - - public void Initialize(ActorTypeInformation actorTypeInformation) - { - throw new NotImplementedException(); - } - - public void Initialize(StatefulServiceInitializationParameters initializationParameters) - { - throw new NotImplementedException(); - } - - public Task LoadRemindersAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public Task LoadStateAsync(ActorId actorId, string stateName, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public Task OpenAsync(ReplicaOpenMode openMode, IStatefulServicePartition partition, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - - public Task ReminderCallbackCompletedAsync(ActorId actorId, IActorReminder reminder, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public Task RemoveActorAsync(ActorId actorId, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public Task RestoreAsync(string backupFolderPath) - { - throw new NotImplementedException(); - } - - public Task RestoreAsync(string backupFolderPath, RestorePolicy restorePolicy, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - - public Task SaveReminderAsync(ActorId actorId, IActorReminder reminder, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public Task SaveStateAsync(ActorId actorId, IReadOnlyCollection stateChanges, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - } -} diff --git a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MockTypes/MockReliableDictionary.cs b/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MockTypes/MockReliableDictionary.cs deleted file mode 100644 index ce3ea381..00000000 --- a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MockTypes/MockReliableDictionary.cs +++ /dev/null @@ -1,342 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.StateMigration.Tests.MockTypes -{ - using System; - using System.Collections.Generic; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Data; - using Microsoft.ServiceFabric.Data.Collections; - using Microsoft.ServiceFabric.Data.Notifications; - - internal class MockReliableDictionary : IReliableDictionary2 - where TKey : IComparable, IEquatable - { - private Dictionary kvPairs; - - public MockReliableDictionary() - { - this.kvPairs = new Dictionary(); - } - - event EventHandler> IReliableDictionary.DictionaryChanged - { - add - { - throw new NotImplementedException(); - } - - remove - { - throw new NotImplementedException(); - } - } - - long IReliableDictionary2.Count { get => this.kvPairs.Count; } - - Func, NotifyDictionaryRebuildEventArgs, Task> IReliableDictionary.RebuildNotificationAsyncCallback { set => throw new NotImplementedException(); } - - Uri IReliableState.Name { get => throw new NotImplementedException(); } - - Task IReliableDictionary.AddAsync(ITransaction tx, TKey key, TValue value) - { - return Task.Run(() => this.kvPairs.Add(key, value)); - } - - Task IReliableDictionary.AddAsync(ITransaction tx, TKey key, TValue value, TimeSpan timeout, CancellationToken cancellationToken) - { - return Task.Run(() => this.kvPairs.Add(key, value)); - } - - Task IReliableDictionary.AddOrUpdateAsync(ITransaction tx, TKey key, Func addValueFactory, Func updateValueFactory) - { - return Task.Run(() => - { - if (this.kvPairs.ContainsKey(key)) - { - this.kvPairs[key] = updateValueFactory.Invoke(key, this.kvPairs[key]); - } - else - { - this.kvPairs.Add(key, addValueFactory.Invoke(key)); - } - - return this.kvPairs[key]; - }); - } - - Task IReliableDictionary.AddOrUpdateAsync(ITransaction tx, TKey key, TValue addValue, Func updateValueFactory) - { - return Task.Run(() => - { - if (this.kvPairs.ContainsKey(key)) - { - this.kvPairs[key] = updateValueFactory.Invoke(key, this.kvPairs[key]); - } - else - { - this.kvPairs.Add(key, addValue); - } - - return this.kvPairs[key]; - }); - } - - Task IReliableDictionary.AddOrUpdateAsync(ITransaction tx, TKey key, Func addValueFactory, Func updateValueFactory, TimeSpan timeout, CancellationToken cancellationToken) - { - return Task.Run(() => - { - if (this.kvPairs.ContainsKey(key)) - { - this.kvPairs[key] = updateValueFactory.Invoke(key, this.kvPairs[key]); - } - else - { - this.kvPairs.Add(key, addValueFactory.Invoke(key)); - } - - return this.kvPairs[key]; - }); - } - - Task IReliableDictionary.AddOrUpdateAsync(ITransaction tx, TKey key, TValue addValue, Func updateValueFactory, TimeSpan timeout, CancellationToken cancellationToken) - { - return Task.Run(() => - { - if (this.kvPairs.ContainsKey(key)) - { - this.kvPairs[key] = updateValueFactory.Invoke(key, this.kvPairs[key]); - } - else - { - this.kvPairs.Add(key, addValue); - } - - return this.kvPairs[key]; - }); - } - - Task IReliableDictionary.ClearAsync(TimeSpan timeout, CancellationToken cancellationToken) - { - this.kvPairs.Clear(); - return Task.CompletedTask; - } - - Task IReliableCollection>.ClearAsync() - { - this.kvPairs.Clear(); - return Task.CompletedTask; - } - - Task IReliableDictionary.ContainsKeyAsync(ITransaction tx, TKey key) - { - return Task.FromResult(this.kvPairs.ContainsKey(key)); - } - - Task IReliableDictionary.ContainsKeyAsync(ITransaction tx, TKey key, LockMode lockMode) - { - return Task.FromResult(this.kvPairs.ContainsKey(key)); - } - - Task IReliableDictionary.ContainsKeyAsync(ITransaction tx, TKey key, TimeSpan timeout, CancellationToken cancellationToken) - { - return Task.FromResult(this.kvPairs.ContainsKey(key)); - } - - Task IReliableDictionary.ContainsKeyAsync(ITransaction tx, TKey key, LockMode lockMode, TimeSpan timeout, CancellationToken cancellationToken) - { - return Task.FromResult(this.kvPairs.ContainsKey(key)); - } - - Task>> IReliableDictionary.CreateEnumerableAsync(ITransaction txn) - { - throw new NotImplementedException(); - } - - Task>> IReliableDictionary.CreateEnumerableAsync(ITransaction txn, EnumerationMode enumerationMode) - { - throw new NotImplementedException(); - } - - Task>> IReliableDictionary.CreateEnumerableAsync(ITransaction txn, Func filter, EnumerationMode enumerationMode) - { - throw new NotImplementedException(); - } - - Task> IReliableDictionary2.CreateKeyEnumerableAsync(ITransaction txn) - { - throw new NotImplementedException(); - } - - Task> IReliableDictionary2.CreateKeyEnumerableAsync(ITransaction txn, EnumerationMode enumerationMode) - { - throw new NotImplementedException(); - } - - Task> IReliableDictionary2.CreateKeyEnumerableAsync(ITransaction txn, EnumerationMode enumerationMode, TimeSpan timeout, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - - Task IReliableCollection>.GetCountAsync(ITransaction tx) - { - return Task.FromResult((long)this.kvPairs.Count); - } - - Task IReliableDictionary.GetOrAddAsync(ITransaction tx, TKey key, Func valueFactory) - { - if (!this.kvPairs.ContainsKey(key)) - { - this.kvPairs.Add(key, valueFactory.Invoke(key)); - } - - return Task.FromResult(this.kvPairs[key]); - } - - Task IReliableDictionary.GetOrAddAsync(ITransaction tx, TKey key, TValue value) - { - if (!this.kvPairs.ContainsKey(key)) - { - this.kvPairs.Add(key, value); - } - - return Task.FromResult(this.kvPairs[key]); - } - - Task IReliableDictionary.GetOrAddAsync(ITransaction tx, TKey key, Func valueFactory, TimeSpan timeout, CancellationToken cancellationToken) - { - if (!this.kvPairs.ContainsKey(key)) - { - this.kvPairs.Add(key, valueFactory.Invoke(key)); - } - - return Task.FromResult(this.kvPairs[key]); - } - - Task IReliableDictionary.GetOrAddAsync(ITransaction tx, TKey key, TValue value, TimeSpan timeout, CancellationToken cancellationToken) - { - if (!this.kvPairs.ContainsKey(key)) - { - this.kvPairs.Add(key, value); - } - - return Task.FromResult(this.kvPairs[key]); - } - - Task IReliableDictionary.SetAsync(ITransaction tx, TKey key, TValue value) - { - this.kvPairs.Add(key, value); - return Task.CompletedTask; - } - - Task IReliableDictionary.SetAsync(ITransaction tx, TKey key, TValue value, TimeSpan timeout, CancellationToken cancellationToken) - { - this.kvPairs.Add(key, value); - return Task.CompletedTask; - } - - Task IReliableDictionary.TryAddAsync(ITransaction tx, TKey key, TValue value) - { - return Task.FromResult(this.kvPairs.TryAdd(key, value)); - } - - Task IReliableDictionary.TryAddAsync(ITransaction tx, TKey key, TValue value, TimeSpan timeout, CancellationToken cancellationToken) - { - return Task.FromResult(this.kvPairs.TryAdd(key, value)); - } - - Task> IReliableDictionary.TryGetValueAsync(ITransaction tx, TKey key) - { - if (this.kvPairs.TryGetValue(key, out var value)) - { - return Task.FromResult(new ConditionalValue(true, value)); - } - - return Task.FromResult(new ConditionalValue(false, default(TValue))); - } - - Task> IReliableDictionary.TryGetValueAsync(ITransaction tx, TKey key, LockMode lockMode) - { - if (this.kvPairs.TryGetValue(key, out var value)) - { - return Task.FromResult(new ConditionalValue(true, value)); - } - - return Task.FromResult(new ConditionalValue(false, default(TValue))); - } - - Task> IReliableDictionary.TryGetValueAsync(ITransaction tx, TKey key, TimeSpan timeout, CancellationToken cancellationToken) - { - if (this.kvPairs.TryGetValue(key, out var value)) - { - return Task.FromResult(new ConditionalValue(true, value)); - } - - return Task.FromResult(new ConditionalValue(false, default(TValue))); - } - - Task> IReliableDictionary.TryGetValueAsync(ITransaction tx, TKey key, LockMode lockMode, TimeSpan timeout, CancellationToken cancellationToken) - { - if (this.kvPairs.TryGetValue(key, out var value)) - { - return Task.FromResult(new ConditionalValue(true, value)); - } - - return Task.FromResult(new ConditionalValue(false, default(TValue))); - } - - Task> IReliableDictionary.TryRemoveAsync(ITransaction tx, TKey key) - { - if (this.kvPairs.Remove(key, out var value)) - { - return Task.FromResult(new ConditionalValue(true, value)); - } - - return Task.FromResult(new ConditionalValue(false, default(TValue))); - } - - Task> IReliableDictionary.TryRemoveAsync(ITransaction tx, TKey key, TimeSpan timeout, CancellationToken cancellationToken) - { - if (this.kvPairs.Remove(key, out var value)) - { - return Task.FromResult(new ConditionalValue(true, value)); - } - - return Task.FromResult(new ConditionalValue(false, default(TValue))); - } - - Task IReliableDictionary.TryUpdateAsync(ITransaction tx, TKey key, TValue newValue, TValue comparisonValue) - { - if (this.kvPairs.TryGetValue(key, out var value)) - { - if (comparisonValue.Equals(value)) - { - this.kvPairs[key] = newValue; - - return Task.FromResult(true); - } - } - - return Task.FromResult(false); - } - - Task IReliableDictionary.TryUpdateAsync(ITransaction tx, TKey key, TValue newValue, TValue comparisonValue, TimeSpan timeout, CancellationToken cancellationToken) - { - if (this.kvPairs.TryGetValue(key, out var value)) - { - if (comparisonValue.Equals(value)) - { - this.kvPairs[key] = newValue; - - return Task.FromResult(true); - } - } - - return Task.FromResult(false); - } - } -} diff --git a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MockTypes/MockServicePartitionClient.cs b/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MockTypes/MockServicePartitionClient.cs deleted file mode 100644 index 05df8def..00000000 --- a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/MockTypes/MockServicePartitionClient.cs +++ /dev/null @@ -1,123 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.StateMigration.Tests.MockTypes -{ - using System; - using System.Collections.Generic; - using System.Net; - using System.Net.Http; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration.Models; - using Microsoft.ServiceFabric.Services.Client; - using Microsoft.ServiceFabric.Services.Communication.Client; - - internal class MockServicePartitionClient : ServicePartitionClient - { - internal static readonly long EnumerationSize = 100; - - public MockServicePartitionClient( - ICommunicationClientFactory communicationClientFactory, - Uri serviceUri, - ServicePartitionKey partitionKey = null, - TargetReplicaSelector targetReplicaSelector = TargetReplicaSelector.Default, - string listenerName = null, - OperationRetrySettings retrySettings = null) - : base(communicationClientFactory, serviceUri, partitionKey, targetReplicaSelector, listenerName, retrySettings) - { - } - - public override Task InvokeWithRetryAsync( - Func> func, - params Type[] doNotRetryExceptionTypes) - { - return this.InvokeWithRetryAsync(func, CancellationToken.None, doNotRetryExceptionTypes); - } - - public override async Task InvokeWithRetryAsync( - Func> func, - CancellationToken cancellationToken, - params Type[] doNotRetryExceptionTypes) - { - return await func.Invoke(this.GetMockCommunicationClient()); - } - - private HttpCommunicationClient GetMockCommunicationClient() - { - return new HttpCommunicationClient(new HttpClient(new MockHttpMessageHandler()) - { - BaseAddress = new Uri("http://testapp:8080/"), - }); - } - - private class MockHttpMessageHandler : HttpMessageHandler - { - protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - var requestUri = request.RequestUri.ToString(); - if (requestUri.EndsWith(MigrationConstants.EnumeratebySNEndpoint)) - { - var kvPairList = new List(); - for (int i = 0; i < EnumerationSize; i++) - { - kvPairList.Add(new KVSToRCMigration.Models.KeyValuePair - { - Version = i, - }); - } - - var response = new EnumerationResponse - { - EndSequenceNumberReached = true, - KeyValuePairs = kvPairList, - }; - - return Task.FromResult(new HttpResponseMessage() - { - StatusCode = HttpStatusCode.OK, - Content = new ByteArrayContent(SerializationUtility.Serialize(KvsActorStateProviderExtensions.ResponseSerializer, response)), - }); - } - else if (requestUri.EndsWith(MigrationConstants.GetStartSNEndpoint)) - { - return Task.FromResult(new HttpResponseMessage() - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(1.ToString()), - }); - } - else if (requestUri.EndsWith(MigrationConstants.GetEndSNEndpoint)) - { - return Task.FromResult(new HttpResponseMessage() - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(100.ToString()), - }); - } - else if (requestUri.EndsWith(MigrationConstants.StartDowntimeEndpoint)) - { - return Task.FromResult(new HttpResponseMessage() - { - StatusCode = HttpStatusCode.OK, - }); - } - else if (requestUri.EndsWith(MigrationConstants.AbortMigrationEndpoint)) - { - return Task.FromResult(new HttpResponseMessage() - { - StatusCode = HttpStatusCode.OK, - }); - } - - return Task.FromResult(new HttpResponseMessage() - { - StatusCode = HttpStatusCode.NotFound, - }); - } - } - } -} diff --git a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/TargetMigrationOrchestratorTests.cs b/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/TargetMigrationOrchestratorTests.cs deleted file mode 100644 index 8aa8adb7..00000000 --- a/test/unittests/Microsoft.ServiceFabric.Actors.StateMigration.Tests/TargetMigrationOrchestratorTests.cs +++ /dev/null @@ -1,641 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.StateMigration.Tests -{ - using System; - using System.Collections.Generic; - using System.Fabric; - using System.Numerics; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.KVSToRCMigration; - using Microsoft.ServiceFabric.Actors.Migration; - using Microsoft.ServiceFabric.Actors.Migration.Exceptions; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Actors.Runtime.Migration; - using Microsoft.ServiceFabric.Actors.StateMigration.Tests.MockTypes; - using Microsoft.ServiceFabric.Services.Communication.Client; - using Moq; - using Xunit; - - /// - /// Target Migration orchestrator tests. - /// - public class TargetMigrationOrchestratorTests - { - /// - /// Auto Migration base case - /// - /// representing the asynchronous unit test. - [Fact] - public async Task AutoMigrationBaseCase() - { - var orchestrator = GetOrchestrator(MigrationMode.Auto); - await orchestrator.StartMigrationAsync(false, CancellationToken.None); - var result = await orchestrator.GetResultAsync(CancellationToken.None); - - Assert.Equal(MigrationPhase.Completed, result.CurrentPhase); - Assert.Equal(MigrationState.Completed, result.Status); - } - - /// - /// Auto Migration failover case - /// - /// representing the asynchronous unit test. - [Fact] - public async Task AutoMigrationFailoverCase() - { - // Failover in Copy phase - var orchestrator = GetOrchestrator(MigrationMode.Auto); - var metaDict = await ((KVStoRCMigrationActorStateProvider)orchestrator.GetMigrationActorStateProvider()).GetMetadataDictionaryAsync(); - await metaDict.AddOrUpdateAsync(orchestrator.Transaction, MigrationConstants.MigrationCurrentPhase, MigrationPhase.Copy.ToString(), (_, __) => MigrationPhase.Copy.ToString()); - await metaDict.AddOrUpdateAsync(orchestrator.Transaction, MigrationConstants.MigrationCurrentStatus, MigrationState.InProgress.ToString(), (_, __) => MigrationState.InProgress.ToString()); - await orchestrator.StartMigrationAsync(false, CancellationToken.None); - var result = await orchestrator.GetResultAsync(CancellationToken.None); - Assert.Equal(MigrationPhase.Completed, result.CurrentPhase); - Assert.Equal(MigrationState.Completed, result.Status); - - // Failover in catchup phase - orchestrator = GetOrchestrator(MigrationMode.Auto); - metaDict = await ((KVStoRCMigrationActorStateProvider)orchestrator.GetMigrationActorStateProvider()).GetMetadataDictionaryAsync(); - await metaDict.AddOrUpdateAsync(orchestrator.Transaction, MigrationConstants.MigrationCurrentPhase, MigrationPhase.Catchup.ToString(), (_, __) => MigrationPhase.Catchup.ToString()); - await metaDict.AddOrUpdateAsync(orchestrator.Transaction, MigrationConstants.MigrationCurrentStatus, MigrationState.InProgress.ToString(), (_, __) => MigrationState.InProgress.ToString()); - await orchestrator.StartMigrationAsync(false, CancellationToken.None); - result = await orchestrator.GetResultAsync(CancellationToken.None); - Assert.Equal(MigrationPhase.Completed, result.CurrentPhase); - Assert.Equal(MigrationState.Completed, result.Status); - - // Failover in downtime phase - orchestrator = GetOrchestrator(MigrationMode.Auto); - metaDict = await ((KVStoRCMigrationActorStateProvider)orchestrator.GetMigrationActorStateProvider()).GetMetadataDictionaryAsync(); - await metaDict.AddOrUpdateAsync(orchestrator.Transaction, MigrationConstants.MigrationCurrentPhase, MigrationPhase.Downtime.ToString(), (_, __) => MigrationPhase.Downtime.ToString()); - await metaDict.AddOrUpdateAsync(orchestrator.Transaction, MigrationConstants.MigrationCurrentStatus, MigrationState.InProgress.ToString(), (_, __) => MigrationState.InProgress.ToString()); - await orchestrator.StartMigrationAsync(false, CancellationToken.None); - result = await orchestrator.GetResultAsync(CancellationToken.None); - Assert.Equal(MigrationPhase.Completed, result.CurrentPhase); - Assert.Equal(MigrationState.Completed, result.Status); - } - - /// - /// Auto Migration abort case - /// - /// representing the asynchronous unit test. - [Fact] - public async Task AutoMigrationAbortCase() - { - var tcs = new CancellationTokenSource(); - var orchestrator = GetOrchestrator(MigrationMode.Auto, MigrationPhase.Copy); - var migrationTask = Task.Run(() => orchestrator.StartMigrationAsync(false, tcs.Token).ConfigureAwait(false).GetAwaiter().GetResult()); - while (true) - { - MigrationResult result1 = null; - try - { - result1 = await orchestrator.GetResultAsync(CancellationToken.None); - } - catch (MigrationFrameworkNotInitializedException e) - { - Console.WriteLine(e); - Thread.Sleep(TimeSpan.FromSeconds(1)); - continue; - } - - if (result1.CurrentPhase == MigrationPhase.None || result1.Status == MigrationState.None) - { - Thread.Sleep(TimeSpan.FromSeconds(1)); - continue; - } - - Assert.True(result1.CurrentPhase <= MigrationPhase.Catchup); - Assert.True(result1.Status == MigrationState.InProgress); - await orchestrator.AbortMigrationAsync(true, CancellationToken.None); - break; - } - - try - { - await migrationTask; - } - catch (OperationCanceledException) - { - // Do nothing - } - - var result = await orchestrator.GetResultAsync(CancellationToken.None); - - Assert.Equal(MigrationState.Aborted, result.Status); - } - - /// - /// Manual Migration base case - /// - /// representing the asynchronous unit test. - [Fact] - public async Task ManualMigrationBaseCase() - { - var orchestrator = GetOrchestrator(MigrationMode.Manual); - - // ActorService calling Start Migration when the service is up - await orchestrator.StartMigrationAsync(false, CancellationToken.None); - - var migrationTask = Task.Run(() => orchestrator.StartMigrationAsync(true, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult()); - while (true) - { - MigrationResult result1 = null; - try - { - result1 = await orchestrator.GetResultAsync(CancellationToken.None); - } - catch (InvalidMigrationOperationException e) - { - Console.WriteLine(e); - Thread.Sleep(TimeSpan.FromSeconds(1)); - continue; - } - - if (result1.CurrentPhase == MigrationPhase.None || result1.Status == MigrationState.None) - { - Thread.Sleep(TimeSpan.FromSeconds(1)); - continue; - } - - Assert.True(result1.CurrentPhase <= MigrationPhase.Catchup); - Assert.True(result1.Status == MigrationState.InProgress); - if (result1.CurrentPhase == MigrationPhase.Catchup) - { - await orchestrator.StartDowntimeAsync(true, CancellationToken.None); - break; - } - - Thread.Sleep(TimeSpan.FromSeconds(1)); - } - - await migrationTask; - var result = await orchestrator.GetResultAsync(CancellationToken.None); - Assert.Equal(MigrationPhase.Completed, result.CurrentPhase); - Assert.Equal(MigrationState.Completed, result.Status); - } - - /// - /// Manual Migration failover case - /// - /// representing the asynchronous unit test. - [Fact] - public async Task ManualMigrationFailoverCase() - { - // Failover in Copy phase - var orchestrator = GetOrchestrator(MigrationMode.Manual); - var metaDict = await ((KVStoRCMigrationActorStateProvider)orchestrator.GetMigrationActorStateProvider()).GetMetadataDictionaryAsync(); - await metaDict.AddOrUpdateAsync(orchestrator.Transaction, MigrationConstants.MigrationCurrentPhase, MigrationPhase.Copy.ToString(), (_, __) => MigrationPhase.Copy.ToString()); - await metaDict.AddOrUpdateAsync(orchestrator.Transaction, MigrationConstants.MigrationCurrentStatus, MigrationState.InProgress.ToString(), (_, __) => MigrationState.InProgress.ToString()); - var migrationTask = Task.Run(() => orchestrator.StartMigrationAsync(false, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult()); - while (true) - { - MigrationResult result1 = null; - try - { - result1 = await orchestrator.GetResultAsync(CancellationToken.None); - } - catch (MigrationFrameworkNotInitializedException e) - { - Console.WriteLine(e); - Thread.Sleep(TimeSpan.FromSeconds(1)); - continue; - } - - Assert.True(result1.CurrentPhase <= MigrationPhase.Catchup); - Assert.True(result1.Status == MigrationState.InProgress); - if (result1.CurrentPhase == MigrationPhase.Catchup) - { - await orchestrator.StartDowntimeAsync(true, CancellationToken.None); - break; - } - - Thread.Sleep(TimeSpan.FromSeconds(1)); - } - - await migrationTask; - var result = await orchestrator.GetResultAsync(CancellationToken.None); - Assert.Equal(MigrationPhase.Completed, result.CurrentPhase); - Assert.Equal(MigrationState.Completed, result.Status); - - // Failover in catchup phase - orchestrator = GetOrchestrator(MigrationMode.Manual); - metaDict = await ((KVStoRCMigrationActorStateProvider)orchestrator.GetMigrationActorStateProvider()).GetMetadataDictionaryAsync(); - await metaDict.AddOrUpdateAsync(orchestrator.Transaction, MigrationConstants.MigrationCurrentPhase, MigrationPhase.Catchup.ToString(), (_, __) => MigrationPhase.Catchup.ToString()); - await metaDict.AddOrUpdateAsync(orchestrator.Transaction, MigrationConstants.MigrationCurrentStatus, MigrationState.InProgress.ToString(), (_, __) => MigrationState.InProgress.ToString()); - migrationTask = Task.Run(() => orchestrator.StartMigrationAsync(false, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult()); - while (true) - { - MigrationResult result1 = null; - try - { - result1 = await orchestrator.GetResultAsync(CancellationToken.None); - } - catch (MigrationFrameworkNotInitializedException e) - { - Console.WriteLine(e); - Thread.Sleep(TimeSpan.FromSeconds(1)); - continue; - } - - Assert.True(result1.CurrentPhase <= MigrationPhase.Catchup); - Assert.True(result1.Status == MigrationState.InProgress); - if (result1.CurrentPhase == MigrationPhase.Catchup) - { - await orchestrator.StartDowntimeAsync(true, CancellationToken.None); - break; - } - - Thread.Sleep(TimeSpan.FromSeconds(1)); - } - - await migrationTask; - result = await orchestrator.GetResultAsync(CancellationToken.None); - Assert.Equal(MigrationPhase.Completed, result.CurrentPhase); - Assert.Equal(MigrationState.Completed, result.Status); - - // Failover in downtime phase - orchestrator = GetOrchestrator(MigrationMode.Manual); - metaDict = await ((KVStoRCMigrationActorStateProvider)orchestrator.GetMigrationActorStateProvider()).GetMetadataDictionaryAsync(); - await metaDict.AddOrUpdateAsync(orchestrator.Transaction, MigrationConstants.MigrationCurrentPhase, MigrationPhase.Downtime.ToString(), (_, __) => MigrationPhase.Downtime.ToString()); - await metaDict.AddOrUpdateAsync(orchestrator.Transaction, MigrationConstants.MigrationCurrentStatus, MigrationState.InProgress.ToString(), (_, __) => MigrationState.InProgress.ToString()); - await orchestrator.StartMigrationAsync(false, CancellationToken.None); - result = await orchestrator.GetResultAsync(CancellationToken.None); - Assert.Equal(MigrationPhase.Completed, result.CurrentPhase); - Assert.Equal(MigrationState.Completed, result.Status); - } - - /// - /// Manual Migration abort case - /// - /// representing the asynchronous unit test. - [Fact] - public async Task ManualMigrationAbortCase() - { - var tcs = new CancellationTokenSource(); - var orchestrator = GetOrchestrator(MigrationMode.Manual); - await orchestrator.StartMigrationAsync(false, tcs.Token); - var migrationTask = Task.Run(() => orchestrator.StartMigrationAsync(true, tcs.Token).ConfigureAwait(false).GetAwaiter().GetResult()); - while (true) - { - MigrationResult result1 = null; - try - { - result1 = await orchestrator.GetResultAsync(CancellationToken.None); - } - catch (MigrationFrameworkNotInitializedException e) - { - Console.WriteLine(e); - Thread.Sleep(TimeSpan.FromSeconds(1)); - continue; - } - - if (result1.CurrentPhase == MigrationPhase.None || result1.Status == MigrationState.None) - { - Thread.Sleep(TimeSpan.FromSeconds(1)); - continue; - } - - Assert.True(result1.CurrentPhase <= MigrationPhase.Catchup); - Assert.True(result1.Status == MigrationState.InProgress); - await orchestrator.AbortMigrationAsync(true, CancellationToken.None); - break; - } - - try - { - await migrationTask; - } - catch (OperationCanceledException) - { - // Do nothing - } - - var result = await orchestrator.GetResultAsync(CancellationToken.None); - - Assert.Equal(MigrationState.Aborted, result.Status); - } - - /// - /// Check if actor calls allowed. - /// - /// representing the asynchronous unit test. - [Fact] - public async Task AreActorCallsAllowedTest() - { - var orchestrator = GetOrchestrator(MigrationMode.Auto); - Assert.False(orchestrator.AreActorCallsAllowed()); - bool callbackInvoked = false; - orchestrator.RegisterCompletionCallback( - (_, __) => - { - callbackInvoked = true; - return Task.CompletedTask; - }); - - await orchestrator.StartMigrationAsync(false, CancellationToken.None); - Assert.True(orchestrator.AreActorCallsAllowed()); - Assert.True(callbackInvoked); - - // Abort case - var tcs = new CancellationTokenSource(); - orchestrator = GetOrchestrator(MigrationMode.Manual); - Assert.False(orchestrator.AreActorCallsAllowed()); - callbackInvoked = false; - orchestrator.RegisterCompletionCallback( - (_, __) => - { - callbackInvoked = true; - return Task.CompletedTask; - }); - - await orchestrator.StartMigrationAsync(false, tcs.Token); - var migrationTask = Task.Run(() => orchestrator.StartMigrationAsync(true, tcs.Token).ConfigureAwait(false).GetAwaiter().GetResult()); - while (true) - { - MigrationResult result1 = null; - try - { - result1 = await orchestrator.GetResultAsync(CancellationToken.None); - } - catch (MigrationFrameworkNotInitializedException e) - { - Console.WriteLine(e); - Thread.Sleep(TimeSpan.FromSeconds(1)); - continue; - } - - if (result1.CurrentPhase == MigrationPhase.None || result1.Status == MigrationState.None) - { - Thread.Sleep(TimeSpan.FromSeconds(1)); - continue; - } - - Assert.True(result1.CurrentPhase <= MigrationPhase.Catchup); - Assert.True(result1.Status == MigrationState.InProgress); - await orchestrator.AbortMigrationAsync(true, CancellationToken.None); - break; - } - - try - { - await migrationTask; - } - catch (OperationCanceledException) - { - // Do nothing - } - - Assert.False(orchestrator.AreActorCallsAllowed()); - Assert.True(callbackInvoked); - } - - /// - /// Actor call forwarding test. - /// - /// representing the asynchronous unit test. - [Fact] - public async Task IsActorCallToBeForwardedTest() - { - var orchestrator = GetOrchestrator(MigrationMode.Manual); - - // Migration not initialized. Hence except exception. - Assert.Throws(() => orchestrator.IsActorCallToBeForwarded()); - - await orchestrator.StartMigrationAsync(false, CancellationToken.None); - var migrationTask = Task.Run(() => orchestrator.StartMigrationAsync(true, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult()); - while (true) - { - MigrationResult result1 = null; - try - { - result1 = await orchestrator.GetResultAsync(CancellationToken.None); - } - catch (MigrationFrameworkNotInitializedException e) - { - Console.WriteLine(e); - Thread.Sleep(TimeSpan.FromSeconds(1)); - continue; - } - - if (result1.CurrentPhase == MigrationPhase.None || result1.Status == MigrationState.None) - { - Thread.Sleep(TimeSpan.FromSeconds(1)); - continue; - } - - // Migration in progress. Call to be forwarded. - Assert.True(orchestrator.IsActorCallToBeForwarded()); - await orchestrator.StartDowntimeAsync(true, CancellationToken.None); - break; - } - - // Migration complete. Do not forward request. - await migrationTask; - Assert.False(orchestrator.IsActorCallToBeForwarded()); - - var tcs = new CancellationTokenSource(); - orchestrator = GetOrchestrator(MigrationMode.Manual); - await orchestrator.StartMigrationAsync(false, tcs.Token); - migrationTask = Task.Run(() => orchestrator.StartMigrationAsync(true, tcs.Token).ConfigureAwait(false).GetAwaiter().GetResult()); - while (true) - { - MigrationResult result1 = null; - try - { - result1 = await orchestrator.GetResultAsync(CancellationToken.None); - } - catch (MigrationFrameworkNotInitializedException e) - { - Console.WriteLine(e); - Thread.Sleep(TimeSpan.FromSeconds(1)); - continue; - } - - if (result1.CurrentPhase == MigrationPhase.None || result1.Status == MigrationState.None) - { - Thread.Sleep(TimeSpan.FromSeconds(1)); - continue; - } - - // Migration in progress. Call to be forwarded. - Assert.True(orchestrator.IsActorCallToBeForwarded()); - await orchestrator.AbortMigrationAsync(true, CancellationToken.None); - break; - } - - try - { - await migrationTask; - } - catch (OperationCanceledException) - { - // Do nothing - } - - // Migration aborted call to be forwarded. - Assert.True(orchestrator.IsActorCallToBeForwarded()); - - orchestrator = GetOrchestrator(MigrationMode.Auto, MigrationPhase.Downtime); - migrationTask = Task.Run(() => orchestrator.StartMigrationAsync(false, tcs.Token).ConfigureAwait(false).GetAwaiter().GetResult()); - while (true) - { - MigrationResult result1 = null; - try - { - result1 = await orchestrator.GetResultAsync(CancellationToken.None); - } - catch (MigrationFrameworkNotInitializedException e) - { - Console.WriteLine(e); - Thread.Sleep(TimeSpan.FromSeconds(1)); - continue; - } - - if (result1.CurrentPhase == MigrationPhase.None || result1.Status == MigrationState.None) - { - Thread.Sleep(TimeSpan.FromSeconds(1)); - continue; - } - - if (result1.CurrentPhase == MigrationPhase.Downtime) - { - // Downtime phase. Call should not be forwarded - Assert.False(orchestrator.IsActorCallToBeForwarded()); - break; - } - } - } - - /// - /// Invalid operations test. - /// - /// representing the asynchronous unit test. - [Fact] - public async Task InvalidOperationsTest() - { - var orchestrator = GetOrchestrator(MigrationMode.Auto); - await Assert.ThrowsAsync(() => orchestrator.AbortMigrationAsync(true, CancellationToken.None)); - await Assert.ThrowsAsync(() => orchestrator.StartDowntimeAsync(true, CancellationToken.None)); - await Assert.ThrowsAsync(() => orchestrator.GetResultAsync(CancellationToken.None)); - await orchestrator.StartMigrationAsync(false, CancellationToken.None); - await Assert.ThrowsAsync(() => orchestrator.AbortMigrationAsync(true, CancellationToken.None)); - await Assert.ThrowsAsync(() => orchestrator.StartDowntimeAsync(true, CancellationToken.None)); - await Assert.ThrowsAsync(() => orchestrator.StartMigrationAsync(true, CancellationToken.None)); - - orchestrator = GetOrchestrator(MigrationMode.Auto, invalidConfig: true); - await Assert.ThrowsAsync(() => orchestrator.StartMigrationAsync(false, CancellationToken.None)); - - orchestrator = GetOrchestrator(MigrationMode.Auto); - await Assert.ThrowsAsync(() => orchestrator.StartMigrationAsync(true, CancellationToken.None)); - } - - private static TargetMigrationOrchestrator GetOrchestrator(MigrationMode mode, MigrationPhase blockingPhase = MigrationPhase.None, bool invalidConfig = false) - { - var setting = new KVSToRCMigration.MigrationSettings - { - MigrationMode = mode, - CopyPhaseParallelism = 2, - ChunksPerEnumeration = 10, - KeyValuePairsPerChunk = 20, - SourceServiceUri = new Uri("fabric:/blah/blahblah"), - DowntimeThreshold = 1000, - }; - - var mockSp = new MockKVStoRCMigrationActorStateProvider(new MockReliableCollectionsStateProvider()); - var mockFactory = new Mock( - mockSp, - new ActorTypeInformation(), - new StatefulServiceContext( - new NodeContext("TestNode", new NodeId(new BigInteger(0), new BigInteger(0)), new BigInteger(0), "TestNodeType", "10.10.10.10"), - new Mock().Object, - "TestServiceType", - new Uri("fabric:/blah/blahblah"), - null, - Guid.NewGuid(), - 0L), - setting, - GetMockExFilter(setting), - new MockServicePartitionClient(null, new Uri("fabric:/Blah/BlahBlah")), - "TestTraceId"); - mockFactory.CallBase = true; - mockFactory.Setup(o => o.GetMigrationPhaseWorkload(It.IsAny(), It.IsAny())) - .Returns((phase, __) => - { - if (phase != MigrationPhase.Completed) - { - var res = GetMockPhaseWorkload(phase, blockingPhase != MigrationPhase.None && blockingPhase == phase); - var metaDict = mockSp.GetMetadataDictionaryAsync().GetAwaiter().GetResult(); - metaDict.AddOrUpdateAsync(mockSp.GetStateManager().CreateTransaction(), MigrationConstants.MigrationCurrentPhase, phase.ToString(), (_, __) => phase.ToString()).GetAwaiter().GetResult(); - return res; - } - - return null; - }); - mockFactory.Setup(o => o.ValidateConfigForMigrationAsync(It.IsAny())) - .Returns(_ => - { - if (invalidConfig) - { - throw new InvalidMigrationConfigException(); - } - - return Task.CompletedTask; - }); - - return mockFactory.Object; - } - - private static PartitionHealthExceptionFilter GetMockExFilter(KVSToRCMigration.MigrationSettings settings) - { - var exFilterFactory = new Mock(settings); - exFilterFactory.CallBase = false; - bool abortMigration = false; - bool rethrow = true; - exFilterFactory.Setup(ex => ex.ReportPartitionHealthIfNeeded(It.IsAny(), It.IsAny(), out abortMigration, out rethrow)); - return exFilterFactory.Object; - } - - private static IMigrationPhaseWorkload GetMockPhaseWorkload(MigrationPhase currentPhase, bool blockingCall = false) - { - var phaseFactory = new Mock(); - phaseFactory.Setup(pw => pw.StartOrResumeMigrationAsync(It.IsAny())) - .Returns(token => - { - token.ThrowIfCancellationRequested(); - if (blockingCall) - { - while (true) - { - token.ThrowIfCancellationRequested(); - Thread.Sleep(TimeSpan.FromSeconds(5)); - } - } - - var result = new PhaseResult - { - Status = MigrationState.Completed, - Phase = currentPhase, - StartDateTimeUTC = DateTime.UtcNow, - EndDateTimeUTC = DateTime.UtcNow, - StartSeqNum = 0, - EndSeqNum = 0, - LastAppliedSeqNum = 0, - Iteration = 1, - NoOfKeysMigrated = 0, - WorkerCount = 1, - }; - - return Task.FromResult(result); - }); - - phaseFactory.SetupGet(pw => pw.Phase).Returns(currentPhase); - - return phaseFactory.Object; - } - } -} From 154af8b79391eee3023d584b7d6b5e26066cc80f Mon Sep 17 00:00:00 2001 From: Oleg Sych Date: Wed, 19 Jun 2024 15:12:23 -0700 Subject: [PATCH 2/2] Remove Microsoft.ServiceFabric.Actors.Migration namespace Types in this namespace were created to support the abandoned KVS to RC state migration effort. --- .../ActorEventSource.cs | 222 ------------------ .../FabricActorExceptionKnownTypes.cs | 25 -- .../Migration/ActorEventForwarder.cs | 57 ----- .../Migration/DefaultActorRequestForwarder.cs | 119 ---------- .../Migration/ErrorResponse.cs | 42 ---- .../Migration/EventSubscriptionCache.cs | 74 ------ .../ActorCallsDisallowedException.cs | 58 ----- .../AmbiguousActorIdDetectedException.cs | 56 ----- .../InvalidMigrationConfigException.cs | 56 ----- .../InvalidMigrationOperationException.cs | 55 ----- .../InvalidMigrationStateProviderException.cs | 56 ----- ...grationFrameworkNotInitializedException.cs | 57 ----- .../Migration/IRequestForwarder.cs | 27 --- .../Migration/MigrationPhase.cs | 38 --- .../Migration/MigrationResult.cs | 101 -------- .../Migration/MigrationState.cs | 33 --- .../Migration/PhaseResult.cs | 199 ---------------- .../Migration/RequestForwarderContext.cs | 37 --- ...TransportActorRemotingProviderAttribute.cs | 28 --- ...icTransportActorServiceRemotingListener.cs | 33 +-- .../Runtime/ActorManager.cs | 22 -- .../Runtime/ActorService.cs | 126 +--------- .../AmbiguousActorIdResolverAttribute.cs | 40 ---- .../Runtime/Migration/Constants.cs | 13 - .../Migration/IAmbiguousActorIdResolver.cs | 22 -- .../Migration/IMigrationOrchestrator.cs | 100 -------- .../Runtime/Migration/MigrationMode.cs | 30 --- .../Migration/MigrationReflectionHelper.cs | 90 ------- .../Runtime/Migration/MigrationSettings.cs | 103 -------- .../Runtime/Migration/MigrationTelemetry.cs | 106 --------- .../Migration/MigrationTelemetryConstants.cs | 17 -- .../RequestForwardableRemotingDispatcher.cs | 71 ------ .../Runtime/Migration/StateMigration.cs | 28 --- .../Migration/StateMigrationAttribute.cs | 47 ---- ...ft.ServiceFabric.Actors_netstandard.csproj | 2 - 35 files changed, 10 insertions(+), 2180 deletions(-) delete mode 100644 src/Microsoft.ServiceFabric.Actors/Migration/ActorEventForwarder.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Migration/DefaultActorRequestForwarder.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Migration/ErrorResponse.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Migration/EventSubscriptionCache.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/ActorCallsDisallowedException.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/AmbiguousActorIdDetectedException.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/InvalidMigrationConfigException.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/InvalidMigrationOperationException.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/InvalidMigrationStateProviderException.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/MigrationFrameworkNotInitializedException.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Migration/IRequestForwarder.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Migration/MigrationPhase.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Migration/MigrationResult.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Migration/MigrationState.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Migration/PhaseResult.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Migration/RequestForwarderContext.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Runtime/Migration/AmbiguousActorIdResolverAttribute.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Runtime/Migration/Constants.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Runtime/Migration/IAmbiguousActorIdResolver.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Runtime/Migration/IMigrationOrchestrator.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationMode.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationReflectionHelper.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationSettings.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationTelemetry.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationTelemetryConstants.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Runtime/Migration/RequestForwardableRemotingDispatcher.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Runtime/Migration/StateMigration.cs delete mode 100644 src/Microsoft.ServiceFabric.Actors/Runtime/Migration/StateMigrationAttribute.cs diff --git a/src/Microsoft.ServiceFabric.Actors/ActorEventSource.cs b/src/Microsoft.ServiceFabric.Actors/ActorEventSource.cs index 51cf9a97..b5fff09d 100644 --- a/src/Microsoft.ServiceFabric.Actors/ActorEventSource.cs +++ b/src/Microsoft.ServiceFabric.Actors/ActorEventSource.cs @@ -37,37 +37,6 @@ internal sealed class ActorEventSource : ServiceFabricEventSource "serviceTypeName = {6}, applicationName = {7}, applicationTypeName = {8}, " + "ownerActorId = {9}, reminderPeriod = {10}, reminderName = {11}"; - #region Migration - private const string MigrationBaseFormat = "{0} : " + - "clusterOsType = {1}, " + - "runtimePlatform = {2}, " + - "partitionId = {3}, " + - "replicaId = {4}, " + - "serviceName = {5}, " + - "serviceTypeName = {6}, " + - "applicationName = {7}, " + - "applicationTypeName = {8}"; - - private const int MigrationStartEventId = 8; - private const string MigrationStartEventFormat = MigrationBaseFormat + ", settings = {9}"; - - private const int MigrationEndEventId = 9; - private const string MigrationEndEventFormat = MigrationBaseFormat + ", result = {9}"; - - private const int MigrationPhaseStartEventId = 10; - private const string MigrationPhaseStartEventFormat = MigrationBaseFormat + ", input = {9}"; - - private const int MigrationPhaseEndEventId = 11; - private const string MigrationPhaseEndEventFormat = MigrationBaseFormat + ", result = {9}"; - - private const int MigrationFailureEventId = 12; - private const string MigrationFailureEventFormat = MigrationBaseFormat + ", phase = {9}, errorMessage = {10}"; - - private const int MigrationAbortEventId = 13; - private const string MigrationAbortEventFormat = MigrationBaseFormat + ", userTriggered = {9}"; - - #endregion Migration - /// /// Prevents a default instance of the class from being created. /// @@ -227,197 +196,6 @@ internal void ActorReminderRegisterationEventWrapper( #endregion - #region MigrationEvents - [Event( - MigrationStartEventId, - Message = MigrationStartEventFormat, - Level = EventLevel.Informational, - Keywords = Keywords.Default)] - internal void MigrationStartEvent( - string type, - string clusterOsType, - string runtimePlatform, - string partitionId, - string replicaId, - string serviceName, - string serviceTypeName, - string applicationName, - string applicationTypeName, - string settingsJson) - { - this.WriteEvent( - MigrationStartEventId, - type, - clusterOsType, - runtimePlatform, - partitionId, - replicaId, - serviceName, - serviceTypeName, - applicationName, - applicationTypeName, - settingsJson); - } - - [Event( - MigrationEndEventId, - Message = MigrationEndEventFormat, - Level = EventLevel.Informational, - Keywords = Keywords.Default)] - internal void MigrationEndEvent( - string type, - string clusterOsType, - string runtimePlatform, - string partitionId, - string replicaId, - string serviceName, - string serviceTypeName, - string applicationName, - string applicationTypeName, - string resultJson) - { - this.WriteEvent( - MigrationEndEventId, - type, - clusterOsType, - runtimePlatform, - partitionId, - replicaId, - serviceName, - serviceTypeName, - applicationName, - applicationTypeName, - resultJson); - } - - [Event( - MigrationPhaseStartEventId, - Message = MigrationPhaseStartEventFormat, - Level = EventLevel.Informational, - Keywords = Keywords.Default)] - internal void MigrationPhaseStartEvent( - string type, - string clusterOsType, - string runtimePlatform, - string partitionId, - string replicaId, - string serviceName, - string serviceTypeName, - string applicationName, - string applicationTypeName, - string inputJson) - { - this.WriteEvent( - MigrationPhaseStartEventId, - type, - clusterOsType, - runtimePlatform, - partitionId, - replicaId, - serviceName, - serviceTypeName, - applicationName, - applicationTypeName, - inputJson); - } - - [Event( - MigrationPhaseEndEventId, - Message = MigrationPhaseEndEventFormat, - Level = EventLevel.Informational, - Keywords = Keywords.Default)] - internal void MigrationPhaseEndEvent( - string type, - string clusterOsType, - string runtimePlatform, - string partitionId, - string replicaId, - string serviceName, - string serviceTypeName, - string applicationName, - string applicationTypeName, - string resultJson) - { - this.WriteEvent( - MigrationPhaseEndEventId, - type, - clusterOsType, - runtimePlatform, - partitionId, - replicaId, - serviceName, - serviceTypeName, - applicationName, - applicationTypeName, - resultJson); - } - - [Event( - MigrationFailureEventId, - Message = MigrationFailureEventFormat, - Level = EventLevel.Error, - Keywords = Keywords.Default)] - internal void MigrationFailureEvent( - string type, - string clusterOsType, - string runtimePlatform, - string partitionId, - string replicaId, - string serviceName, - string serviceTypeName, - string applicationName, - string applicationTypeName, - string phase, - string errorMsg) - { - this.WriteEvent( - MigrationFailureEventId, - type, - clusterOsType, - runtimePlatform, - partitionId, - replicaId, - serviceName, - serviceTypeName, - applicationName, - applicationTypeName, - phase, - errorMsg); - } - - [Event( - MigrationAbortEventId, - Message = MigrationAbortEventFormat, - Level = EventLevel.Informational, - Keywords = Keywords.Default)] - internal void MigrationAbortEvent( - string type, - string clusterOsType, - string runtimePlatform, - string partitionId, - string replicaId, - string serviceName, - string serviceTypeName, - string applicationName, - string applicationTypeName, - bool userTriggered) - { - this.WriteEvent( - MigrationAbortEventId, - type, - clusterOsType, - runtimePlatform, - partitionId, - replicaId, - serviceName, - serviceTypeName, - applicationName, - applicationTypeName, - userTriggered); - } - - #endregion MigrationEvents - #region Events [Event(1, Message = "{2}", Level = EventLevel.Informational, Keywords = Keywords.Default)] private void InfoText(string id, string type, string message) diff --git a/src/Microsoft.ServiceFabric.Actors/FabricActorExceptionKnownTypes.cs b/src/Microsoft.ServiceFabric.Actors/FabricActorExceptionKnownTypes.cs index d87d58e4..8d0ef706 100644 --- a/src/Microsoft.ServiceFabric.Actors/FabricActorExceptionKnownTypes.cs +++ b/src/Microsoft.ServiceFabric.Actors/FabricActorExceptionKnownTypes.cs @@ -8,7 +8,6 @@ namespace Microsoft.ServiceFabric.Actors using System; using System.Collections.Generic; using System.Fabric; - using Microsoft.ServiceFabric.Actors.Migration.Exceptions; using Microsoft.ServiceFabric.Actors.Runtime; using Microsoft.ServiceFabric.Services.Communication; @@ -83,30 +82,6 @@ internal class FabricActorExceptionKnownTypes InnerExFunc = ex => GetInnerExceptions(ex), } }, - { - "Microsoft.ServiceFabric.Actors.Migration.Exceptions.ActorCallsDisallowedException", new ConvertorFuncs() - { - ToServiceExFunc = ex => ToServiceException(ex), - FromServiceExFunc = (svcEx, innerEx) => FromServiceException(svcEx, innerEx), - InnerExFunc = ex => GetInnerExceptions(ex), - } - }, - { - "Microsoft.ServiceFabric.Actors.Migration.Exceptions.InvalidMigrationConfigException", new ConvertorFuncs() - { - ToServiceExFunc = ex => ToServiceException(ex), - FromServiceExFunc = (svcEx, innerEx) => FromServiceException(svcEx, innerEx), - InnerExFunc = ex => GetInnerExceptions(ex), - } - }, - { - "Microsoft.ServiceFabric.Actors.Migration.Exceptions.InvalidMigrationStateProviderException", new ConvertorFuncs() - { - ToServiceExFunc = ex => ToServiceException(ex), - FromServiceExFunc = (svcEx, innerEx) => FromServiceException(svcEx, innerEx), - InnerExFunc = ex => GetInnerExceptions(ex), - } - }, }; private static ServiceException ToServiceException(FabricException fabricEx) diff --git a/src/Microsoft.ServiceFabric.Actors/Migration/ActorEventForwarder.cs b/src/Microsoft.ServiceFabric.Actors/Migration/ActorEventForwarder.cs deleted file mode 100644 index 4dd87a05..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Migration/ActorEventForwarder.cs +++ /dev/null @@ -1,57 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Migration -{ - using System; - using Microsoft.ServiceFabric.Actors.Remoting.V2; - using Microsoft.ServiceFabric.Actors.Remoting.V2.Client; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Services.Remoting.V2; - using Microsoft.ServiceFabric.Services.Remoting.V2.Client; - - internal class ActorEventForwarder : IServiceRemotingCallbackMessageHandler - { - private static readonly string TraceType = typeof(ActorEventForwarder).Name; - private ActorService actorService; - private string traceId; - private EventSubscriptionCache subscriptionCache; - private ActorEventSubscriberManager eventManager = ActorEventSubscriberManager.Instance; - - public ActorEventForwarder(ActorService actorService, EventSubscriptionCache subscriptionCache) - { - this.actorService = actorService; - this.subscriptionCache = subscriptionCache; - this.traceId = this.actorService.Context.TraceId; - } - - public void HandleOneWayMessage(IServiceRemotingRequestMessage requestMessage) - { - if (this.actorService.IsActorCallToBeForwarded) - { - var actorHeaders = (IActorRemotingMessageHeaders)requestMessage.GetHeader(); - if (this.subscriptionCache.GetSubscription(actorHeaders.ActorId.GetGuidId(), out var callbackClient)) - { - ActorTrace.Source.WriteInfoWithId(TraceType, this.traceId, $"Forwarding actor event message - ActorId : {actorHeaders.ActorId}, MethodName : {requestMessage.GetHeader().MethodName}"); - try - { - callbackClient.SendOneWay(requestMessage); - } - catch (Exception e) - { - ActorTrace.Source.WriteErrorWithId(TraceType, this.traceId, $"Error encountered while forwarding actor event message - ActorId : {actorHeaders.ActorId}, MethodName : {requestMessage.GetHeader().MethodName}, Exception : {e}"); - throw e; - } - - ActorTrace.Source.WriteInfoWithId(TraceType, this.traceId, $"Successfully forwarded actor event message - ActorId : {actorHeaders.ActorId}, MethodName : {requestMessage.GetHeader().MethodName}"); - } - - return; - } - - this.eventManager.HandleOneWayMessage(requestMessage); - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Migration/DefaultActorRequestForwarder.cs b/src/Microsoft.ServiceFabric.Actors/Migration/DefaultActorRequestForwarder.cs deleted file mode 100644 index 98383f95..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Migration/DefaultActorRequestForwarder.cs +++ /dev/null @@ -1,119 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Migration -{ - using System; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.Remoting; - using Microsoft.ServiceFabric.Actors.Remoting.V2; - using Microsoft.ServiceFabric.Actors.Remoting.V2.FabricTransport.Client; - using Microsoft.ServiceFabric.Actors.Remoting.V2.Runtime; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Services; - using Microsoft.ServiceFabric.Services.Communication.Client; - using Microsoft.ServiceFabric.Services.Remoting.V2; - using Microsoft.ServiceFabric.Services.Remoting.V2.Client; - using Microsoft.ServiceFabric.Services.Remoting.V2.Runtime; - - /// - /// Default implementation for actor request forwarding scenario. - /// - public class DefaultActorRequestForwarder : IRequestForwarder - { - private static readonly string TraceType = typeof(DefaultActorRequestForwarder).Name; - private ServiceRemotingPartitionClient remotingClient; - private EventSubscriptionCache eventCache; - private IServiceRemotingCallbackMessageHandler callbackHandler; - private ActorService actorService; - private string traceId; - - /// - /// Initializes a new instance of the class - /// - /// Actor service. - /// Context for request forwarder. - /// Remote service listener name. If specified null, "Migration Listener" will be used as default. - /// Factory method to create remoting communication client factory. - /// Retry settings for the remote object calls made by proxy. - public DefaultActorRequestForwarder( - ActorService actorService, - RequestForwarderContext requestForwarderContext, - string listenerName = null, - Func createServiceRemotingClientFactory = null, - OperationRetrySettings retrySettings = null) - { - this.actorService = actorService; - this.eventCache = new EventSubscriptionCache(actorService, requestForwarderContext.TraceId); - this.callbackHandler = new ActorEventForwarder(this.actorService, this.eventCache); - var serviceRemotingClientFactory = createServiceRemotingClientFactory == null - ? new FabricTransportActorRemotingClientFactory(this.callbackHandler) - : createServiceRemotingClientFactory.Invoke(this.callbackHandler); - - this.remotingClient = new ServiceRemotingPartitionClient( - serviceRemotingClientFactory, - requestForwarderContext.ServiceUri, - requestForwarderContext.ServicePartitionKey, - requestForwarderContext.ReplicaSelector, - listenerName ?? Runtime.Migration.Constants.MigrationListenerName, - retrySettings); - - this.traceId = requestForwarderContext.TraceId; - } - - /// - public async Task ForwardRequestResponseAsync( - IServiceRemotingRequestContext requestContext, - IServiceRemotingRequestMessage requestMessage) - { - ActorId actorId = null; - if (requestMessage.GetHeader() is IActorRemotingMessageHeaders actorHeaders) - { - actorId = ((IActorRemotingMessageHeaders)requestMessage.GetHeader()).ActorId; - if (actorHeaders.InterfaceId == ActorEventSubscription.InterfaceId) - { - var requestMsgBody = requestMessage.GetBody(); - if (actorHeaders.MethodId == ActorEventSubscription.SubscribeMethodId) - { - var castedRequestMsgBody = - (EventSubscriptionRequestBody)requestMsgBody.GetParameter( - 0, - "Value", - typeof(EventSubscriptionRequestBody)); - - this.eventCache.AddToCache(castedRequestMsgBody.SubscriptionId, requestContext.GetCallBackClient()); - } - else if (actorHeaders.MethodId == ActorEventSubscription.UnSubscribeMethodId) - { - var castedRequestMsgBody = - (EventSubscriptionRequestBody)requestMsgBody.GetParameter( - 0, - "Value", - typeof(EventSubscriptionRequestBody)); - - this.eventCache.RemoveFromCache(castedRequestMsgBody.SubscriptionId); - } - } - } - - ActorTrace.Source.WriteInfoWithId(TraceType, this.traceId, $"[{LogContext.GetRequestIdOrDefault()}] Forwarding actor request - ActorId : {actorId}, MethodName : {requestMessage.GetHeader().MethodName}"); - - try - { - requestMessage.GetHeader().AddHeader(Runtime.Migration.Constants.ForwardRequestHeaderName, new byte[0]); - var retVal = await this.remotingClient.InvokeAsync(requestMessage, requestMessage.GetHeader().MethodName, CancellationToken.None); - ActorTrace.Source.WriteInfoWithId(TraceType, this.traceId, $"[{LogContext.GetRequestIdOrDefault()}] Successfully received response for the forwarded actor request - ActorId : {actorId}, MethodName : {requestMessage.GetHeader().MethodName}"); - - return retVal; - } - catch (Exception e) - { - ActorTrace.Source.WriteErrorWithId(TraceType, this.traceId, $"[{LogContext.GetRequestIdOrDefault()}] Error encountered while forwarding actor request - ActorId : {actorId}, MethodName : {requestMessage.GetHeader().MethodName}, Exception : {e}"); - throw e; - } - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Migration/ErrorResponse.cs b/src/Microsoft.ServiceFabric.Actors/Migration/ErrorResponse.cs deleted file mode 100644 index 83e33ef7..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Migration/ErrorResponse.cs +++ /dev/null @@ -1,42 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Migration -{ - using System.Fabric; - using System.Runtime.Serialization; - - /// - /// Migration custom http error reponse. - /// - [DataContract] - [KnownType(typeof(FabricErrorCode))] - public class ErrorResponse - { - /// - /// Gets or sets the migration error message. - /// - [DataMember] - public string Message { get; set; } - - /// - /// Gets or sets the migration error code. - /// - [DataMember] - public FabricErrorCode ErrorCode { get; set; } - - /// - /// Gets or sets the exception type - /// - [DataMember] - public string ExceptionType { get; set; } - - /// - /// Gets or sets a value indicating whether the error is Fabric related. - /// - [DataMember] - public bool IsFabricError { get; set; } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Migration/EventSubscriptionCache.cs b/src/Microsoft.ServiceFabric.Actors/Migration/EventSubscriptionCache.cs deleted file mode 100644 index 052a6937..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Migration/EventSubscriptionCache.cs +++ /dev/null @@ -1,74 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Migration -{ - using System; - using System.Collections.Concurrent; - using Microsoft.ServiceFabric.Actors.Remoting.V2.Builder; - using Microsoft.ServiceFabric.Actors.Runtime; - using Microsoft.ServiceFabric.Services.Remoting.V2.Runtime; - - internal class EventSubscriptionCache - { - private static readonly string TraceType = typeof(EventSubscriptionCache).Name; - //// TODO: Leak when client crashes or exits without unsubscribing. - private readonly ConcurrentDictionary callbackClientMap; - private string traceId; - - public EventSubscriptionCache(ActorService actorService, string traceId) - { - this.traceId = traceId; - - foreach (var eventType in actorService.ActorTypeInformation.EventInterfaceTypes) - { - // Required to generate interface description for IActorEvent, - // incase this is the first call to the event type and needs to be forwarded. - ActorCodeBuilder.GetOrCreateEventProxyGenerator(eventType); - } - - this.callbackClientMap = new ConcurrentDictionary(); - } - - public void AddToCache(Guid subscriptionId, IServiceRemotingCallbackClient callbackClient) - { - if (!this.callbackClientMap.TryAdd(subscriptionId, callbackClient)) - { - ActorTrace.Source.WriteWarningWithId( - TraceType, - this.traceId, - $"CallbackClient already found for subscription : {subscriptionId}. Ignoring the add callbackclient request."); - - return; - } - } - - public void RemoveFromCache(Guid subscriptionId) - { - if (!this.callbackClientMap.TryRemove(subscriptionId, out var callbackClient)) - { - ActorTrace.Source.WriteWarningWithId( - TraceType, - this.traceId, - $"CallbackClient not found for subscription : {subscriptionId}. Ignoring the remove callbackclient request."); - } - } - - public bool GetSubscription(Guid subscriptionId, out IServiceRemotingCallbackClient callbackClient) - { - if (!this.callbackClientMap.TryGetValue(subscriptionId, out callbackClient)) - { - ActorTrace.Source.WriteWarningWithId( - TraceType, - this.traceId, - $"CallbackClient not found for subscription : {subscriptionId}. Ignoring the actor event."); - - return false; - } - - return true; - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/ActorCallsDisallowedException.cs b/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/ActorCallsDisallowedException.cs deleted file mode 100644 index 11e4eba1..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/ActorCallsDisallowedException.cs +++ /dev/null @@ -1,58 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Migration.Exceptions -{ - using System; - using System.Fabric; - using System.Runtime.Serialization; - - /// - /// Exception to indicate the current migration service is not allowed to dispatch actor calls. - /// Source Migration service is disallowed to accept calls in downtime phase. - /// Target Migration service is disallowed to accept calls until all the sequence numbers are migrated successfully. - /// - [Serializable] - public sealed class ActorCallsDisallowedException : FabricException - { - /// - /// Initializes a new instance of the class. - /// - public ActorCallsDisallowedException() - : base() - { - } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - /// The error message that explains the reason for the exception. - public ActorCallsDisallowedException(string message) - : base(message) - { - } - - /// - /// Initializes a new instance of the class with a specified error message and - /// a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - public ActorCallsDisallowedException(string message, Exception inner) - : base(message, inner) - { - } - - /// - /// Initializes a new instance of the class with serialized data. - /// - /// The that holds the serialized object data about the exception being thrown. - /// The that contains contextual information about the source or destination. - private ActorCallsDisallowedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/AmbiguousActorIdDetectedException.cs b/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/AmbiguousActorIdDetectedException.cs deleted file mode 100644 index 5ddb57f4..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/AmbiguousActorIdDetectedException.cs +++ /dev/null @@ -1,56 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Migration.Exceptions -{ - using System; - using System.Fabric; - using System.Runtime.Serialization; - - /// - /// Exception to represent unresolved ambiguous actor id detection. - /// - [Serializable] - public sealed class AmbiguousActorIdDetectedException : FabricException - { - /// - /// Initializes a new instance of the class. - /// - public AmbiguousActorIdDetectedException() - : base() - { - } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - /// The error message that explains the reason for the exception. - public AmbiguousActorIdDetectedException(string message) - : base(message) - { - } - - /// - /// Initializes a new instance of the class with a specified error message and - /// a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - public AmbiguousActorIdDetectedException(string message, Exception inner) - : base(message, inner) - { - } - - /// - /// Initializes a new instance of the class with serialized data. - /// - /// The that holds the serialized object data about the exception being thrown. - /// The that contains contextual information about the source or destination. - private AmbiguousActorIdDetectedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/InvalidMigrationConfigException.cs b/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/InvalidMigrationConfigException.cs deleted file mode 100644 index d96f1603..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/InvalidMigrationConfigException.cs +++ /dev/null @@ -1,56 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Migration.Exceptions -{ - using System; - using System.Fabric; - using System.Runtime.Serialization; - - /// - /// Exception to represent MigrationConfig provided is invalid. - /// - [Serializable] - public sealed class InvalidMigrationConfigException : FabricException - { - /// - /// Initializes a new instance of the class. - /// - public InvalidMigrationConfigException() - : base() - { - } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - /// The error message that explains the reason for the exception. - public InvalidMigrationConfigException(string message) - : base(message) - { - } - - /// - /// Initializes a new instance of the class with a specified error message and - /// a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - public InvalidMigrationConfigException(string message, Exception inner) - : base(message, inner) - { - } - - /// - /// Initializes a new instance of the class with serialized data. - /// - /// The that holds the serialized object data about the exception being thrown. - /// The that contains contextual information about the source or destination. - private InvalidMigrationConfigException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/InvalidMigrationOperationException.cs b/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/InvalidMigrationOperationException.cs deleted file mode 100644 index f6b7ee61..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/InvalidMigrationOperationException.cs +++ /dev/null @@ -1,55 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Migration.Exceptions -{ - using System; - using System.Fabric; - using System.Runtime.Serialization; - - /// - /// Exception to indicate the current migration operation is not allowed. - /// - public sealed class InvalidMigrationOperationException : FabricException - { - /// - /// Initializes a new instance of the class. - /// - public InvalidMigrationOperationException() - : base() - { - } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - /// The error message that explains the reason for the exception. - public InvalidMigrationOperationException(string message) - : base(message) - { - } - - /// - /// Initializes a new instance of the class with a specified error message and - /// a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - public InvalidMigrationOperationException(string message, Exception inner) - : base(message, inner) - { - } - - /// - /// Initializes a new instance of the class with serialized data. - /// - /// The that holds the serialized object data about the exception being thrown. - /// The that contains contextual information about the source or destination. - private InvalidMigrationOperationException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/InvalidMigrationStateProviderException.cs b/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/InvalidMigrationStateProviderException.cs deleted file mode 100644 index 328b8be6..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/InvalidMigrationStateProviderException.cs +++ /dev/null @@ -1,56 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors -{ - using System; - using System.Fabric; - using System.Runtime.Serialization; - - /// - /// Exception to indicate actor state provider is invalid and cannot partitipate in migration. - /// - [Serializable] - public sealed class InvalidMigrationStateProviderException : FabricException - { - /// - /// Initializes a new instance of the class. - /// - public InvalidMigrationStateProviderException() - : base() - { - } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - /// The error message that explains the reason for the exception. - public InvalidMigrationStateProviderException(string message) - : base(message) - { - } - - /// - /// Initializes a new instance of the class with a specified error message and - /// a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - public InvalidMigrationStateProviderException(string message, Exception inner) - : base(message, inner) - { - } - - /// - /// Initializes a new instance of the class with serialized data. - /// - /// The that holds the serialized object data about the exception being thrown. - /// The that contains contextual information about the source or destination. - private InvalidMigrationStateProviderException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/MigrationFrameworkNotInitializedException.cs b/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/MigrationFrameworkNotInitializedException.cs deleted file mode 100644 index 99bf3f83..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Migration/Exceptions/MigrationFrameworkNotInitializedException.cs +++ /dev/null @@ -1,57 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Migration.Exceptions -{ - using System; - using System.Fabric; - using System.Runtime.Serialization; - - /// - /// Exception to indicate the migration framework is not yet initialized. - /// This is a transient exception and proxy calls receiving this exception could retry the call. - /// - [Serializable] - public class MigrationFrameworkNotInitializedException : FabricException - { - /// - /// Initializes a new instance of the class. - /// - public MigrationFrameworkNotInitializedException() - : base() - { - } - - /// - /// Initializes a new instance of the class with a specified error message. - /// - /// The error message that explains the reason for the exception. - public MigrationFrameworkNotInitializedException(string message) - : base(message) - { - } - - /// - /// Initializes a new instance of the class with a specified error message and - /// a reference to the inner exception that is the cause of this exception. - /// - /// The error message that explains the reason for the exception. - /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - public MigrationFrameworkNotInitializedException(string message, Exception inner) - : base(message, inner) - { - } - - /// - /// Initializes a new instance of the class with serialized data. - /// - /// The that holds the serialized object data about the exception being thrown. - /// The that contains contextual information about the source or destination. - private MigrationFrameworkNotInitializedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Migration/IRequestForwarder.cs b/src/Microsoft.ServiceFabric.Actors/Migration/IRequestForwarder.cs deleted file mode 100644 index 54f621e4..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Migration/IRequestForwarder.cs +++ /dev/null @@ -1,27 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Migration -{ - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Services.Remoting.V2; - using Microsoft.ServiceFabric.Services.Remoting.V2.Runtime; - - /// - /// Interface definition for forwardding actor requests if the current service cannot service the request. - /// - public interface IRequestForwarder - { - /// - /// Forwards the actor/service proxy requests to the remote service. - /// - /// Contains additional information about the request. - /// The request message. - /// Task to represent the status of the async operation. - public Task ForwardRequestResponseAsync( - IServiceRemotingRequestContext requestContext, - IServiceRemotingRequestMessage requestMessage); - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Migration/MigrationPhase.cs b/src/Microsoft.ServiceFabric.Actors/Migration/MigrationPhase.cs deleted file mode 100644 index 0a1e4e46..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Migration/MigrationPhase.cs +++ /dev/null @@ -1,38 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Migration -{ - /// - /// Indicates actor service migration phase. - /// - public enum MigrationPhase - { - /// - /// Migration not started. - /// - None = 0, - - /// - /// Copy phase of migration. - /// - Copy = 1, - - /// - /// Catchup phase of migration. - /// - Catchup = 2, - - /// - /// Downtime phase of migration. - /// - Downtime = 3, - - /// - /// Migration completed. - /// - Completed = 4, - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Migration/MigrationResult.cs b/src/Microsoft.ServiceFabric.Actors/Migration/MigrationResult.cs deleted file mode 100644 index 3834ebf8..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Migration/MigrationResult.cs +++ /dev/null @@ -1,101 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Migration -{ - using System; - using System.IO; - using System.Runtime.Serialization; - using System.Runtime.Serialization.Json; - using System.Text; - using Microsoft.ServiceFabric.Actors.Runtime.Migration; - - /// - /// Migration result. - /// - [DataContract] - public class MigrationResult - { - private static DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(MigrationResult), new DataContractJsonSerializerSettings - { - UseSimpleDictionaryFormat = true, - }); - - /// - /// Gets or sets the migration mode. - /// - [DataMember] - public MigrationMode MigrationMode { get; set; } - - /// - /// Gets or sets the migration start time. - /// - [DataMember] - public DateTime? StartDateTimeUTC { get; set; } - - /// - /// Gets or sets the migration end time. - /// - [DataMember] - public DateTime? EndDateTimeUTC { get; set; } - - /// - /// Gets or sets the migration status. - /// - [DataMember] - public MigrationState Status { get; set; } - - /// - /// Gets or sets the current migration phase. - /// - [DataMember] - public MigrationPhase CurrentPhase { get; set; } - - /// - /// Gets or sets the start sequence num. - /// - [DataMember] - public long? StartSeqNum { get; set; } - - /// - /// Gets or sets the end sequence nummber. - /// - [DataMember] - public long? EndSeqNum { get; set; } - - /// - /// Gets or sets the last applied sequence number. - /// - [DataMember] - public long? LastAppliedSeqNum { get; set; } - - /// - /// Gets or sets the number of sequence numbers migrated. - /// - [DataMember] - public long? NoOfKeysMigrated { get; set; } - - /// - /// Gets or sets the phase wise results. - /// - [DataMember] - public PhaseResult[] PhaseResults { get; set; } - - /// - /// String representation of the object. - /// - /// Returns the string representation of the object. - public override string ToString() - { - using (var stream = new MemoryStream()) - { - serializer.WriteObject(stream, this); - var returnVal = Encoding.UTF8.GetString(stream.ToArray()); - - return returnVal; - } - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Migration/MigrationState.cs b/src/Microsoft.ServiceFabric.Actors/Migration/MigrationState.cs deleted file mode 100644 index 1067508d..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Migration/MigrationState.cs +++ /dev/null @@ -1,33 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Migration -{ - /// - /// Indicates actor service migration state. - /// - public enum MigrationState - { - /// - /// Migration not started. - /// - None = 0, - - /// - /// Migration in progress. - /// - InProgress = 1, - - /// - /// Migration completed. - /// - Completed = 2, - - /// - /// Migration aborted. - /// - Aborted = 3, - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Migration/PhaseResult.cs b/src/Microsoft.ServiceFabric.Actors/Migration/PhaseResult.cs deleted file mode 100644 index 7e97ec19..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Migration/PhaseResult.cs +++ /dev/null @@ -1,199 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Migration -{ - using System; - using System.IO; - using System.Runtime.Serialization; - using System.Runtime.Serialization.Json; - using System.Text; - - /// - /// Migration phase result. - /// - [DataContract] - public class PhaseResult - { - private static DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(PhaseResult), new DataContractJsonSerializerSettings - { - UseSimpleDictionaryFormat = true, - }); - - /// - /// Gets or sets the migration start time. - /// - [DataMember] - public DateTime StartDateTimeUTC { get; set; } - - /// - /// Gets or sets the migration end time. - /// - [DataMember] - public DateTime? EndDateTimeUTC { get; set; } - - /// - /// Gets or sets the start sequence number. - /// - [DataMember] - public long StartSeqNum { get; set; } - - /// - /// Gets or sets the end sequence number. - /// - [DataMember] - public long EndSeqNum { get; set; } - - /// - /// Gets or sets the last applied sequence number. - /// - [DataMember] - public long? LastAppliedSeqNum { get; set; } - - /// - /// Gets or sets the migration status. - /// - [DataMember] - public MigrationState Status { get; set; } - - /// - /// Gets or sets the worker count. - /// - [DataMember] - public int WorkerCount { get; set; } - - /// - /// Gets or sets the current iteration. - /// - [DataMember] - public int Iteration { get; set; } - - /// - /// Gets or sets the number of keys migrated. - /// - [DataMember] - public long? NoOfKeysMigrated { get; set; } - - /// - /// Gets or sets the migration phase. - /// - [DataMember] - public MigrationPhase Phase { get; set; } - - /// - /// Gets or sets the worker results. - /// - [DataMember] - public WorkerResult[] WorkerResults { get; set; } - - /// - /// String representation of the object. - /// - /// Returns the string representation of the object. - public override string ToString() - { - using (var stream = new MemoryStream()) - { - serializer.WriteObject(stream, this); - var returnVal = Encoding.UTF8.GetString(stream.ToArray()); - - return returnVal; - } - } - - /// - /// Migration worker result. - /// - [DataContract] - public class WorkerResult - { - private static DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(WorkerResult), new DataContractJsonSerializerSettings - { - UseSimpleDictionaryFormat = true, - }); - - /// - /// Gets or sets the worker id. - /// - [DataMember] - public int WorkerId { get; set; } - - /// - /// Gets or sets the migration start time. - /// - [DataMember] - public DateTime StartDateTimeUTC { get; set; } - - /// - /// Gets or sets the migration end time. - /// - [DataMember] - public DateTime? EndDateTimeUTC { get; set; } - - /// - /// Gets or sets the start sequence number. - /// - [DataMember] - public long StartSeqNum { get; set; } - - /// - /// Gets or sets the end sequence number. - /// - [DataMember] - public long EndSeqNum { get; set; } - - /// - /// Gets or sets the last applied sequence number. - /// - [DataMember] - public long? LastAppliedSeqNum { get; set; } - - /// - /// Gets or sets the migration status. - /// - [DataMember] - public MigrationState Status { get; set; } - - /// - /// Gets or sets the worker count. - /// - [DataMember] - public int WorkerCount { get; set; } - - /// - /// Gets or sets the current iteration. - /// - [DataMember] - public int Iteration { get; set; } - - /// - /// Gets or sets the number of keys migrated. - /// - [DataMember] - public long? NoOfKeysMigrated { get; set; } - - /// - /// Gets or sets the migration phase. - /// - [DataMember] - public MigrationPhase Phase { get; set; } - - /// - /// String representation of the object. - /// - /// Returns the string representation of the object. - public override string ToString() - { - using (var stream = new MemoryStream()) - { - serializer.WriteObject(stream, this); - var returnVal = Encoding.UTF8.GetString(stream.ToArray()); - - return returnVal; - } - } - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Migration/RequestForwarderContext.cs b/src/Microsoft.ServiceFabric.Actors/Migration/RequestForwarderContext.cs deleted file mode 100644 index 7ae61bfa..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Migration/RequestForwarderContext.cs +++ /dev/null @@ -1,37 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Migration -{ - using System; - using Microsoft.ServiceFabric.Services.Client; - using Microsoft.ServiceFabric.Services.Communication.Client; - - /// - /// Context for request forwarder when the current service is unable to service the request. - /// - public class RequestForwarderContext - { - /// - /// Gets the remote service uri. - /// - public Uri ServiceUri { get; internal set; } - - /// - /// Gets the remote partition key. - /// - public ServicePartitionKey ServicePartitionKey { get; internal set; } - - /// - /// Gets the target replica selector. - /// - public TargetReplicaSelector ReplicaSelector { get; internal set; } - - /// - /// Gets the trace id for logging. - /// - public string TraceId { get; internal set; } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Remoting/FabricTransport/FabricTransportActorRemotingProviderAttribute.cs b/src/Microsoft.ServiceFabric.Actors/Remoting/FabricTransport/FabricTransportActorRemotingProviderAttribute.cs index 62a81cd5..73d87130 100644 --- a/src/Microsoft.ServiceFabric.Actors/Remoting/FabricTransport/FabricTransportActorRemotingProviderAttribute.cs +++ b/src/Microsoft.ServiceFabric.Actors/Remoting/FabricTransport/FabricTransportActorRemotingProviderAttribute.cs @@ -7,9 +7,7 @@ namespace Microsoft.ServiceFabric.Actors.Remoting.FabricTransport { using System; using System.Collections.Generic; - using System.Fabric; using Microsoft.ServiceFabric.Actors.Generator; - using Microsoft.ServiceFabric.Actors.Migration; using Microsoft.ServiceFabric.Actors.Remoting.V2.Client; using Microsoft.ServiceFabric.Actors.Remoting.V2.FabricTransport.Client; using Microsoft.ServiceFabric.Actors.Runtime; @@ -150,19 +148,6 @@ public override Dictionary> => { var listenerSettings = this.InitializeListenerSettings(actorService); - if (actorService.IsConfiguredForMigration()) - { - return new V2.FabricTransport.Runtime.FabricTransportActorServiceRemotingListener( - actorService, - listenerSettings, - requestForwarderFactory: requestForwarderContext => new DefaultActorRequestForwarder( - actorService, - requestForwarderContext, - ServiceRemotingProviderAttribute.DefaultV2listenerName, - callbackMessageHandler => this.CreateServiceRemotingClientFactory(callbackMessageHandler), - null)); - } - return new V2.FabricTransport.Runtime.FabricTransportActorServiceRemotingListener( actorService, listenerSettings); @@ -176,19 +161,6 @@ public override Dictionary> { var listenerSettings = this.InitializeListenerSettings(actorService); listenerSettings.UseWrappedMessage = true; - if (actorService.IsConfiguredForMigration()) - { - return new V2.FabricTransport.Runtime.FabricTransportActorServiceRemotingListener( - actorService, - listenerSettings, - requestForwarderFactory: requestForwarderContext => new DefaultActorRequestForwarder( - actorService, - requestForwarderContext, - ServiceRemotingProviderAttribute.DefaultWrappedMessageStackListenerName, - callbackMessageHandler => this.CreateServiceRemotingClientFactory(callbackMessageHandler), - null)); - } - return new V2.FabricTransport.Runtime.FabricTransportActorServiceRemotingListener( actorService, listenerSettings); diff --git a/src/Microsoft.ServiceFabric.Actors/Remoting/V2/FabricTransport/Runtime/FabricTransportActorServiceRemotingListener.cs b/src/Microsoft.ServiceFabric.Actors/Remoting/V2/FabricTransport/Runtime/FabricTransportActorServiceRemotingListener.cs index 9c4bee44..8b798a5a 100644 --- a/src/Microsoft.ServiceFabric.Actors/Remoting/V2/FabricTransport/Runtime/FabricTransportActorServiceRemotingListener.cs +++ b/src/Microsoft.ServiceFabric.Actors/Remoting/V2/FabricTransport/Runtime/FabricTransportActorServiceRemotingListener.cs @@ -11,7 +11,6 @@ namespace Microsoft.ServiceFabric.Actors.Remoting.V2.FabricTransport.Runtime using System.Collections.Generic; using System.Fabric; using Microsoft.ServiceFabric.Actors.Generator; - using Microsoft.ServiceFabric.Actors.Migration; using Microsoft.ServiceFabric.Actors.Remoting.FabricTransport; using Microsoft.ServiceFabric.Actors.Remoting.V2.Runtime; using Microsoft.ServiceFabric.Actors.Runtime; @@ -40,18 +39,15 @@ public class FabricTransportActorServiceRemotingListener : FabricTransportServic /// The settings to use for the listener. /// /// Convertors to convert user exception to service exception. - /// Request forwarder incase migration is ongoing and current service cannot service the request. public FabricTransportActorServiceRemotingListener( ActorService actorService, FabricTransportRemotingListenerSettings listenerSettings = null, - IEnumerable exceptionConvertors = null, - Func requestForwarderFactory = null) + IEnumerable exceptionConvertors = null) : this( actorService, CreateActorRemotingDispatcher(actorService, listenerSettings), SetEndPointResourceName(listenerSettings, actorService), - exceptionConvertors: exceptionConvertors, - requestForwarderFactory: requestForwarderFactory) + exceptionConvertors: exceptionConvertors) { } @@ -69,27 +65,24 @@ public FabricTransportActorServiceRemotingListener( /// The settings to use for the listener. /// /// Convertors to convert user exception to service exception. - /// Request forwarder incase migration is ongoing and current service cannot service the request. public FabricTransportActorServiceRemotingListener( ActorService actorService, IServiceRemotingMessageSerializationProvider serializationProvider, FabricTransportRemotingListenerSettings listenerSettings = null, - IEnumerable exceptionConvertors = null, - Func requestForwarderFactory = null) + IEnumerable exceptionConvertors = null) : this( actorService, new ActorServiceRemotingDispatcher(actorService, serializationProvider.CreateMessageBodyFactory()), SetEndPointResourceName(listenerSettings, actorService), serializationProvider, - exceptionConvertors, - requestForwarderFactory) + exceptionConvertors) { } /// /// Initializes a new instance of the class. /// This is a Service Fabric TCP transport based service remoting listener for the specified actor service. - /// This constructor is deprecated, use + /// This constructor is deprecated, use /// /// /// The context of the service for which the remoting listener is being constructed. @@ -130,17 +123,15 @@ public FabricTransportActorServiceRemotingListener( /// Listener Settings. /// Serialization provider for remoting. /// Convertors to convert user exception to service exception. - /// Request forwarder incase migration is ongoing and current service cannot service the request. public FabricTransportActorServiceRemotingListener( ActorService actorService, IServiceRemotingMessageHandler messageHandler, FabricTransportRemotingListenerSettings listenerSettings = null, IServiceRemotingMessageSerializationProvider serializationProvider = null, - IEnumerable exceptionConvertors = null, - Func requestForwarderFactory = null) + IEnumerable exceptionConvertors = null) : base( GetContext(actorService), - OverrideMessageHandlerIfRequired(actorService, messageHandler, requestForwarderFactory), + messageHandler, InitializeSerializerManager( SetEndPointResourceName(listenerSettings, actorService), serializationProvider), @@ -149,16 +140,6 @@ public FabricTransportActorServiceRemotingListener( { } - private static IServiceRemotingMessageHandler OverrideMessageHandlerIfRequired(ActorService actorService, IServiceRemotingMessageHandler messageHandler, Func requestForwarderFactory) - { - if (actorService.IsConfiguredForMigration()) - { - return actorService.MigrationOrchestrator.GetMessageHandler(actorService, messageHandler, requestForwarderFactory); - } - - return messageHandler; - } - private static IEnumerable GetExceptionConvertors(IEnumerable exceptionConvertors) { var actorConvertors = new List(); diff --git a/src/Microsoft.ServiceFabric.Actors/Runtime/ActorManager.cs b/src/Microsoft.ServiceFabric.Actors/Runtime/ActorManager.cs index 80a474ab..3c06eb11 100644 --- a/src/Microsoft.ServiceFabric.Actors/Runtime/ActorManager.cs +++ b/src/Microsoft.ServiceFabric.Actors/Runtime/ActorManager.cs @@ -18,7 +18,6 @@ namespace Microsoft.ServiceFabric.Actors.Runtime using Microsoft.ServiceFabric.Actors.Diagnostics; using Microsoft.ServiceFabric.Actors.Query; using Microsoft.ServiceFabric.Actors.Remoting; - using Microsoft.ServiceFabric.Actors.Runtime.Migration; using Microsoft.ServiceFabric.Services.Common; using Microsoft.ServiceFabric.Services.Remoting; using Microsoft.ServiceFabric.Services.Remoting.V2; @@ -158,7 +157,6 @@ public Task InvokeAsync( cancellationToken.ThrowIfCancellationRequested(); this.ThrowIfClosed(); - this.ThrowIfMigrationInProgress(); var methodDispatcher = this.actorService.MethodDispatcherMapV1.GetDispatcher(interfaceId, methodId); var actorMethodName = methodDispatcher.GetMethodName(methodId); @@ -197,7 +195,6 @@ public async Task DispatchToActorAsync( CancellationToken cancellationToken) { this.ThrowIfClosed(); - this.ThrowIfMigrationInProgress(); ExceptionDispatchInfo exceptionInfo = null; Exception exception = null; @@ -321,7 +318,6 @@ public Task InvokeAsync( cancellationToken.ThrowIfCancellationRequested(); this.ThrowIfClosed(); - this.ThrowIfMigrationInProgress(); var methodDispatcher = this.actorService.MethodDispatcherMapV2.GetDispatcher(interfaceId, methodId); var actorMethodName = methodDispatcher.GetMethodName(methodId); @@ -348,15 +344,11 @@ public Task InvokeAsync( public Task SubscribeAsync(ActorId actorId, int eventInterfaceId, IActorEventSubscriberProxy subscriber) { - this.ThrowIfMigrationInProgress(); - return this.eventManager.SubscribeAsync(actorId, eventInterfaceId, subscriber); } public Task UnsubscribeAsync(ActorId actorId, int eventInterfaceId, Guid subscriberId) { - this.ThrowIfMigrationInProgress(); - return this.eventManager.UnsubscribeAsync(actorId, eventInterfaceId, subscriberId); } @@ -373,8 +365,6 @@ public async Task RegisterOrUpdateReminderAsync( TimeSpan period, bool saveState = true) { - this.ThrowIfMigrationInProgress(); - var reminder = new ActorReminder(actorId, this, reminderName, state, dueTime, period); await this.RegisterOrUpdateReminderAsync(reminder, dueTime, saveState); @@ -401,7 +391,6 @@ public IActorReminder GetReminder(string reminderName, ActorId actorId) public async Task UnregisterReminderAsync(string reminderName, ActorId actorId, bool removeFromStateProvider) { this.ThrowIfClosed(); - this.ThrowIfMigrationInProgress(); ActorTrace.Source.WriteInfoWithId( TraceType, @@ -443,16 +432,12 @@ public async Task UnregisterReminderAsync(string reminderName, ActorId actorId, public Task StartLoadingRemindersAsync(CancellationToken cancellationToken) { - this.ThrowIfMigrationInProgress(); - this.loadRemindersTask = this.LoadRemindersAsync(cancellationToken); return this.loadRemindersTask; } public async Task FireReminderAsync(ActorReminder reminder) { - this.ThrowIfMigrationInProgress(); - var rearmTimer = true; try @@ -538,8 +523,6 @@ await this.DispatchToActorAsync( public async Task DeleteActorAsync(string callContext, ActorId actorId, CancellationToken cancellationToken) { - this.ThrowIfMigrationInProgress(); - ExceptionDispatchInfo exceptionInfo = null; if (!this.HasRemindersLoaded) @@ -1174,11 +1157,6 @@ private void ThrowIfClosed() } } - private void ThrowIfMigrationInProgress() - { - this.ActorService.ThrowIfActorCallsDisallowed(); - } - private void DisposeDiagnosticsManager() { if (this.diagnosticsManager != null) diff --git a/src/Microsoft.ServiceFabric.Actors/Runtime/ActorService.cs b/src/Microsoft.ServiceFabric.Actors/Runtime/ActorService.cs index d3941532..b0921744 100644 --- a/src/Microsoft.ServiceFabric.Actors/Runtime/ActorService.cs +++ b/src/Microsoft.ServiceFabric.Actors/Runtime/ActorService.cs @@ -15,7 +15,6 @@ namespace Microsoft.ServiceFabric.Actors.Runtime using Microsoft.ServiceFabric.Actors.Diagnostics; using Microsoft.ServiceFabric.Actors.Query; using Microsoft.ServiceFabric.Actors.Remoting; - using Microsoft.ServiceFabric.Actors.Runtime.Migration; using Microsoft.ServiceFabric.Services; using Microsoft.ServiceFabric.Services.Communication.Runtime; using Microsoft.ServiceFabric.Services.Runtime; @@ -44,8 +43,6 @@ public class ActorService : StatefulServiceBase, IActorService private ReplicaRole replicaRole; private Remoting.V2.Runtime.ActorMethodDispatcherMap methodDispatcherMapV2; - private IMigrationOrchestrator migrationOrchestrator; - /// /// Initializes a new instance of the class. /// @@ -62,51 +59,9 @@ public ActorService( Func stateManagerFactory = null, IActorStateProvider stateProvider = null, ActorServiceSettings settings = null) - : this( - context, - actorTypeInfo, - migrationSettings: null, - actorFactory, - stateManagerFactory, - stateProvider, - settings) - { - } - - internal ActorService( - StatefulServiceContext context, - ActorTypeInformation actorTypeInfo, - MigrationSettings migrationSettings, - Func actorFactory = null, - Func stateManagerFactory = null, - IActorStateProvider stateProvider = null, - ActorServiceSettings settings = null) - : this( - context, - actorTypeInfo, - MigrationReflectionHelper.GetMigrationOrchestrator( - stateProvider ?? ActorStateProviderHelper.CreateDefaultStateProvider(actorTypeInfo), - actorTypeInfo, - context, - migrationSettings), - actorFactory, - stateManagerFactory, - stateProvider ?? ActorStateProviderHelper.CreateDefaultStateProvider(actorTypeInfo), - settings) - { - } - - internal ActorService( - StatefulServiceContext context, - ActorTypeInformation actorTypeInfo, - IMigrationOrchestrator migrationOrchestrator, - Func actorFactory = null, - Func stateManagerFactory = null, - IActorStateProvider stateProvider = null, - ActorServiceSettings settings = null) : base( - context, - migrationOrchestrator != null ? migrationOrchestrator.GetMigrationActorStateProvider() : stateProvider) + context, + stateProvider) { this.actorTypeInformation = actorTypeInfo; this.stateProvider = (IActorStateProvider)this.StateProviderReplica; @@ -118,13 +73,6 @@ internal ActorService( this.actorManagerAdapter = new ActorManagerAdapter { ActorManager = new MockActorManager(this) }; this.replicaRole = ReplicaRole.Unknown; - if (migrationOrchestrator != null) - { - // Migration initialization - this.migrationOrchestrator = migrationOrchestrator; - this.migrationOrchestrator.RegisterCompletionCallback(this.StartRemindersIfNeededAsync); - } - ActorTelemetry.ActorServiceInitializeEvent( this.ActorManager.ActorService.Context, this.StateProviderReplica.GetType().ToString()); @@ -195,36 +143,6 @@ internal IActorManager ActorManager get { return this.actorManagerAdapter.ActorManager; } } - #region Migration - internal bool AreActorCallsAllowed - { - get - { - if (this.migrationOrchestrator != null) - { - return this.migrationOrchestrator.AreActorCallsAllowed(); - } - - return true; - } - } - - internal bool IsActorCallToBeForwarded - { - get - { - if (this.migrationOrchestrator != null) - { - return this.migrationOrchestrator.IsActorCallToBeForwarded(); - } - - return false; - } - } - - internal IMigrationOrchestrator MigrationOrchestrator { get => this.migrationOrchestrator; } - #endregion Migration - #region IActorService Members /// @@ -332,21 +250,6 @@ internal void InitializeInternal(ActorMethodFriendlyNameBuilder methodNameBuilde new Actors.Remoting.V2.Runtime.ActorMethodDispatcherMap(this.ActorTypeInformation); } - #region Migration - internal bool IsConfiguredForMigration() - { - return this.migrationOrchestrator != null; - } - - internal void ThrowIfActorCallsDisallowed() - { - if (this.migrationOrchestrator != null) - { - this.migrationOrchestrator.ThrowIfActorCallsDisallowed(); - } - } - #endregion Migration - #region StatefulServiceBase Overrides /// @@ -381,25 +284,9 @@ protected override IEnumerable CreateServiceReplicaListe } } - this.AddMigrationListener(serviceReplicaListeners); - return serviceReplicaListeners; } - /// - /// Adds migration specific listeners. - /// - /// Existing listener list. - /// To be used when CreateServiceReplicaListeners() is overriden by Custom implementation of Actor Service. - protected void AddMigrationListener(IList serviceReplicaListeners) - { - // Add migration endpoint - if (this.migrationOrchestrator != null) - { - serviceReplicaListeners.Add(new ServiceReplicaListener(_ => this.migrationOrchestrator.GetMigrationCommunicationListener(), Migration.Constants.MigrationListenerName)); - } - } - /// /// Overrides . /// @@ -418,14 +305,7 @@ protected void AddMigrationListener(IList serviceReplica /// protected override async Task RunAsync(CancellationToken cancellationToken) { - if (this.migrationOrchestrator != null) - { - await this.migrationOrchestrator.StartMigrationAsync(false, cancellationToken); - } - else - { - await this.ActorManager.StartLoadingRemindersAsync(cancellationToken); - } + await this.ActorManager.StartLoadingRemindersAsync(cancellationToken); } /// diff --git a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/AmbiguousActorIdResolverAttribute.cs b/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/AmbiguousActorIdResolverAttribute.cs deleted file mode 100644 index 669e43dd..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/AmbiguousActorIdResolverAttribute.cs +++ /dev/null @@ -1,40 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Runtime.Migration -{ - using System; - using System.Collections.Generic; - using System.Reflection; - - /// - /// Represents the class is an implementation of . This implementation will be used to resolve ambigious actor storage keys. - /// There can be more than one class annotated with this attribute. In that case, all the resolvers will be tried in order. - /// - [AttributeUsage(AttributeTargets.Class, Inherited = false)] - public sealed class AmbiguousActorIdResolverAttribute : Attribute - { - /// - /// Initializes a new instance of the class. - /// - public AmbiguousActorIdResolverAttribute() - { - } - - internal static IEnumerable GetTypesWithAttribute() - { - // TODO: Is checking entry assembly sufficient? - var assembly = Assembly.GetEntryAssembly(); - - foreach (Type type in assembly.GetTypes()) - { - if (type.GetCustomAttributes(typeof(AmbiguousActorIdResolverAttribute), true).Length > 0) - { - yield return type; - } - } - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/Constants.cs b/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/Constants.cs deleted file mode 100644 index baea81a7..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/Constants.cs +++ /dev/null @@ -1,13 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Runtime.Migration -{ - internal static class Constants - { - internal static readonly string MigrationListenerName = "Migration Listener"; - internal static readonly string ForwardRequestHeaderName = "ActorRequestForwarded"; - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/IAmbiguousActorIdResolver.cs b/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/IAmbiguousActorIdResolver.cs deleted file mode 100644 index 942a85ee..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/IAmbiguousActorIdResolver.cs +++ /dev/null @@ -1,22 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Runtime.Migration -{ - /// - /// Interface to resolve actorId from storage key incase there is any ambiguity. - /// The implementation should have a default constructor. - /// - public interface IAmbiguousActorIdResolver - { - /// - /// Resolves actor id from storage key. - /// - /// Underscore delimited actor id and state name(Ex, MyActorId_MyStateName) - /// Resolved Actor id. - /// True if resolved, false otherwise. - bool TryResolveActorIdAndStateName(string key, out string actorId); - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/IMigrationOrchestrator.cs b/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/IMigrationOrchestrator.cs deleted file mode 100644 index a9e6a090..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/IMigrationOrchestrator.cs +++ /dev/null @@ -1,100 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Runtime.Migration -{ - using System; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.Migration; - using Microsoft.ServiceFabric.Services.Communication.Runtime; - using Microsoft.ServiceFabric.Services.Remoting.V2.Runtime; - - /// - /// Interface definition for migraiton operations./>. - /// - internal interface IMigrationOrchestrator - { - /// - /// Gets the Migration ready actor state provider. - /// - /// Migration ready actor state provider. - public IActorStateProvider GetMigrationActorStateProvider(); - - /// - /// Gets the communication listener to opne migration endpoint. - /// - /// Migration specific communication listener. - public ICommunicationListener GetMigrationCommunicationListener(); - - /// - /// Gets the message handler that forwards requests when the current service is unable to service the request. - /// - /// Actor service. - /// Original message handler. - /// Request forwarder factory. - /// Request forwardable message handler. - public IServiceRemotingMessageHandler GetMessageHandler(ActorService actorService, IServiceRemotingMessageHandler messageHandler, Func requestForwarderFactory); - - /// - /// Starts the migration operation. - /// - /// Is user triggered operation. - /// Token to signal cancellation on long running taks. - /// A task that represents the asynchronous migration operation. - public Task StartMigrationAsync(bool userTriggered, CancellationToken cancellationToken); - - /// - /// Starts the downtime phase. - /// For source service, downtime phase indicates unavailability for any actor operations. - /// For target service, downtime phase indicates catching up final sequence numbers from source service - /// - /// Is user triggered operation. - /// Token to signal cancellation on long running taks. - /// A task that represents the asynchronous migration operation. - public Task StartDowntimeAsync(bool userTriggered, CancellationToken cancellationToken); - - /// - /// Aborts the migration workflow. - /// - /// Is user triggered operation. - /// Token to signal cancellation on long running taks. - /// A task that represents the asynchronous migration operation. - public Task AbortMigrationAsync(bool userTriggered, CancellationToken cancellationToken); - - /// - /// Gets the actor service state. - /// A true value indicates state provider is in a state to accept read/write operation. - /// A false value indicates state provider is either not ready yet or in reject state post migration. - /// - /// - /// A True result indicates actor calls are allowed on the actor service, false otherwise. - /// - public bool AreActorCallsAllowed(); - - /// - /// Is actor call to be forwarded if the current actor service cannot service the request. - /// - /// True if the request needs to be forwarded, false otherwise. - public bool IsActorCallToBeForwarded(); - - /// - /// Throws migration exception if actor calls are not allowed. - /// - public void ThrowIfActorCallsDisallowed(); - - /// - /// Gets the migration start mode. - /// - /// Return true if the MigrationMode is Auto, false otherwise. - public bool IsAutoStartMigration(); - - /// - /// Register Migration completion callback. - /// - /// Completion callback - public void RegisterCompletionCallback(Func completionCallback); - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationMode.cs b/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationMode.cs deleted file mode 100644 index 005a8d32..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationMode.cs +++ /dev/null @@ -1,30 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Runtime.Migration -{ - using System; - - /// - /// Migration Mode. - /// - public enum MigrationMode - { - /// - /// Automatic Mode. - /// Migration is started automatically after the Target service is up. - /// Downtime on the Source service is also invoked automatically when the Downtime threshold is met. - /// - Auto, - - /// - /// Manual Mode. - /// Migration is not started automatically. User needs to use StartMigration Web Api partition wise to start migration. - /// Similarly Downtime is not invoked automaticaly. User needs to use StartDowntime Web Api partition wise to start downtime. - /// GetMigrationStatus Web Api can be used to check the current status of the migration and decide whether to invoke downtime or not. - /// - Manual, - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationReflectionHelper.cs b/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationReflectionHelper.cs deleted file mode 100644 index 284db300..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationReflectionHelper.cs +++ /dev/null @@ -1,90 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Runtime.Migration -{ - using System; - using System.Fabric; - using System.Reflection; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.Generator; - - internal static class MigrationReflectionHelper - { - private static readonly string TraceType = typeof(MigrationReflectionHelper).Name; - - public static IMigrationOrchestrator GetMigrationOrchestrator( - IActorStateProvider stateProvider, - ActorTypeInformation actorTypeInfo, - StatefulServiceContext serviceContext, - MigrationSettings settings) - { - try - { - var migrationAttribute = StateMigrationAttribute.Get(actorTypeInfo.ImplementationType); - if (migrationAttribute.StateMigration == StateMigration.None) - { - return null; - } - - MigrationSettings migrationSettings = settings; - if (migrationSettings == null) - { - migrationSettings = new MigrationSettings(); - migrationSettings.LoadFrom( - serviceContext.CodePackageActivationContext, - ActorNameFormat.GetMigrationConfigSectionName(actorTypeInfo.ImplementationType)); - } - - string reflectionClassFQN; - if (migrationAttribute.StateMigration == StateMigration.Source) - { - reflectionClassFQN = migrationSettings.MigrationSourceOrchestrator; - } - else - { - reflectionClassFQN = migrationSettings.MigrationTargetOrchestrator; - } - - var tokens = reflectionClassFQN.Split(','); - if (tokens.Length != 2) - { - throw new ArgumentException("Migration<>Orchestrator is invalid. Valid format is , "); - } - - var className = tokens[0].Trim(); - var assemblyName = tokens[1].Trim(); - var currentAssembly = typeof(MigrationReflectionHelper).GetTypeInfo().Assembly; - var actorsMigrationAssembly = new AssemblyName - { - Name = assemblyName, - Version = currentAssembly.GetName().Version, -#if !DotNetCoreClr - CultureInfo = currentAssembly.GetName().CultureInfo, -#endif - ProcessorArchitecture = currentAssembly.GetName().ProcessorArchitecture, - }; - - actorsMigrationAssembly.SetPublicKeyToken(currentAssembly.GetName().GetPublicKeyToken()); - - var orchestratorType = Type.GetType($"{className}, {assemblyName}", true); - - // TODO provide a singleton pattern or initialization - return (IMigrationOrchestrator)Activator.CreateInstance(orchestratorType, stateProvider, actorTypeInfo, serviceContext, migrationSettings); - } - catch (Exception ex) - { - ActorTrace.Source.WriteErrorWithId( - TraceType, - serviceContext.TraceId, - $"Error encountered while creating migration orchestrator : {ex}"); - //// TODO: Partition health warning - } - - return null; - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationSettings.cs b/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationSettings.cs deleted file mode 100644 index b263aa39..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationSettings.cs +++ /dev/null @@ -1,103 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ -namespace Microsoft.ServiceFabric.Actors.Runtime.Migration -{ - using System; - using System.Fabric; - using System.Runtime.Serialization; - using Microsoft.ServiceFabric.Actors.Generator; - using Microsoft.ServiceFabric.Actors.Migration.Exceptions; - - [DataContract] - internal class MigrationSettings - { - private static readonly string TraceType = typeof(MigrationSettings).ToString(); - - public MigrationSettings() - { - this.MigrationSourceOrchestrator = "Microsoft.ServiceFabric.Actors.KVSToRCMigration.SourceMigrationOrchestrator, Microsoft.ServiceFabric.Actors.KVSToRCMigration"; - this.MigrationTargetOrchestrator = "Microsoft.ServiceFabric.Actors.KVSToRCMigration.TargetMigrationOrchestrator, Microsoft.ServiceFabric.Actors.KVSToRCMigration"; - this.MigrationMode = MigrationMode.Auto; - } - - [DataMember] - public Uri SourceServiceUri { get; set; } - - [DataMember] - public Uri TargetServiceUri { get; set; } - - [DataMember] - public MigrationMode MigrationMode { get; set; } - - [DataMember] - internal string MigrationSourceOrchestrator { get; set; } - - [DataMember] - internal string MigrationTargetOrchestrator { get; set; } - - internal string MigrationConfigSectionName { get; private set; } - - internal virtual void LoadFrom(ICodePackageActivationContext codePackageActivationContext, string configSectionName = "MigrationConfig") - { - this.MigrationConfigSectionName = configSectionName; - var configPackageName = ActorNameFormat.GetConfigPackageName(); - try - { - var configPackageObj = codePackageActivationContext.GetConfigurationPackageObject(configPackageName); - if (configPackageObj.Settings.Sections.Contains(configSectionName)) - { - var migrationSettings = configPackageObj.Settings.Sections[configSectionName]; - if (migrationSettings.Parameters.Contains("SourceServiceUri")) - { - this.SourceServiceUri = new Uri(migrationSettings.Parameters["SourceServiceUri"].Value); - } - - if (migrationSettings.Parameters.Contains("TargetServiceUri")) - { - this.TargetServiceUri = new Uri(migrationSettings.Parameters["TargetServiceUri"].Value); - } - - if (migrationSettings.Parameters.Contains("MigrationMode")) - { - this.MigrationMode = (MigrationMode)Enum.Parse(typeof(MigrationMode), migrationSettings.Parameters["MigrationMode"].Value); - } - } - else - { - var errorMsg = $"Section {configSectionName} not found in settings file."; - ActorTrace.Source.WriteError(TraceType, errorMsg); - - throw new InvalidMigrationConfigException(errorMsg); - } - } - catch (Exception e) - { - var errorMsg = $"Section {configSectionName} not found in settings file."; - ActorTrace.Source.WriteError(TraceType, errorMsg); - - throw new InvalidMigrationConfigException(errorMsg, e); - } - } - - internal virtual void Validate(bool isSource) - { - if (!isSource && (this.SourceServiceUri == null || !this.SourceServiceUri.AbsoluteUri.StartsWith("fabric:/", StringComparison.InvariantCultureIgnoreCase))) - { - var errorMsg = $"SourceServiceUri is either null or valid. Add SourceServiceUri section in {this.MigrationConfigSectionName} section of settings file."; - ActorTrace.Source.WriteError(TraceType, errorMsg); - - throw new InvalidMigrationConfigException(errorMsg); - } - - if (isSource && this.TargetServiceUri != null && !this.TargetServiceUri.AbsoluteUri.StartsWith("fabric:/", StringComparison.InvariantCultureIgnoreCase)) - { - var errorMsg = $"TargetServiceUri is valid."; - ActorTrace.Source.WriteError(TraceType, errorMsg); - - throw new InvalidMigrationConfigException(errorMsg); - } - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationTelemetry.cs b/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationTelemetry.cs deleted file mode 100644 index fa0c03d1..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationTelemetry.cs +++ /dev/null @@ -1,106 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Runtime.Migration -{ - using System.Fabric; - using Microsoft.ServiceFabric.Services; - - internal static class MigrationTelemetry - { - private static readonly ActorEventSource EventSource = ActorEventSource.Instance; - - internal static void MigrationStartEvent(StatefulServiceContext context, string settingsJson) - { - EventSource.MigrationStartEvent( - MigrationTelemetryConstants.MigrationStartEvent, - TelemetryConstants.OsType, - TelemetryConstants.RuntimePlatform, - context.PartitionId.ToString(), - context.ReplicaId.ToString(), - context.ServiceName.OriginalString, - context.ServiceTypeName, - context.CodePackageActivationContext.ApplicationName, - context.CodePackageActivationContext.ApplicationTypeName, - settingsJson); - } - - internal static void MigrationEndEvent(StatefulServiceContext context, string resultJson) - { - EventSource.MigrationEndEvent( - MigrationTelemetryConstants.MigrationEndEvent, - TelemetryConstants.OsType, - TelemetryConstants.RuntimePlatform, - context.PartitionId.ToString(), - context.ReplicaId.ToString(), - context.ServiceName.OriginalString, - context.ServiceTypeName, - context.CodePackageActivationContext.ApplicationName, - context.CodePackageActivationContext.ApplicationTypeName, - resultJson); - } - - internal static void MigrationPhaseStartEvent(StatefulServiceContext context, string inputJson) - { - EventSource.MigrationPhaseStartEvent( - MigrationTelemetryConstants.MigrationPhaseStartEvent, - TelemetryConstants.OsType, - TelemetryConstants.RuntimePlatform, - context.PartitionId.ToString(), - context.ReplicaId.ToString(), - context.ServiceName.OriginalString, - context.ServiceTypeName, - context.CodePackageActivationContext.ApplicationName, - context.CodePackageActivationContext.ApplicationTypeName, - inputJson); - } - - internal static void MigrationPhaseEndEvent(StatefulServiceContext context, string resultJson) - { - EventSource.MigrationPhaseEndEvent( - MigrationTelemetryConstants.MigrationPhaseEndEvent, - TelemetryConstants.OsType, - TelemetryConstants.RuntimePlatform, - context.PartitionId.ToString(), - context.ReplicaId.ToString(), - context.ServiceName.OriginalString, - context.ServiceTypeName, - context.CodePackageActivationContext.ApplicationName, - context.CodePackageActivationContext.ApplicationTypeName, - resultJson); - } - - internal static void MigrationFailureEvent(StatefulServiceContext context, string phase, string errorMsg) - { - EventSource.MigrationFailureEvent( - MigrationTelemetryConstants.MigrationFailureEvent, - TelemetryConstants.OsType, - TelemetryConstants.RuntimePlatform, - context.PartitionId.ToString(), - context.ReplicaId.ToString(), - context.ServiceName.OriginalString, - context.ServiceTypeName, - context.CodePackageActivationContext.ApplicationName, - context.CodePackageActivationContext.ApplicationTypeName, - phase, - errorMsg); - } - - internal static void MigrationAbortEvent(StatefulServiceContext context, bool userTriggered) - { - EventSource.MigrationAbortEvent( - MigrationTelemetryConstants.MigrationAbortEvent, - TelemetryConstants.OsType, - TelemetryConstants.RuntimePlatform, - context.PartitionId.ToString(), - context.ReplicaId.ToString(), - context.ServiceName.OriginalString, - context.ServiceTypeName, - context.CodePackageActivationContext.ApplicationName, - context.CodePackageActivationContext.ApplicationTypeName, - userTriggered); - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationTelemetryConstants.cs b/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationTelemetryConstants.cs deleted file mode 100644 index 49874611..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/MigrationTelemetryConstants.cs +++ /dev/null @@ -1,17 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Runtime.Migration -{ - internal class MigrationTelemetryConstants - { - internal static readonly string MigrationStartEvent = "TelemetryEvents.MigrationStartOrResumeEvent"; - internal static readonly string MigrationEndEvent = "TelemetryEvents.MigrationEndEvent"; - internal static readonly string MigrationPhaseStartEvent = "TelemetryEvents.MigrationPhaseStartOrResumeEvent"; - internal static readonly string MigrationPhaseEndEvent = "TelemetryEvents.MigrationPhaseEndEvent"; - internal static readonly string MigrationFailureEvent = "TelemetryEvents.MigrationFailureEvent"; - internal static readonly string MigrationAbortEvent = "TelemetryEvents.MigrationAbortEvent"; - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/RequestForwardableRemotingDispatcher.cs b/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/RequestForwardableRemotingDispatcher.cs deleted file mode 100644 index 21ba6799..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/RequestForwardableRemotingDispatcher.cs +++ /dev/null @@ -1,71 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Runtime.Migration -{ - using System; - using System.Threading.Tasks; - using Microsoft.ServiceFabric.Actors.Migration; - using Microsoft.ServiceFabric.Actors.Migration.Exceptions; - using Microsoft.ServiceFabric.Services.Remoting.Runtime; - using Microsoft.ServiceFabric.Services.Remoting.V2; - using Microsoft.ServiceFabric.Services.Remoting.V2.Runtime; - - internal class RequestForwardableRemotingDispatcher : IServiceRemotingMessageHandler, IDisposable - { - private static readonly string TraceType = typeof(RequestForwardableRemotingDispatcher).Name; - private IServiceRemotingMessageHandler actualMessageHandler; - private ActorService actorService; - private IRequestForwarder requestForwarder; - private ServiceRemotingCancellationHelper cancellationHelper; - private string traceId; - - public RequestForwardableRemotingDispatcher(ActorService actorService, IServiceRemotingMessageHandler actualMessageHandler, IRequestForwarder requestForwarder) - { - this.actorService = actorService; - this.actualMessageHandler = actualMessageHandler; - this.requestForwarder = requestForwarder; - this.traceId = this.actorService.Context.TraceId; - this.cancellationHelper = new ServiceRemotingCancellationHelper(this.actorService.Context.TraceId); - } - - public IServiceRemotingMessageBodyFactory GetRemotingMessageBodyFactory() - { - return this.actualMessageHandler.GetRemotingMessageBodyFactory(); - } - - public void HandleOneWayMessage(IServiceRemotingRequestMessage requestMessage) - { - this.actualMessageHandler.HandleOneWayMessage(requestMessage); - } - - public async Task HandleRequestResponseAsync(IServiceRemotingRequestContext requestContext, IServiceRemotingRequestMessage requestMessage) - { - if (this.actorService.IsActorCallToBeForwarded) - { - if (requestMessage.GetHeader().TryGetHeaderValue(Runtime.Migration.Constants.ForwardRequestHeaderName, out var val)) - { - var errorMsg = $"Both migration services are in Downtime. Retry the call after Downtime phase is completed."; - ActorTrace.Source.WriteInfoWithId( - TraceType, - this.traceId, - errorMsg); - - throw new ActorCallsDisallowedException(errorMsg); - } - - return await this.requestForwarder.ForwardRequestResponseAsync(requestContext, requestMessage); - } - - // User could observe ActorCallsDisallowedException in a race situation where service moved to downtime phase after dispatching the request. - return await this.actualMessageHandler.HandleRequestResponseAsync(requestContext, requestMessage); - } - - public void Dispose() - { - ((IDisposable)this.actualMessageHandler).Dispose(); - } - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/StateMigration.cs b/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/StateMigration.cs deleted file mode 100644 index 7735ea69..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/StateMigration.cs +++ /dev/null @@ -1,28 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Runtime.Migration -{ - /// - /// Indicates actor service migration state. - /// - public enum StateMigration - { - /// - /// Actor service is not migration ready. - /// - None = 0, - - /// - /// Actor service is migration ready and configured as source service. - /// - Source = 1, - - /// - /// Actor service is migration ready and configured as target service. - /// - Target = 2, - } -} diff --git a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/StateMigrationAttribute.cs b/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/StateMigrationAttribute.cs deleted file mode 100644 index d5162fc9..00000000 --- a/src/Microsoft.ServiceFabric.Actors/Runtime/Migration/StateMigrationAttribute.cs +++ /dev/null @@ -1,47 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See License.txt in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.ServiceFabric.Actors.Runtime.Migration -{ - using System; - using System.Collections.Generic; - using System.Reflection; - - /// - /// Indicates whether the actor service participates in state migration. - /// - [AttributeUsage(AttributeTargets.Class, Inherited = false)] - public sealed class StateMigrationAttribute : Attribute - { - /// - /// Initializes a new instance of the class. - /// - /// Indicates an actor service is source or target for migration. - public StateMigrationAttribute(StateMigration stateMigration) - { - this.StateMigration = stateMigration; - } - - /// - /// Gets the enum representing type of actor service migration. - /// - /// representing type of state store to use for the actor. - public StateMigration StateMigration { get; private set; } - - internal static StateMigrationAttribute Get(Type actorType) - { - var attribute = new StateMigrationAttribute(StateMigration.None); - - var attributes = actorType.GetTypeInfo().GetCustomAttributes(typeof(StateMigrationAttribute), false); - var enumerator = attributes.GetEnumerator(); - if (enumerator.MoveNext()) - { - attribute.StateMigration = ((StateMigrationAttribute)enumerator.Current).StateMigration; - } - - return attribute; - } - } -} diff --git a/src/netstandard/Microsoft.ServiceFabric.Actors/Microsoft.ServiceFabric.Actors_netstandard.csproj b/src/netstandard/Microsoft.ServiceFabric.Actors/Microsoft.ServiceFabric.Actors_netstandard.csproj index 55add375..ca6d6ab2 100644 --- a/src/netstandard/Microsoft.ServiceFabric.Actors/Microsoft.ServiceFabric.Actors_netstandard.csproj +++ b/src/netstandard/Microsoft.ServiceFabric.Actors/Microsoft.ServiceFabric.Actors_netstandard.csproj @@ -13,8 +13,6 @@ - -