Merge branch 'Cleanup' into 'main'
Program.cs cleanup, HiveModel change, log level change See merge request kzotkin/hiveemulator!3
This commit is contained in:
commit
08f30fc7fc
|
@ -37,7 +37,7 @@ namespace DevOpsProject.CommunicationControl.Logic.Services
|
|||
bool isSuccessfullyDisconnected = false;
|
||||
try
|
||||
{
|
||||
var result = await _redisService.DeleteAsync(hiveId);
|
||||
var result = await _redisService.DeleteAsync(GetHiveKey(hiveId));
|
||||
isSuccessfullyDisconnected = result;
|
||||
return result;
|
||||
}
|
||||
|
@ -65,9 +65,11 @@ namespace DevOpsProject.CommunicationControl.Logic.Services
|
|||
|
||||
public async Task<HiveOperationalArea> ConnectHive(HiveModel model)
|
||||
{
|
||||
_logger.LogInformation("Trying to connect Hive: {@model}", model);
|
||||
bool result = await _redisService.SetAsync(GetHiveKey(model.HiveID), model);
|
||||
if (result)
|
||||
{
|
||||
_logger.LogInformation("Successfully connected Hive: {@model}", model);
|
||||
var operationalArea = _spatialService.GetHiveOperationalArea(model);
|
||||
await _messageBus.Publish(new HiveConnectedMessage
|
||||
{
|
||||
|
@ -80,46 +82,41 @@ namespace DevOpsProject.CommunicationControl.Logic.Services
|
|||
}
|
||||
else
|
||||
{
|
||||
await _messageBus.Publish(new HiveConnectedMessage
|
||||
{
|
||||
HiveID = model.HiveID,
|
||||
Hive = model,
|
||||
IsSuccessfullyConnected = result
|
||||
});
|
||||
_logger.LogError("Failed to connect Hive: {@model}", model);
|
||||
throw new HiveConnectionException($"Failed to connect hive for HiveId: {model.HiveID}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> IsHiveConnected(string hiveId)
|
||||
{
|
||||
string hiveKey = GetHiveKey(hiveId);
|
||||
return await _redisService.CheckIfKeyExists(hiveKey);
|
||||
}
|
||||
|
||||
public async Task<DateTime> AddTelemetry(HiveTelemetryModel model)
|
||||
{
|
||||
string hiveKey = GetHiveKey(model.HiveID);
|
||||
bool hiveExists = await _redisService.CheckIfKeyExists(hiveKey);
|
||||
if (hiveExists)
|
||||
bool result = await _redisService.UpdateAsync(hiveKey, (HiveModel hive) =>
|
||||
{
|
||||
bool result = await _redisService.UpdateAsync(hiveKey, (HiveModel hive) =>
|
||||
{
|
||||
hive.Telemetry = model;
|
||||
});
|
||||
hive.Telemetry = model;
|
||||
});
|
||||
|
||||
await _messageBus.Publish(new TelemetrySentMessage
|
||||
{
|
||||
HiveID = model.HiveID,
|
||||
Telemetry = model,
|
||||
IsSuccessfullySent = result
|
||||
});
|
||||
return model.Timestamp;
|
||||
if (result)
|
||||
{
|
||||
_logger.LogInformation("Telemetry updated for HiveID: {hiveId}. Updated telemetry timestamp: {timestamp}", model.HiveID, model.Timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _messageBus.Publish(new TelemetrySentMessage
|
||||
{
|
||||
HiveID = model.HiveID,
|
||||
Telemetry = model,
|
||||
IsSuccessfullySent = false
|
||||
});
|
||||
throw new HiveNotFoundException($"Hive not found for id: {model.HiveID}");
|
||||
_logger.LogError("Failed to update Telemetry - Redis update issue. HiveID: {hiveId}, Telemetry model: {@telemetry}", model.HiveID, model);
|
||||
}
|
||||
|
||||
await _messageBus.Publish(new TelemetrySentMessage
|
||||
{
|
||||
HiveID = model.HiveID,
|
||||
Telemetry = model,
|
||||
IsSuccessfullySent = result
|
||||
});
|
||||
return model.Timestamp;
|
||||
}
|
||||
|
||||
public async Task<string> SendHiveControlSignal(string hiveId, Location destination)
|
||||
|
@ -127,33 +124,40 @@ namespace DevOpsProject.CommunicationControl.Logic.Services
|
|||
var hive = await GetHiveModel(hiveId);
|
||||
if (hive == null)
|
||||
{
|
||||
throw new Exception($"Hive control signal error: cannot find hive with id: {hiveId}");
|
||||
_logger.LogError("Sending Hive Control signal: Hive not found for HiveID: {hiveId}", hiveId);
|
||||
return null;
|
||||
}
|
||||
|
||||
bool isSuccessfullySent = false;
|
||||
|
||||
string hiveMindPath = _communicationControlConfiguration.CurrentValue.HiveMindPath;
|
||||
var command = new MoveHiveMindCommand
|
||||
{
|
||||
CommandType = State.Move,
|
||||
Location = destination,
|
||||
Timestamp = DateTime.Now
|
||||
};
|
||||
try
|
||||
{
|
||||
var command = new MoveHiveMindCommand
|
||||
{
|
||||
CommandType = State.Move,
|
||||
Location = destination,
|
||||
Timestamp = DateTime.Now
|
||||
};
|
||||
|
||||
var result = await _hiveHttpClient.SendHiveControlCommandAsync(_communicationControlConfiguration.CurrentValue.RequestScheme,
|
||||
hive.HiveIP, hive.HivePort, _communicationControlConfiguration.CurrentValue.HiveMindPath, command);
|
||||
var result = await _hiveHttpClient.SendHiveControlCommandAsync(hive.HiveSchema, hive.HiveIP, hive.HivePort, hiveMindPath, command);
|
||||
isSuccessfullySent = true;
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
await _messageBus.Publish(new MoveHiveMessage
|
||||
if (isSuccessfullySent)
|
||||
{
|
||||
IsSuccessfullySent = isSuccessfullySent,
|
||||
Destination = destination,
|
||||
HiveID = hiveId
|
||||
});
|
||||
await _messageBus.Publish(new MoveHiveMessage
|
||||
{
|
||||
IsSuccessfullySent = isSuccessfullySent,
|
||||
Destination = destination,
|
||||
HiveID = hiveId
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("Failed to send control command for Hive: {@hive}, path: {path}, \n Command: {@command}", hive, hiveMindPath, command);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace DevOpsProject.CommunicationControl.Logic.Services.Interfaces
|
|||
Task<HiveModel> GetHiveModel(string hiveId);
|
||||
Task<List<HiveModel>> GetAllHives();
|
||||
Task<HiveOperationalArea> ConnectHive(HiveModel model);
|
||||
Task<bool> IsHiveConnected(string hiveId);
|
||||
Task<DateTime> AddTelemetry(HiveTelemetryModel model);
|
||||
Task<string> SendHiveControlSignal(string hiveId, Location destination);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
using DevOpsProject.HiveMind.Logic.Services.Interfaces;
|
||||
using DevOpsProject.HiveMind.Logic.Services;
|
||||
using Asp.Versioning;
|
||||
|
||||
namespace DevOpsProject.HiveMind.API.DI
|
||||
{
|
||||
public static class ApiVersioningConfiguration
|
||||
{
|
||||
public static IServiceCollection AddApiVersioningConfiguration(this IServiceCollection serviceCollection)
|
||||
{
|
||||
serviceCollection.AddApiVersioning(options =>
|
||||
{
|
||||
options.DefaultApiVersion = new ApiVersion(1, 0);
|
||||
options.AssumeDefaultVersionWhenUnspecified = true;
|
||||
options.ReportApiVersions = true;
|
||||
options.ApiVersionReader = ApiVersionReader.Combine(
|
||||
new UrlSegmentApiVersionReader(),
|
||||
new HeaderApiVersionReader("X-Api-Version")
|
||||
);
|
||||
}).AddApiExplorer(options =>
|
||||
{
|
||||
options.GroupNameFormat = "'v'VVV";
|
||||
options.SubstituteApiVersionInUrl = true;
|
||||
});
|
||||
|
||||
return serviceCollection;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
namespace DevOpsProject.HiveMind.API.DI
|
||||
{
|
||||
public static class CorsConfiguration
|
||||
{
|
||||
public static IServiceCollection AddCorsConfiguration(this IServiceCollection serviceCollection, string corsPolicyName)
|
||||
{
|
||||
serviceCollection.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy(name: corsPolicyName,
|
||||
policy =>
|
||||
{
|
||||
policy.AllowAnyOrigin() //SECURITY WARNING ! Never allow all origins
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader();
|
||||
});
|
||||
});
|
||||
|
||||
return serviceCollection;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
using DevOpsProject.Shared.Clients;
|
||||
using Polly.Extensions.Http;
|
||||
using Polly;
|
||||
|
||||
namespace DevOpsProject.HiveMind.API.DI
|
||||
{
|
||||
public static class HttpClientsConfiguration
|
||||
{
|
||||
public static IServiceCollection AddHttpClientsConfiguration(this IServiceCollection serviceCollection)
|
||||
{
|
||||
var communicationControlTelemetryPolicy = HttpPolicyExtensions
|
||||
.HandleTransientHttpError()
|
||||
.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
|
||||
serviceCollection.AddHttpClient<HiveMindHttpClient>()
|
||||
.AddPolicyHandler(communicationControlTelemetryPolicy);
|
||||
serviceCollection.AddHttpClient("HiveConnectClient");
|
||||
|
||||
return serviceCollection;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
using DevOpsProject.Shared.Configuration;
|
||||
|
||||
namespace DevOpsProject.HiveMind.API.DI
|
||||
{
|
||||
public static class OptionsConfiguration
|
||||
{
|
||||
public static IServiceCollection AddOptionsConfiguration(this IServiceCollection serviceCollection, IConfiguration configuration)
|
||||
{
|
||||
serviceCollection.Configure<HiveCommunicationConfig>(configuration.GetSection("CommunicationConfiguration"));
|
||||
|
||||
return serviceCollection;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,13 +3,10 @@ using Asp.Versioning.Builder;
|
|||
using DevOpsProject.HiveMind.API.DI;
|
||||
using DevOpsProject.HiveMind.API.Middleware;
|
||||
using DevOpsProject.HiveMind.Logic.Services.Interfaces;
|
||||
using DevOpsProject.Shared.Clients;
|
||||
using DevOpsProject.Shared.Configuration;
|
||||
using DevOpsProject.Shared.Models;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Polly;
|
||||
using Polly.Extensions.Http;
|
||||
using Serilog;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
@ -19,52 +16,23 @@ builder.Host.UseSerilog((context, services, loggerConfig) =>
|
|||
.ReadFrom.Services(services)
|
||||
.Enrich.FromLogContext());
|
||||
|
||||
builder.Services.AddApiVersioning(options =>
|
||||
{
|
||||
options.DefaultApiVersion = new ApiVersion(1, 0);
|
||||
options.AssumeDefaultVersionWhenUnspecified = true;
|
||||
options.ReportApiVersions = true;
|
||||
options.ApiVersionReader = ApiVersionReader.Combine(
|
||||
new UrlSegmentApiVersionReader(),
|
||||
new HeaderApiVersionReader("X-Api-Version")
|
||||
);
|
||||
}).AddApiExplorer(options =>
|
||||
{
|
||||
options.GroupNameFormat = "'v'VVV";
|
||||
options.SubstituteApiVersionInUrl = true;
|
||||
});
|
||||
builder.Services.AddApiVersioningConfiguration();
|
||||
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddAuthorization();
|
||||
builder.Services.AddSwaggerGen(c =>
|
||||
{
|
||||
c.SwaggerDoc("v1", new OpenApiInfo { Title = "HiveMind - V1", Version = "v1.0" });
|
||||
});
|
||||
|
||||
builder.Services.AddOptionsConfiguration(builder.Configuration);
|
||||
|
||||
builder.Services.AddHiveMindLogic();
|
||||
|
||||
builder.Services.Configure<HiveCommunicationConfig>(builder.Configuration.GetSection("CommunicationConfiguration"));
|
||||
|
||||
var communicationControlTelemetryPolicy = HttpPolicyExtensions
|
||||
.HandleTransientHttpError()
|
||||
.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
|
||||
builder.Services.AddHttpClient<HiveMindHttpClient>()
|
||||
.AddPolicyHandler(communicationControlTelemetryPolicy);
|
||||
|
||||
// register NAMED client for connect request
|
||||
builder.Services.AddHttpClient("HiveConnectClient");
|
||||
builder.Services.AddHttpClientsConfiguration();
|
||||
|
||||
string corsPolicyName = "HiveMindCorsPolicy";
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy(name: corsPolicyName,
|
||||
policy =>
|
||||
{
|
||||
policy.AllowAnyOrigin() //SECURITY WARNING ! Never allow all origins
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader();
|
||||
});
|
||||
});
|
||||
builder.Services.AddCorsConfiguration(corsPolicyName);
|
||||
|
||||
builder.Services.AddExceptionHandler<ExceptionHandlingMiddleware>();
|
||||
builder.Services.AddProblemDetails();
|
||||
|
@ -82,7 +50,7 @@ using (var scope = app.Services.CreateScope())
|
|||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError($"Error occured while connecting Hive to Communication Control. \nException text: {ex.Message}");
|
||||
System.Diagnostics.Process.GetCurrentProcess().Kill();
|
||||
Environment.Exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,7 +73,6 @@ ApiVersionSet apiVersionSet = app.NewApiVersionSet()
|
|||
.HasApiVersion(new ApiVersion(1))
|
||||
.ReportApiVersions()
|
||||
.Build();
|
||||
|
||||
RouteGroupBuilder groupBuilder = app.MapGroup("api/v{apiVersion:apiVersion}").WithApiVersionSet(apiVersionSet);
|
||||
|
||||
groupBuilder.MapGet("ping", (IOptionsSnapshot<HiveCommunicationConfig> config) =>
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
"rollingInterval": "Day",
|
||||
"rollOnFileSizeLimit": true,
|
||||
"formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact",
|
||||
"restrictedToMinimumLevel": "Warning"
|
||||
"restrictedToMinimumLevel": "Information"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace DevOpsProject.HiveMind.Logic.Services
|
|||
// If already moving - stop movement
|
||||
if (HiveInMemoryState.IsMoving)
|
||||
{
|
||||
_logger.LogWarning("Previous movement command terminated. Previous destination: {@destination}, Current Location: {@current}, new destination: {@destination}", HiveInMemoryState.Destination, HiveInMemoryState.CurrentLocation, destination);
|
||||
StopMovement();
|
||||
}
|
||||
|
||||
|
@ -39,8 +40,9 @@ namespace DevOpsProject.HiveMind.Logic.Services
|
|||
if (_movementTimer == null)
|
||||
{
|
||||
// TODO: Recalculating position each N seconds
|
||||
_movementTimer = new Timer(UpdateMovement, null, TimeSpan.Zero, TimeSpan.FromSeconds(3));
|
||||
_logger.LogInformation("Movement timer started.");
|
||||
int intervalFromSeconds = 3;
|
||||
_movementTimer = new Timer(UpdateMovement, null, TimeSpan.Zero, TimeSpan.FromSeconds(intervalFromSeconds));
|
||||
_logger.LogInformation("Movement timer started. Destination: {@destination}, recalculation interval: {interval}", destination, intervalFromSeconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,14 +62,13 @@ namespace DevOpsProject.HiveMind.Logic.Services
|
|||
|
||||
if (AreLocationsEqual(currentLocation.Value, destination.Value))
|
||||
{
|
||||
_logger.LogInformation("Reached destination. Current location: {@currentLocation}, Destination: {@destination}", currentLocation, destination);
|
||||
StopMovement();
|
||||
return;
|
||||
}
|
||||
|
||||
Location newLocation = CalculateNextPosition(currentLocation.Value, destination.Value, 0.1f);
|
||||
HiveInMemoryState.CurrentLocation = newLocation;
|
||||
|
||||
_logger.LogInformation($"Moved closer: {newLocation}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,7 +78,6 @@ namespace DevOpsProject.HiveMind.Logic.Services
|
|||
_movementTimer = null;
|
||||
HiveInMemoryState.IsMoving = false;
|
||||
HiveInMemoryState.Destination = null;
|
||||
_logger.LogInformation("Movement stopped: Reached destination.");
|
||||
}
|
||||
|
||||
private static bool AreLocationsEqual(Location loc1, Location loc2)
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace DevOpsProject.HiveMind.Logic.Services
|
|||
{
|
||||
var request = new HiveConnectRequest
|
||||
{
|
||||
HiveSchema = _communicationConfigurationOptions.RequestSchema,
|
||||
HiveIP = _communicationConfigurationOptions.HiveIP,
|
||||
HivePort = _communicationConfigurationOptions.HivePort,
|
||||
HiveID = _communicationConfigurationOptions.HiveID
|
||||
|
@ -47,6 +48,8 @@ namespace DevOpsProject.HiveMind.Logic.Services
|
|||
};
|
||||
var jsonContent = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json");
|
||||
|
||||
_logger.LogInformation("Attempting to connect Hive. Request: {@request}, URI: {uri}", request, uriBuilder.Uri);
|
||||
|
||||
var retryPolicy = Policy.HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
|
||||
.WaitAndRetryAsync(
|
||||
10,
|
||||
|
@ -68,7 +71,6 @@ namespace DevOpsProject.HiveMind.Logic.Services
|
|||
HiveInMemoryState.OperationalArea = hiveConnectResponse.OperationalArea;
|
||||
HiveInMemoryState.CurrentLocation = _communicationConfigurationOptions.InitialLocation;
|
||||
|
||||
// HERE - we are starting to send telemetry
|
||||
StartTelemetry();
|
||||
}
|
||||
else
|
||||
|
@ -80,7 +82,7 @@ namespace DevOpsProject.HiveMind.Logic.Services
|
|||
else
|
||||
{
|
||||
_logger.LogError($"Failed to connect hive, terminating process");
|
||||
System.Diagnostics.Process.GetCurrentProcess().Kill();
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
{
|
||||
public class ComControlCommunicationConfiguration
|
||||
{
|
||||
public string RequestScheme { get; set; }
|
||||
public string HiveMindPath { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
namespace DevOpsProject.Shared.Exceptions
|
||||
{
|
||||
public class HiveNotFoundException : Exception
|
||||
{
|
||||
public HiveNotFoundException()
|
||||
{
|
||||
}
|
||||
|
||||
public HiveNotFoundException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public HiveNotFoundException(string message, Exception inner)
|
||||
: base(message, inner)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DevOpsProject.Shared.Models
|
||||
namespace DevOpsProject.Shared.Models
|
||||
{
|
||||
public class HiveConnectRequest
|
||||
{
|
||||
public string HiveSchema { get; set; }
|
||||
public string HiveIP { get; set; }
|
||||
public int HivePort { get; set; }
|
||||
public string HiveID { get; set; }
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
public string HiveID { get; set; }
|
||||
public string HiveIP { get; set; }
|
||||
public int HivePort { get; set; }
|
||||
public string HiveSchema { get; set; }
|
||||
public HiveTelemetryModel Telemetry { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,17 +32,21 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
|
|||
[HttpGet("hive/{hiveId}")]
|
||||
public async Task<IActionResult> GetHive(string hiveId)
|
||||
{
|
||||
var hiveModel = await _communicationControlService.GetHiveModel(hiveId);
|
||||
var hiveExists = await _communicationControlService.IsHiveConnected(hiveId);
|
||||
if (!hiveExists)
|
||||
{
|
||||
_logger.LogWarning("Failed to get Hive for HiveID: {hiveId}", hiveId);
|
||||
return NotFound($"Hive with HiveID: {hiveId} is not found");
|
||||
}
|
||||
|
||||
var hiveModel = await _communicationControlService.GetHiveModel(hiveId);
|
||||
return Ok(hiveModel);
|
||||
}
|
||||
|
||||
[HttpGet("hive")]
|
||||
public async Task<IActionResult> GetHives()
|
||||
{
|
||||
|
||||
var hives = await _communicationControlService.GetAllHives();
|
||||
|
||||
return Ok(hives);
|
||||
}
|
||||
|
||||
|
@ -59,6 +63,7 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
|
|||
if (request?.Hives == null || !request.Hives.Any())
|
||||
return BadRequest("No hive IDs provided.");
|
||||
|
||||
_logger.LogInformation("Hive moving request accepted by enpdoint. Request: {@request}", request);
|
||||
foreach (var id in request.Hives)
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
|
@ -69,7 +74,7 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, $"Failed to send control signal for HiveID: {id}");
|
||||
_logger.LogError(ex, "Failed to send control signal for HiveID: {id} \n Request: {@request}", id, request);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -11,10 +11,12 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
|
|||
public class HiveController : Controller
|
||||
{
|
||||
private readonly ICommunicationControlService _communicationControlService;
|
||||
private readonly ILogger<HiveController> _logger;
|
||||
|
||||
public HiveController(ICommunicationControlService communicationControlService)
|
||||
public HiveController(ICommunicationControlService communicationControlService, ILogger<HiveController> logger)
|
||||
{
|
||||
_communicationControlService = communicationControlService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpPost("connect")]
|
||||
|
@ -25,8 +27,16 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
|
|||
HiveID = request.HiveID,
|
||||
HiveIP = request.HiveIP,
|
||||
HivePort = request.HivePort,
|
||||
HiveSchema = request.HiveSchema
|
||||
};
|
||||
|
||||
bool isConnected = await _communicationControlService.IsHiveConnected(request.HiveID);
|
||||
if (isConnected)
|
||||
{
|
||||
_logger.LogError("Hive with HiveID: {hiveId} already connected. Request: {@request}", request.HiveID, request);
|
||||
return BadRequest($"Hive with HiveID: {request.HiveID} already connected");
|
||||
}
|
||||
|
||||
var hiveOperationalArea = await _communicationControlService.ConnectHive(hiveModel);
|
||||
var connectResponse = new HiveConnectResponse
|
||||
{
|
||||
|
@ -35,6 +45,7 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
|
|||
};
|
||||
|
||||
return Ok(connectResponse);
|
||||
|
||||
}
|
||||
|
||||
[HttpPost("telemetry")]
|
||||
|
@ -50,13 +61,22 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
|
|||
Timestamp = DateTime.Now
|
||||
};
|
||||
|
||||
var telemetryUpdateTimestamp = await _communicationControlService.AddTelemetry(hiveTelemetryModel);
|
||||
var telemetryResponse = new HiveTelemetryResponse
|
||||
bool isHiveConnected = await _communicationControlService.IsHiveConnected(request.HiveID);
|
||||
if (isHiveConnected)
|
||||
{
|
||||
Timestamp = telemetryUpdateTimestamp
|
||||
};
|
||||
var telemetryUpdateTimestamp = await _communicationControlService.AddTelemetry(hiveTelemetryModel);
|
||||
var telemetryResponse = new HiveTelemetryResponse
|
||||
{
|
||||
Timestamp = telemetryUpdateTimestamp
|
||||
};
|
||||
|
||||
return Ok(telemetryResponse);
|
||||
return Ok(telemetryResponse);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("Failed to write telemetry. Hive with HiveID: {hiveId} is not connected. Request: {@request}", request.HiveID, request);
|
||||
return NotFound($"Failed to write telemetry. Hive with HiveID: {request.HiveID} is not connected");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
using Asp.Versioning;
|
||||
|
||||
namespace DevOpsProject.CommunicationControl.API.DI
|
||||
{
|
||||
public static class ApiVersioningConfiguration
|
||||
{
|
||||
public static IServiceCollection AddApiVersioningConfiguration(this IServiceCollection serviceCollection)
|
||||
{
|
||||
serviceCollection.AddApiVersioning(options =>
|
||||
{
|
||||
options.DefaultApiVersion = new ApiVersion(1, 0);
|
||||
options.AssumeDefaultVersionWhenUnspecified = true;
|
||||
options.ReportApiVersions = true;
|
||||
options.ApiVersionReader = ApiVersionReader.Combine(
|
||||
new UrlSegmentApiVersionReader(),
|
||||
new HeaderApiVersionReader("X-Api-Version")
|
||||
);
|
||||
}).AddApiExplorer(options =>
|
||||
{
|
||||
options.GroupNameFormat = "'v'VVV";
|
||||
options.SubstituteApiVersionInUrl = true;
|
||||
});
|
||||
|
||||
return serviceCollection;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
namespace DevOpsProject.CommunicationControl.API.DI
|
||||
{
|
||||
public static class CorsConfiguration
|
||||
{
|
||||
public static IServiceCollection AddCorsConfiguration(this IServiceCollection serviceCollection, string corsPolicyName)
|
||||
{
|
||||
serviceCollection.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy(name: corsPolicyName,
|
||||
policy =>
|
||||
{
|
||||
policy.AllowAnyOrigin() //SECURITY WARNING ! Never allow all origins
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader();
|
||||
});
|
||||
});
|
||||
|
||||
return serviceCollection;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
using DevOpsProject.Shared.Clients;
|
||||
using Polly;
|
||||
using Polly.Extensions.Http;
|
||||
|
||||
namespace DevOpsProject.CommunicationControl.API.DI
|
||||
{
|
||||
public static class HttpClientsConfiguration
|
||||
{
|
||||
public static IServiceCollection AddHttpClientsConfiguration(this IServiceCollection serviceCollection)
|
||||
{
|
||||
var hiveRetryPolicy = HttpPolicyExtensions
|
||||
.HandleTransientHttpError()
|
||||
.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
|
||||
serviceCollection.AddHttpClient<CommunicationControlHttpClient>()
|
||||
.AddPolicyHandler(hiveRetryPolicy);
|
||||
|
||||
return serviceCollection;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
namespace DevOpsProject.CommunicationControl.API.DI
|
||||
{
|
||||
public static class JsonControllerOptionsConfiguration
|
||||
{
|
||||
public static IServiceCollection AddJsonControllerOptionsConfiguration(this IServiceCollection serviceCollection)
|
||||
{
|
||||
serviceCollection.AddControllers().AddJsonOptions(options =>
|
||||
{
|
||||
options.JsonSerializerOptions.PropertyNamingPolicy = null;
|
||||
});
|
||||
|
||||
return serviceCollection;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,5 @@ namespace DevOpsProject.CommunicationControl.API.DI
|
|||
|
||||
return serviceCollection;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
using DevOpsProject.Shared.Configuration;
|
||||
using DevOpsProject.Shared.Models;
|
||||
|
||||
namespace DevOpsProject.CommunicationControl.API.DI
|
||||
{
|
||||
public static class OptionsConfiguration
|
||||
{
|
||||
public static IServiceCollection AddOptionsConfiguration(this IServiceCollection serviceCollection, IConfiguration configuration)
|
||||
{
|
||||
serviceCollection.Configure<OperationalAreaConfig>(configuration.GetSection("OperationalArea"));
|
||||
serviceCollection.Configure<ComControlCommunicationConfiguration>(configuration.GetSection("CommunicationConfiguration"));
|
||||
|
||||
return serviceCollection;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +1,6 @@
|
|||
using Asp.Versioning;
|
||||
using DevOpsProject.CommunicationControl.API.DI;
|
||||
using DevOpsProject.CommunicationControl.API.Middleware;
|
||||
using DevOpsProject.Shared.Clients;
|
||||
using DevOpsProject.Shared.Configuration;
|
||||
using DevOpsProject.Shared.Models;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Polly;
|
||||
using Polly.Extensions.Http;
|
||||
using Serilog;
|
||||
|
||||
internal class Program
|
||||
|
@ -21,26 +14,11 @@ internal class Program
|
|||
.ReadFrom.Services(services)
|
||||
.Enrich.FromLogContext());
|
||||
|
||||
builder.Services.AddApiVersioning(options =>
|
||||
{
|
||||
options.DefaultApiVersion = new ApiVersion(1, 0);
|
||||
options.AssumeDefaultVersionWhenUnspecified = true;
|
||||
options.ReportApiVersions = true;
|
||||
options.ApiVersionReader = ApiVersionReader.Combine(
|
||||
new UrlSegmentApiVersionReader(),
|
||||
new HeaderApiVersionReader("X-Api-Version")
|
||||
);
|
||||
}).AddApiExplorer(options =>
|
||||
{
|
||||
options.GroupNameFormat = "'v'VVV";
|
||||
options.SubstituteApiVersionInUrl = true;
|
||||
});
|
||||
builder.Services.AddApiVersioningConfiguration();
|
||||
|
||||
// TODO: consider this approach
|
||||
builder.Services.AddControllers().AddJsonOptions(options =>
|
||||
{
|
||||
options.JsonSerializerOptions.PropertyNamingPolicy = null;
|
||||
}); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
builder.Services.AddJsonControllerOptionsConfiguration();
|
||||
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen(c =>
|
||||
{
|
||||
|
@ -52,36 +30,12 @@ internal class Program
|
|||
builder.Services.AddRedis(builder.Configuration);
|
||||
builder.Services.AddCommunicationControlLogic();
|
||||
|
||||
builder.Services.Configure<OperationalAreaConfig>(builder.Configuration.GetSection("OperationalArea"));
|
||||
builder.Services.Configure<ComControlCommunicationConfiguration>(builder.Configuration.GetSection("CommunicationConfiguration"));
|
||||
|
||||
var hiveRetryPolicy = HttpPolicyExtensions
|
||||
.HandleTransientHttpError()
|
||||
.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
|
||||
builder.Services.AddHttpClient<CommunicationControlHttpClient>()
|
||||
.AddPolicyHandler(hiveRetryPolicy);
|
||||
builder.Services.AddOptionsConfiguration(builder.Configuration);
|
||||
|
||||
builder.Services.AddHttpClientsConfiguration();
|
||||
|
||||
var corsPolicyName = "AllowReactApp";
|
||||
var localCorsPolicyName = "AllowLocalHtml";
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy(name: corsPolicyName,
|
||||
policy =>
|
||||
{
|
||||
policy.AllowAnyOrigin() //SECURITY WARNING ! Never allow all origins
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader();
|
||||
});
|
||||
|
||||
options.AddPolicy(name: localCorsPolicyName,
|
||||
policy =>
|
||||
{
|
||||
policy.AllowAnyOrigin() //SECURITY WARNING ! Never allow all origins
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader();
|
||||
});
|
||||
});
|
||||
builder.Services.AddCorsConfiguration(corsPolicyName);
|
||||
|
||||
builder.Services.AddExceptionHandler<ExceptionHandlingMiddleware>();
|
||||
builder.Services.AddProblemDetails();
|
||||
|
@ -97,7 +51,6 @@ internal class Program
|
|||
}
|
||||
|
||||
app.UseCors(corsPolicyName);
|
||||
//app.UseCors(localCorsPolicyName);
|
||||
|
||||
app.UseAuthorization();
|
||||
|
||||
|
|
|
@ -14,10 +14,8 @@
|
|||
"InitialSpeed_KM": 5,
|
||||
"TelemetryInterval_MS": 30000,
|
||||
"PingInterval_MS": 15000
|
||||
|
||||
},
|
||||
"CommunicationConfiguration": {
|
||||
"RequestScheme": "http",
|
||||
"HiveMindPath": "api/v1"
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
|
@ -45,7 +43,7 @@
|
|||
"rollingInterval": "Day",
|
||||
"rollOnFileSizeLimit": true,
|
||||
"formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact",
|
||||
"restrictedToMinimumLevel": "Warning"
|
||||
"restrictedToMinimumLevel": "Information"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue