Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add regional datastore service #2180

Merged
merged 8 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/PortingAssistant.Client.Client/DependencyInjection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public static void AddAssessment(this IServiceCollection serviceCollection, Port
serviceCollection.AddTransient<ICompatibilityChecker, Compatibility.Core.Checkers.SdkCompatibilityChecker>();
serviceCollection.AddTransient<ICompatibilityChecker, Compatibility.Core.Checkers.PortabilityAnalyzerCompatibilityChecker>();
serviceCollection.AddTransient<IHttpService, Compatibility.Common.Utils.HttpService>();
serviceCollection.AddTransient<IRegionalDatastoreService, Compatibility.Common.Utils.RegionalDatastoreService>();
}

public static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace PortingAssistant.Compatibility.Common.Interface
{
public interface IRegionalDatastoreService
{
public Task<Stream?> DownloadRegionalS3FileAsync(string fileToDownload, bool isRegionalCall = false);

public Task<HashSet<string>> ListRegionalNamespacesObjectAsync(bool isRegionalCall = false);

public Task<Stream> DownloadGitHubFileAsync(string fileToDownload);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using Amazon;
using Amazon.S3;
using PortingAssistant.Compatibility.Common.Interface;
using Amazon.S3.Model;
using Microsoft.Extensions.Logging;

namespace PortingAssistant.Compatibility.Common.Utils
{
public class RegionalDatastoreService : IRegionalDatastoreService
{
private readonly IHttpService _httpService;
private readonly AmazonS3Client _s3Client;
private readonly bool _isLambdaEnvSetup;
private readonly string _regionaS3BucketName;
private readonly ILogger<RegionalDatastoreService> _logger;

public RegionalDatastoreService(
IHttpService httpService,
ILogger<RegionalDatastoreService> logger
)
{
_httpService = httpService;
_logger = logger;
string region = Environment.GetEnvironmentVariable("AWS_REGION");

if (!string.IsNullOrEmpty(region))
{
_isLambdaEnvSetup = true;
_regionaS3BucketName = $"portingassistant-datastore-{region}";
_s3Client = new AmazonS3Client(RegionEndpoint.GetBySystemName(region));
mrkdeng marked this conversation as resolved.
Show resolved Hide resolved
}
}

public async Task<Stream> DownloadGitHubFileAsync(string fileToDownload)
{
return await _httpService.DownloadGitHubFileAsync(fileToDownload);
}

public async Task<Stream?> DownloadRegionalS3FileAsync(string fileToDownload, bool isRegionalCall = false)
{
try
{
_logger.LogInformation($"Downloading {fileToDownload} from regional S3 " + _regionaS3BucketName);
if (isRegionalCall && _isLambdaEnvSetup)
{
GetObjectRequest request = new GetObjectRequest
{
BucketName = _regionaS3BucketName,
Key = fileToDownload
};
using (GetObjectResponse response = await _s3Client.GetObjectAsync(request))
mrkdeng marked this conversation as resolved.
Show resolved Hide resolved
{
_logger.LogInformation($"Downloaded {fileToDownload} from " + _regionaS3BucketName);
return response.ResponseStream;
}

}
else
{
return await _httpService.DownloadS3FileAsync(fileToDownload);
}
}
catch (Exception ex)
{
_logger.LogError($"fail to download {fileToDownload}. " + ex.Message);
return null;
}

}

// TODO: This method could be deprecated since sdk namespaces won't change after each feature release
public Task<HashSet<string>> ListRegionalNamespacesObjectAsync(bool isRegionalCall = false)
{
return _httpService.ListNamespacesObjectAsync();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ namespace PortingAssistant.Compatibility.Core.Checkers
{
public class ExternalCompatibilityChecker : ICompatibilityChecker
{
private readonly IHttpService _httpService;
private readonly IRegionalDatastoreService _regionalDatastoreService;
private static readonly int _maxProcessConcurrency = 3;
private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(_maxProcessConcurrency);
private ILogger _logger;

public virtual PackageSourceType CompatibilityCheckerType => PackageSourceType.NUGET;

public ExternalCompatibilityChecker(
IHttpService httpService,
IRegionalDatastoreService regionalDatastoreService,
ILogger<ExternalCompatibilityChecker> logger)
{
_httpService = httpService;
_regionalDatastoreService = regionalDatastoreService;
_logger = logger;
}

Expand Down Expand Up @@ -80,7 +80,7 @@ private async void ProcessCompatibility( IEnumerable<PackageVersionPair> package
{
HashSet<string>? apis = null; // OriginalDefinition
PackageDetails packageDetails = null;
packageDetails = await GetPackageDetailFromS3(fileToDownload, _httpService, apis);
packageDetails = await GetPackageDetailFromS3(fileToDownload, _regionalDatastoreService, apis);

if (packageDetails == null || packageDetails.Name == null || !string.Equals(packageDetails.Name.Trim().ToLower(),
packageToDownload.Trim().ToLower(), StringComparison.OrdinalIgnoreCase))
Expand Down Expand Up @@ -190,9 +190,9 @@ public class PackageFromS3
}


public async Task<PackageDetails> GetPackageDetailFromS3(string fileToDownload, IHttpService httpService, HashSet<string> apis = null)
public async Task<PackageDetails> GetPackageDetailFromS3(string fileToDownload, IRegionalDatastoreService regionalDatastoreService, HashSet<string> apis = null)
mrkdeng marked this conversation as resolved.
Show resolved Hide resolved
{
using var stream = await httpService.DownloadS3FileAsync(fileToDownload);
using var stream = await regionalDatastoreService.DownloadRegionalS3FileAsync(fileToDownload, isRegionalCall: true);
mrkdeng marked this conversation as resolved.
Show resolved Hide resolved
if (stream == null)
{
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ public class NugetCompatibilityChecker : ExternalCompatibilityChecker
public override PackageSourceType CompatibilityCheckerType => PackageSourceType.NUGET;
public ILogger _logger;
public NugetCompatibilityChecker(
IHttpService httpService,
IRegionalDatastoreService regionalDatastoreService,
ILogger<NugetCompatibilityChecker> logger
)
: base(httpService, logger)
: base(regionalDatastoreService, logger)
{
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace PortingAssistant.Compatibility.Core.Checkers
public class PortabilityAnalyzerCompatibilityChecker : ICompatibilityChecker
{
private const string NamespaceLookupFile = "microsoftlibs.namespace.lookup.json";
private readonly IHttpService _httpService;
private readonly IRegionalDatastoreService _regionalDatastoreService;
private Dictionary<string, string> _manifest;
private static readonly int _maxProcessConcurrency = 3;
private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(_maxProcessConcurrency);
Expand All @@ -27,11 +27,11 @@ public class PortabilityAnalyzerCompatibilityChecker : ICompatibilityChecker
/// </summary>
/// <param name="httpService">The transferUtility object to read data from S3</param>
public PortabilityAnalyzerCompatibilityChecker(
IHttpService httpService,
IRegionalDatastoreService regionalDatastoreService,
ILogger<PortabilityAnalyzerCompatibilityChecker> logger
)
{
_httpService = httpService;
_regionalDatastoreService = regionalDatastoreService;
_manifest = null;
_logger = logger;
}
Expand Down Expand Up @@ -124,7 +124,7 @@ private async void ProcessCompatibility( IEnumerable<PackageVersionPair> package
try
{
_logger.LogInformation($"Downloading {url.Key} from {CompatibilityCheckerType}");
using var stream = await _httpService.DownloadS3FileAsync(url.Key);
using var stream = await _regionalDatastoreService.DownloadRegionalS3FileAsync(url.Key, isRegionalCall: true);
using var gzipStream = new GZipStream(stream, CompressionMode.Decompress);
using var streamReader = new StreamReader(gzipStream);
var packageFromS3 = JsonConvert.DeserializeObject<PackageFromS3>(streamReader.ReadToEnd());
Expand Down Expand Up @@ -185,7 +185,7 @@ private async void ProcessCompatibility( IEnumerable<PackageVersionPair> package
private async Task<Dictionary<string, string>> GetManifestAsync()
{
// Download the lookup file "microsoftlibs.namespace.lookup.json" from S3.
using var stream = await _httpService.DownloadS3FileAsync(NamespaceLookupFile);
using var stream = await _regionalDatastoreService.DownloadRegionalS3FileAsync(NamespaceLookupFile, isRegionalCall: true);
using var streamReader = new StreamReader(stream);
var result = streamReader.ReadToEnd();
return JsonConvert.DeserializeObject<JObject>(result).ToObject<Dictionary<string, string>>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ public class SdkCompatibilityChecker : ExternalCompatibilityChecker
public override PackageSourceType CompatibilityCheckerType => PackageSourceType.SDK;
private ILogger _logger;
public SdkCompatibilityChecker(
IHttpService httpService,
IRegionalDatastoreService regionalDatastoreService,
ILogger<SdkCompatibilityChecker> logger)
: base(httpService, logger)
: base(regionalDatastoreService, logger)
{
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ namespace PortingAssistant.Compatibility.Core
// The CompatibilityCheckerRecommendationActionHandler checks and gets recommendation action file details ("namespace.json") from the datastore, if any.
public class CompatibilityCheckerRecommendationActionHandler : ICompatibilityCheckerRecommendationActionHandler
{
private readonly IHttpService _httpService;
private readonly IRegionalDatastoreService _regionalDatastoreService;
private const string _recommendationFileSuffix = ".json";
private ILogger _logger;
public PackageSourceType CompatibilityCheckerType => PackageSourceType.RECOMMENDATION;


public CompatibilityCheckerRecommendationActionHandler(
IHttpService httpService,
IRegionalDatastoreService regionalDatastoreService,
ILogger<CompatibilityCheckerRecommendationActionHandler> logger
)
{
_httpService = httpService;
_regionalDatastoreService = regionalDatastoreService;
_logger = logger;
}

Expand All @@ -39,7 +39,7 @@ public async Task<Dictionary<string, RecommendationActionFileDetails>> GetRecomm
Stream? stream = null;
try
{
stream = await _httpService.DownloadS3FileAsync(recommendationDownloadPath);
stream = await _regionalDatastoreService.DownloadRegionalS3FileAsync(recommendationDownloadPath, isRegionalCall: true);
using var streamReader = new StreamReader(stream);
var recommendationFromS3 = JsonConvert.DeserializeObject<RecommendationActionFileDetails>(await streamReader.ReadToEndAsync());
recommendationActionDetailsNamespaceDict.Add(namespaceName, recommendationFromS3);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using Amazon.S3;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Moq;
Expand All @@ -16,6 +17,7 @@
using PortingAssistant.Client.Common.Utils;
using PortingAssistant.Compatibility.Common.Interface;
using PortingAssistant.Compatibility.Common.Model;
using PortingAssistant.Compatibility.Common.Utils;
using PortingAssistant.Compatibility.Core;
using PortingAssistant.Compatibility.Core.Checkers;
using ILogger = NuGet.Common.ILogger;
Expand All @@ -26,6 +28,7 @@ public class PortingAssistantNuGetHandlerTest
{
private Mock<IHttpService> _httpService;
private Mock<IFileSystem> _fileSystem;
private IRegionalDatastoreService _regionalDatastoreService;
private ExternalCompatibilityChecker _externalPackagesCompatibilityChecker;
private PortabilityAnalyzerCompatibilityChecker _portabilityAnalyzerCompatibilityChecker;
private SdkCompatibilityChecker _sdkCompatibilityChecker;
Expand Down Expand Up @@ -205,6 +208,8 @@ public void OneTimeSetup()
{
//httpMessageHandler = new Mock<HttpMessageHandler>
_httpService = new Mock<IHttpService>();
var datastoreServiceLoggerMock = new Mock<ILogger<RegionalDatastoreService>>();
_regionalDatastoreService = new RegionalDatastoreService(_httpService.Object, datastoreServiceLoggerMock.Object);
_fileSystem = new Mock<IFileSystem>();
}

Expand Down Expand Up @@ -248,22 +253,22 @@ public void Setup()


_externalPackagesCompatibilityChecker = new ExternalCompatibilityChecker(
_httpService.Object,
_regionalDatastoreService,
NullLogger<ExternalCompatibilityChecker>.Instance
);

_portabilityAnalyzerCompatibilityChecker = new PortabilityAnalyzerCompatibilityChecker(
_httpService.Object,
_regionalDatastoreService,
NullLogger<PortabilityAnalyzerCompatibilityChecker>.Instance
);

_sdkCompatibilityChecker = new SdkCompatibilityChecker(
_httpService.Object,
_regionalDatastoreService,
NullLogger<SdkCompatibilityChecker>.Instance
);

_portabilityAnalyzerCompatibilityChecker = new PortabilityAnalyzerCompatibilityChecker(
_httpService.Object,
_regionalDatastoreService,
NullLogger<PortabilityAnalyzerCompatibilityChecker>.Instance
);

Expand Down Expand Up @@ -367,7 +372,7 @@ private ICompatibilityCheckerNuGetHandler GetCheckerWithException()
private ExternalCompatibilityChecker GetExternalPackagesCompatibilityChecker()
{
var externalChecker = new ExternalCompatibilityChecker(
_httpService.Object,
_regionalDatastoreService,
NullLogger<ExternalCompatibilityChecker>.Instance
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
using PortingAssistant.Compatibility.Core.Checkers;
using Assert = NUnit.Framework.Assert;
using Microsoft.Extensions.Logging;
using PortingAssistant.Compatibility.Common.Utils;
using Amazon.S3;

namespace PortingAssistant.Compatibility.Core.Tests.UnitTests
{

public class NugetHandlerTest
{
private Mock<IHttpService> _httpService;
private IRegionalDatastoreService _regionalDatastoreService;
private Mock<ICompatibilityCheckerNuGetHandler> _compatibilityCheckerNuGetHandler;
private NugetCompatibilityChecker _nugetCompatibilityChecker;
private PortabilityAnalyzerCompatibilityChecker _portabilityAnalyzerCompatibilityChecker;
Expand Down Expand Up @@ -67,6 +70,8 @@ public class NugetHandlerTest
public void OneTimeSetup()
{
_httpService = new Mock<IHttpService>();
var datastoreServiceLoggerMock = new Mock<ILogger<RegionalDatastoreService>>();
_regionalDatastoreService = new RegionalDatastoreService(_httpService.Object, datastoreServiceLoggerMock.Object);
}

[SetUp]
Expand Down Expand Up @@ -142,17 +147,17 @@ public void Setup()
_logger = Mock.Of<ILogger<ICompatibilityChecker>>();

_nugetCompatibilityChecker = new NugetCompatibilityChecker(
_httpService.Object,
_regionalDatastoreService,
Mock.Of<ILogger<NugetCompatibilityChecker>>()
);

_portabilityAnalyzerCompatibilityChecker = new PortabilityAnalyzerCompatibilityChecker(
_httpService.Object,
_regionalDatastoreService,
Mock.Of<ILogger<PortabilityAnalyzerCompatibilityChecker>>()
);

_sdkCompatibilityChecker = new SdkCompatibilityChecker(
_httpService.Object,
_regionalDatastoreService,
Mock.Of<ILogger<SdkCompatibilityChecker>>()
);

Expand Down Expand Up @@ -207,7 +212,7 @@ private ICompatibilityCheckerNuGetHandler GetCheckerWithException()
private NugetCompatibilityChecker GetExternalPackagesCompatibilityChecker()
{
var externalChecker = new NugetCompatibilityChecker(
_httpService.Object, Mock.Of<ILogger<NugetCompatibilityChecker>>());
_regionalDatastoreService, Mock.Of<ILogger<NugetCompatibilityChecker>>());

return externalChecker;
}
Expand Down
Loading