-
-
Notifications
You must be signed in to change notification settings - Fork 99
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
11698ad
commit c3667a1
Showing
5 changed files
with
247 additions
and
194 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 58 additions & 48 deletions
106
src/HappyCode.NetCoreBoilerplate.Api/BackgroundServices/PingWebsiteBackgroundService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,48 +1,58 @@ | ||
using System.Net.Http; | ||
using HappyCode.NetCoreBoilerplate.Core.Settings; | ||
using Microsoft.Extensions.Hosting; | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Options; | ||
|
||
namespace HappyCode.NetCoreBoilerplate.Api.BackgroundServices | ||
{ | ||
public class PingWebsiteBackgroundService : BackgroundService | ||
{ | ||
private readonly PeriodicTimer _timer; | ||
private readonly HttpClient _client; | ||
private readonly ILogger<PingWebsiteBackgroundService> _logger; | ||
private readonly IOptions<PingWebsiteSettings> _configuration; | ||
|
||
public PingWebsiteBackgroundService( | ||
IHttpClientFactory httpClientFactory, | ||
ILogger<PingWebsiteBackgroundService> logger, | ||
IOptions<PingWebsiteSettings> configuration) | ||
{ | ||
_client = httpClientFactory.CreateClient(nameof(PingWebsiteBackgroundService)); | ||
_logger = logger; | ||
_configuration = configuration; | ||
_timer = new PeriodicTimer(TimeSpan.FromMinutes(_configuration.Value.TimeIntervalInMinutes)); | ||
} | ||
|
||
protected override async Task ExecuteAsync(CancellationToken cancellationToken) | ||
{ | ||
while (!cancellationToken.IsCancellationRequested) | ||
{ | ||
_logger.LogInformation("{BackgroundService} running at '{Date}', pinging '{URL}'", | ||
nameof(PingWebsiteBackgroundService), DateTime.Now, _configuration.Value.Url); | ||
try | ||
{ | ||
using var response = await _client.GetAsync(_configuration.Value.Url, HttpCompletionOption.ResponseHeadersRead, cancellationToken); | ||
_logger.LogInformation("Is '{Host}' responding: {Status}", | ||
_configuration.Value.Url.Authority, response.IsSuccessStatusCode); | ||
} | ||
catch (Exception ex) | ||
{ | ||
_logger.LogWarning(ex, "Error during ping"); | ||
} | ||
await _timer.WaitForNextTickAsync(cancellationToken); | ||
} | ||
_timer.Dispose(); | ||
} | ||
} | ||
} | ||
using System.Net; | ||
using System.Net.Http; | ||
using HappyCode.NetCoreBoilerplate.Core.Settings; | ||
using Microsoft.Extensions.Hosting; | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Options; | ||
|
||
namespace HappyCode.NetCoreBoilerplate.Api.BackgroundServices | ||
{ | ||
public interface IPingService | ||
{ | ||
public HttpStatusCode WebsiteStatusCode { get; } | ||
} | ||
|
||
public class PingWebsiteBackgroundService : BackgroundService, IPingService | ||
{ | ||
private readonly PeriodicTimer _timer; | ||
private readonly HttpClient _client; | ||
private readonly ILogger<PingWebsiteBackgroundService> _logger; | ||
private readonly IOptions<PingWebsiteSettings> _configuration; | ||
|
||
public HttpStatusCode WebsiteStatusCode { get; private set; } | ||
|
||
public PingWebsiteBackgroundService( | ||
IHttpClientFactory httpClientFactory, | ||
ILogger<PingWebsiteBackgroundService> logger, | ||
IOptions<PingWebsiteSettings> configuration) | ||
{ | ||
_client = httpClientFactory.CreateClient(nameof(PingWebsiteBackgroundService)); | ||
_logger = logger; | ||
_configuration = configuration; | ||
|
||
_timer = new PeriodicTimer(TimeSpan.FromMinutes(_configuration.Value.TimeIntervalInMinutes)); | ||
} | ||
|
||
protected override async Task ExecuteAsync(CancellationToken cancellationToken) | ||
{ | ||
while (!cancellationToken.IsCancellationRequested) | ||
{ | ||
_logger.LogInformation("{BackgroundService} running at '{Date}', pinging '{URL}'", | ||
nameof(PingWebsiteBackgroundService), DateTime.Now, _configuration.Value.Url); | ||
try | ||
{ | ||
using var response = await _client.GetAsync(_configuration.Value.Url, HttpCompletionOption.ResponseHeadersRead, cancellationToken); | ||
WebsiteStatusCode = response.StatusCode; | ||
_logger.LogInformation("Is '{Host}' responding: {Status}", | ||
_configuration.Value.Url.Authority, response.IsSuccessStatusCode); | ||
} | ||
catch (Exception ex) | ||
{ | ||
_logger.LogWarning(ex, "Error during ping"); | ||
} | ||
await _timer.WaitForNextTickAsync(cancellationToken); | ||
} | ||
_timer.Dispose(); | ||
} | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
src/HappyCode.NetCoreBoilerplate.Api/Controllers/PingsController.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
using System.Net; | ||
using HappyCode.NetCoreBoilerplate.Api.BackgroundServices; | ||
using Microsoft.AspNetCore.Authorization; | ||
using Microsoft.AspNetCore.Http; | ||
using Microsoft.AspNetCore.Mvc; | ||
|
||
namespace HappyCode.NetCoreBoilerplate.Api.Controllers | ||
{ | ||
[AllowAnonymous] | ||
[Route("api/pings")] | ||
public class PingsController : ApiControllerBase | ||
{ | ||
private readonly IPingService _pingService; | ||
|
||
public PingsController(IPingService pingService) | ||
{ | ||
_pingService = pingService; | ||
} | ||
|
||
[HttpGet("website")] | ||
[ProducesResponseType(typeof(string), StatusCodes.Status200OK)] | ||
public IActionResult GetWebsitePingStatusCode() | ||
{ | ||
var result = _pingService.WebsiteStatusCode; | ||
return Ok($"{(int)result} ({result})"); | ||
} | ||
|
||
[HttpGet("random")] | ||
[ProducesResponseType(typeof(string), StatusCodes.Status200OK)] | ||
public IActionResult GetRandomStatusCode() | ||
{ | ||
var random = new Random(Guid.NewGuid().GetHashCode()); | ||
int pretender; | ||
do | ||
{ | ||
pretender = random.Next(100, 600); | ||
} while (!Enum.IsDefined(typeof(HttpStatusCode), pretender)); | ||
return Ok($"{pretender} ({(HttpStatusCode)pretender})"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,99 +1,101 @@ | ||
using HappyCode.NetCoreBoilerplate.Api.BackgroundServices; | ||
using HappyCode.NetCoreBoilerplate.Api.Infrastructure.Configurations; | ||
using HappyCode.NetCoreBoilerplate.Api.Infrastructure.Filters; | ||
using HappyCode.NetCoreBoilerplate.Api.Infrastructure.Registrations; | ||
using HappyCode.NetCoreBoilerplate.BooksModule; | ||
using HappyCode.NetCoreBoilerplate.Core; | ||
using HappyCode.NetCoreBoilerplate.Core.Registrations; | ||
using HappyCode.NetCoreBoilerplate.Core.Settings; | ||
using HealthChecks.UI.Client; | ||
using Microsoft.AspNetCore.Builder; | ||
using Microsoft.AspNetCore.Diagnostics.HealthChecks; | ||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.EntityFrameworkCore; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Hosting; | ||
using Microsoft.FeatureManagement; | ||
using Microsoft.FeatureManagement.FeatureFilters; | ||
using Swashbuckle.AspNetCore.SwaggerUI; | ||
|
||
namespace HappyCode.NetCoreBoilerplate.Api | ||
{ | ||
public class Startup | ||
{ | ||
private readonly IConfiguration _configuration; | ||
|
||
public Startup(IConfiguration configuration) | ||
{ | ||
_configuration = configuration; | ||
} | ||
|
||
public virtual void ConfigureServices(IServiceCollection services) | ||
{ | ||
services | ||
.AddHttpContextAccessor() | ||
.AddRouting(options => options.LowercaseUrls = true); | ||
|
||
services.AddMvcCore(options => | ||
{ | ||
options.Filters.Add<HttpGlobalExceptionFilter>(); | ||
options.Filters.Add<ValidateModelStateFilter>(); | ||
options.Filters.Add<ApiKeyAuthorizationFilter>(); | ||
}) | ||
.AddApiExplorer() | ||
.AddDataAnnotations(); | ||
|
||
//there is a difference between AddDbContext() and AddDbContextPool(), more info https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-2.0#dbcontext-pooling and https://stackoverflow.com/questions/48443567/adddbcontext-or-adddbcontextpool | ||
services.AddDbContext<EmployeesContext>(options => options.UseMySql(_configuration.GetConnectionString("MySqlDb"), ServerVersion.Parse("8.0")), contextLifetime: ServiceLifetime.Transient, optionsLifetime: ServiceLifetime.Singleton); | ||
services.AddDbContextPool<CarsContext>(options => options.UseSqlServer(_configuration.GetConnectionString("MsSqlDb")), poolSize: 10); | ||
|
||
services.Configure<ApiKeySettings>(_configuration.GetSection("ApiKey")); | ||
services.AddSwagger(_configuration); | ||
|
||
services.Configure<PingWebsiteSettings>(_configuration.GetSection("PingWebsite")); | ||
services.AddHostedService<PingWebsiteBackgroundService>(); | ||
services.AddHttpClient(nameof(PingWebsiteBackgroundService)); | ||
|
||
services.AddCoreComponents(); | ||
services.AddBooksModule(_configuration); | ||
|
||
services.AddFeatureManagement() | ||
.AddFeatureFilter<TimeWindowFilter>(); | ||
|
||
services.AddHealthChecks() | ||
.AddMySql(_configuration.GetConnectionString("MySqlDb")) | ||
.AddSqlServer(_configuration.GetConnectionString("MsSqlDb")) | ||
.AddBooksModule(_configuration); | ||
} | ||
|
||
public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env) | ||
{ | ||
if (env.IsDevelopment()) | ||
{ | ||
app.UseDeveloperExceptionPage(); | ||
} | ||
|
||
app.UseRouting(); | ||
app.UseEndpoints(endpoints => | ||
{ | ||
endpoints.MapControllers(); | ||
endpoints.MapBooksModule(); | ||
|
||
endpoints.MapHealthChecks("/health", new HealthCheckOptions | ||
{ | ||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse, | ||
}); | ||
}); | ||
|
||
app.UseSwagger(); | ||
app.UseSwaggerUI(c => | ||
{ | ||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Simple Api V1"); | ||
c.DocExpansion(DocExpansion.None); | ||
}); | ||
|
||
app.InitBooksModule(); | ||
} | ||
} | ||
} | ||
using System.Linq; | ||
using HappyCode.NetCoreBoilerplate.Api.BackgroundServices; | ||
using HappyCode.NetCoreBoilerplate.Api.Infrastructure.Configurations; | ||
using HappyCode.NetCoreBoilerplate.Api.Infrastructure.Filters; | ||
using HappyCode.NetCoreBoilerplate.Api.Infrastructure.Registrations; | ||
using HappyCode.NetCoreBoilerplate.BooksModule; | ||
using HappyCode.NetCoreBoilerplate.Core; | ||
using HappyCode.NetCoreBoilerplate.Core.Registrations; | ||
using HappyCode.NetCoreBoilerplate.Core.Settings; | ||
using HealthChecks.UI.Client; | ||
using Microsoft.AspNetCore.Builder; | ||
using Microsoft.AspNetCore.Diagnostics.HealthChecks; | ||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.EntityFrameworkCore; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Hosting; | ||
using Microsoft.FeatureManagement; | ||
using Microsoft.FeatureManagement.FeatureFilters; | ||
using Swashbuckle.AspNetCore.SwaggerUI; | ||
|
||
namespace HappyCode.NetCoreBoilerplate.Api | ||
{ | ||
public class Startup | ||
{ | ||
private readonly IConfiguration _configuration; | ||
|
||
public Startup(IConfiguration configuration) | ||
{ | ||
_configuration = configuration; | ||
} | ||
|
||
public virtual void ConfigureServices(IServiceCollection services) | ||
{ | ||
services | ||
.AddHttpContextAccessor() | ||
.AddRouting(options => options.LowercaseUrls = true); | ||
|
||
services.AddMvcCore(options => | ||
{ | ||
options.Filters.Add<HttpGlobalExceptionFilter>(); | ||
options.Filters.Add<ValidateModelStateFilter>(); | ||
options.Filters.Add<ApiKeyAuthorizationFilter>(); | ||
}) | ||
.AddApiExplorer() | ||
.AddDataAnnotations(); | ||
|
||
//there is a difference between AddDbContext() and AddDbContextPool(), more info https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-2.0#dbcontext-pooling and https://stackoverflow.com/questions/48443567/adddbcontext-or-adddbcontextpool | ||
services.AddDbContext<EmployeesContext>(options => options.UseMySql(_configuration.GetConnectionString("MySqlDb"), ServerVersion.Parse("8.0")), contextLifetime: ServiceLifetime.Transient, optionsLifetime: ServiceLifetime.Singleton); | ||
services.AddDbContextPool<CarsContext>(options => options.UseSqlServer(_configuration.GetConnectionString("MsSqlDb")), poolSize: 10); | ||
|
||
services.Configure<ApiKeySettings>(_configuration.GetSection("ApiKey")); | ||
services.AddSwagger(_configuration); | ||
|
||
services.Configure<PingWebsiteSettings>(_configuration.GetSection("PingWebsite")); | ||
services.AddHttpClient(nameof(PingWebsiteBackgroundService)); | ||
services.AddHostedService<PingWebsiteBackgroundService>(); | ||
services.AddSingleton(x => x.GetServices<IHostedService>().OfType<IPingService>().Single()); | ||
|
||
services.AddCoreComponents(); | ||
services.AddBooksModule(_configuration); | ||
|
||
services.AddFeatureManagement() | ||
.AddFeatureFilter<TimeWindowFilter>(); | ||
|
||
services.AddHealthChecks() | ||
.AddMySql(_configuration.GetConnectionString("MySqlDb")) | ||
.AddSqlServer(_configuration.GetConnectionString("MsSqlDb")) | ||
.AddBooksModule(_configuration); | ||
} | ||
|
||
public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env) | ||
{ | ||
if (env.IsDevelopment()) | ||
{ | ||
app.UseDeveloperExceptionPage(); | ||
} | ||
|
||
app.UseRouting(); | ||
app.UseEndpoints(endpoints => | ||
{ | ||
endpoints.MapControllers(); | ||
endpoints.MapBooksModule(); | ||
|
||
endpoints.MapHealthChecks("/health", new HealthCheckOptions | ||
{ | ||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse, | ||
}); | ||
}); | ||
|
||
app.UseSwagger(); | ||
app.UseSwaggerUI(c => | ||
{ | ||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Simple Api V1"); | ||
c.DocExpansion(DocExpansion.None); | ||
}); | ||
|
||
app.InitBooksModule(); | ||
} | ||
} | ||
} |
Oops, something went wrong.