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

Bump to .NET8 and align code structure for Databricks #290

Merged
merged 11 commits into from
Mar 11, 2024
538 changes: 538 additions & 0 deletions source/Databricks/.editorconfig

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions source/Databricks/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<Project>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
<!-- RunAnalyzersDuringXxx: https://learn.microsoft.com/en-us/visualstudio/code-quality/disable-code-analysis?view=vs-2022#net-framework-projects -->
<RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
<RunAnalyzersDuringLiveAnalysis>true</RunAnalyzersDuringLiveAnalysis>
<!-- EnforceCodeStyleInBuild: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-8#enable-on-build -->
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<!--
Add stylecop for all projects (so long as they don't override Directory.Build.props) with a common ruleset.
See also: https://docs.microsoft.com/en-us/visualstudio/msbuild/customize-your-build?view=vs-2019#search-scope
-->
<ItemGroup>
<!--
IMPORTANT: Do NOT add NuGet package dependencies in this file, except for "StyleCop.Analyzers".
-->
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

<!--
Additional settings for specific rules (e.g. SA1200 specify namespaces must be placed correctly, the json file then defines what "correctly" means)
See also [stylecop.json](https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/Configuration.md)
-->
<AdditionalFiles Include="$(MSBuildThisFileDirectory)\..\stylecop.json"/>
</ItemGroup>
</Project>
4 changes: 4 additions & 0 deletions source/Databricks/documents/release-notes/release-notes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Databricks Release Notes

## Version 10.0.0

Bump to .NET 8.0 for TargetFramework.

## Version 9.0.2

Cancel statement if token cancellation is requested.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,93 +28,92 @@
using Moq.Protected;
using NodaTime;

namespace Energinet.DataHub.Core.Databricks.Jobs.IntegrationTests.Fixtures
namespace Energinet.DataHub.Core.Databricks.Jobs.IntegrationTests.Fixtures;

public sealed class HealthChecksFixture : IDisposable
{
public sealed class HealthChecksFixture : IDisposable
private readonly TestServer _server;

public HealthChecksFixture()
{
private readonly TestServer _server;

public HealthChecksFixture()
{
var webHostBuilder = CreateWebHostBuilder();
_server = new TestServer(webHostBuilder);
HttpClient = _server.CreateClient();
}

public HttpClient HttpClient { get; }

public void Dispose()
{
_server.Dispose();
}

private static IWebHostBuilder CreateWebHostBuilder()
{
return new WebHostBuilder()
.ConfigureServices(services =>
{
services.AddOptions<DatabricksJobsOptions>().Configure(options =>
{
options.WarehouseId = "baz";
options.WorkspaceToken = "bar";
options.WorkspaceUrl = "https://foo.com";
options.DatabricksHealthCheckStartHour = 0;
options.DatabricksHealthCheckEndHour = 23;
});

services.AddRouting();

RegisterHttpClientFactoryMock(services);
RegisterJobsApiClientMock(services);

services.AddScoped(typeof(IClock), _ => SystemClock.Instance);

services.AddHealthChecks()
.AddLiveCheck()
.AddDatabricksJobsApiHealthCheck();
})
.Configure(app =>
var webHostBuilder = CreateWebHostBuilder();
_server = new TestServer(webHostBuilder);
HttpClient = _server.CreateClient();
}

public HttpClient HttpClient { get; }

public void Dispose()
{
_server.Dispose();
}

private static IWebHostBuilder CreateWebHostBuilder()
{
return new WebHostBuilder()
.ConfigureServices(services =>
{
services.AddOptions<DatabricksJobsOptions>().Configure(options =>
{
app.UseRouting();
options.WarehouseId = "baz";
options.WorkspaceToken = "bar";
options.WorkspaceUrl = "https://foo.com";
options.DatabricksHealthCheckStartHour = 0;
options.DatabricksHealthCheckEndHour = 23;
});

services.AddRouting();

RegisterHttpClientFactoryMock(services);
RegisterJobsApiClientMock(services);

services.AddScoped(typeof(IClock), _ => SystemClock.Instance);

app.UseEndpoints(endpoints =>
{
endpoints.MapLiveHealthChecks();
endpoints.MapReadyHealthChecks();
});
services.AddHealthChecks()
.AddLiveCheck()
.AddDatabricksJobsApiHealthCheck();
})
.Configure(app =>
{
app.UseRouting();

app.UseEndpoints(endpoints =>
{
endpoints.MapLiveHealthChecks();
endpoints.MapReadyHealthChecks();
});
}

private static void RegisterJobsApiClientMock(IServiceCollection services)
{
var jobsApiClientMock = new Mock<IJobsApiClient>();
jobsApiClientMock.Setup(x => x.Jobs).Returns(new Mock<IJobsApi>().Object);
services.AddScoped(_ => jobsApiClientMock.Object);
}

private static void RegisterHttpClientFactoryMock(IServiceCollection services)
{
var httpMessageHandlerMock = new Mock<HttpMessageHandler>();

var response = new HttpResponseMessage { StatusCode = HttpStatusCode.OK };

httpMessageHandlerMock
.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(response);

var httpClient = new HttpClient(httpMessageHandlerMock.Object);
services.AddScoped(_ => httpClient);

var httpClientFactoryMock = new Mock<IHttpClientFactory>();
httpClientFactoryMock
.Setup(x => x.CreateClient(Options.DefaultName))
.Returns(() => httpClient);

services.AddScoped(_ => httpClientFactoryMock.Object);
}
});
}

private static void RegisterJobsApiClientMock(IServiceCollection services)
{
var jobsApiClientMock = new Mock<IJobsApiClient>();
jobsApiClientMock.Setup(x => x.Jobs).Returns(new Mock<IJobsApi>().Object);
services.AddScoped(_ => jobsApiClientMock.Object);
}

private static void RegisterHttpClientFactoryMock(IServiceCollection services)
{
var httpMessageHandlerMock = new Mock<HttpMessageHandler>();

var response = new HttpResponseMessage { StatusCode = HttpStatusCode.OK };

httpMessageHandlerMock
.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(response);

var httpClient = new HttpClient(httpMessageHandlerMock.Object);
services.AddScoped(_ => httpClient);

var httpClientFactoryMock = new Mock<IHttpClientFactory>();
httpClientFactoryMock
.Setup(x => x.CreateClient(Options.DefaultName))
.Returns(() => httpClient);

services.AddScoped(_ => httpClientFactoryMock.Object);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ limitations under the License.
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>12</LangVersion>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ limitations under the License.
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>12</LangVersion>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
Expand Down
55 changes: 27 additions & 28 deletions source/Databricks/source/Jobs/Client/JobsApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,42 +16,41 @@
using Energinet.DataHub.Core.Databricks.Jobs.Constants;
using Microsoft.Azure.Databricks.Client;

namespace Energinet.DataHub.Core.Databricks.Jobs.Client
namespace Energinet.DataHub.Core.Databricks.Jobs.Client;

/// <summary>
/// A databricks client based on the Microsoft.Azure.JobsApiClient, which is using Job API 2.0.
/// The client is extended with a method for reading jobs created using Python Wheels, using Job API 2.1.
/// Because the Job API 2.0 does not support reading python wheel settings.
/// Which is used when we run new jobs and need to know the existing parameters of the job.
/// The code is based on https://github.com/Azure/azure-databricks-client and can be replaced by the official
/// package when support for Job API 2.1 is added.
/// </summary>
public sealed class JobsApiClient : IDisposable, IJobsApiClient
{
/// <summary>
/// A databricks client based on the Microsoft.Azure.JobsApiClient, which is using Job API 2.0.
/// The client is extended with a method for reading jobs created using Python Wheels, using Job API 2.1.
/// Because the Job API 2.0 does not support reading python wheel settings.
/// Which is used when we run new jobs and need to know the existing parameters of the job.
/// The code is based on https://github.com/Azure/azure-databricks-client and can be replaced by the official
/// package when support for Job API 2.1 is added.
/// Create Databricks Jobs client object with a Http client.
/// </summary>
public sealed class JobsApiClient : IDisposable, IJobsApiClient
/// <param name="httpClientFactory">The <see cref="IHttpClientFactory"/>.</param>
public JobsApiClient(IHttpClientFactory httpClientFactory)
{
/// <summary>
/// Create Databricks Jobs client object with a Http client.
/// </summary>
/// <param name="httpClientFactory">The <see cref="IHttpClientFactory"/>.</param>
public JobsApiClient(IHttpClientFactory httpClientFactory)
{
var httpClient = httpClientFactory.CreateClient(HttpClientNameConstants.DatabricksJobsApi);
Jobs = new Microsoft.Azure.Databricks.Client.JobsApiClient(httpClient);
}
var httpClient = httpClientFactory.CreateClient(HttpClientNameConstants.DatabricksJobsApi);
Jobs = new Microsoft.Azure.Databricks.Client.JobsApiClient(httpClient);
}

public IJobsApi Jobs { get; }
public IJobsApi Jobs { get; }

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

private void Dispose(bool disposing)
private void Dispose(bool disposing)
{
if (disposing)
{
if (disposing)
{
Jobs.Dispose();
}
Jobs.Dispose();
}
}
}
Loading
Loading