Merge remote-tracking branch 'origin/main'

This commit is contained in:
Janus Knudsen 2025-02-28 17:56:19 +01:00
commit b1e134490d
9 changed files with 226 additions and 50 deletions

View file

@ -15,22 +15,29 @@ namespace PlanTempus.Core.Telemetry
} }
public new void Send(ITelemetry telemetry) public new void Send(ITelemetry telemetry)
{ {
if (telemetry.Context.GlobalProperties["OmitSeqTelemetryChannel"] != "true")
try if (telemetry.Context.GlobalProperties.TryGetValue("OmitSeqTelemetryChannel", out string value))
if (value == "true")
{ {
var writeTask = _messageChannel.Writer.WriteAsync(telemetry).AsTask(); base.Send(telemetry);
writeTask.ContinueWith(t => return;
}
try
{
var writeTask = _messageChannel.Writer.WriteAsync(telemetry).AsTask();
writeTask.ContinueWith(t =>
{
if (t.Exception != null)
{ {
if (t.Exception != null) throw t.Exception;
{ }
throw t.Exception; }, TaskContinuationOptions.OnlyOnFaulted);
} }
}, TaskContinuationOptions.OnlyOnFaulted); catch (Exception e)
} {
catch (Exception e) _telemetryClient.TrackException(e, new Dictionary<string, string> { { "OmitSeqTelemetryChannel", "true" } });
{ }
_telemetryClient.TrackException(e, new Dictionary<string, string> { { "OmitSeqTelemetryChannel", "true" } });
}
base.Send(telemetry); base.Send(telemetry);
} }
} }

View file

@ -235,3 +235,4 @@ namespace PlanTempus.SetupInfrastructure
} }

View file

@ -0,0 +1,190 @@
using PlanTempus.Database.ConfigurationManagementSystem;
using Insight.Database;
using System.Data;
using Newtonsoft.Json;
using FluentAssertions;
using Autofac;
using PlanTempus.Database.Core.ConnectionFactory;
namespace PlanTempus.Tests.ConfigurationSystem;
[TestClass]
public class SetupConfigurationTests : TestFixture
{
private IDbConnection _connection;
private SetupConfiguration _setupConfiguration;
[TestInitialize]
public void Setup()
{
var connectionFactory = Container.Resolve<IDbConnectionFactory>();
_connection = connectionFactory.Create();
}
[TestCleanup]
public void Cleanup()
{
_connection.ExecuteSql(@"
TRUNCATE TABLE app_configuration_history;
TRUNCATE TABLE app_configuration CASCADE;");
_connection.Dispose();
}
[TestMethod]
public void InsertConfiguration_ShouldCreateHistoryRecord()
{
// Arrange
var configData = new
{
key = "test.key",
value = "test value",
label = "Test Label"
};
// Act
var result = _connection.QuerySql<dynamic>(@"
INSERT INTO app_configuration (key, value, label)
VALUES (@key, @value, @label)
RETURNING *", configData).Single();
var history = _connection.QuerySql<dynamic>(@"
SELECT key, value, label, action_type
FROM app_configuration_history
WHERE id = @id AND action_type = 'I'",
new { id = (int)result.id })
.Single();
// Assert
var expected = JsonConvert.SerializeObject(new
{
key = configData.key,
value = configData.value,
label = configData.label,
action_type = "I"
});
var actual = JsonConvert.SerializeObject(history) as string;
actual.Should().Be(expected);
}
[TestMethod]
public void UpdateConfiguration_ShouldUpdateModifiedAt()
{
// Arrange
var configData = new
{
key = "test.key",
value = "original value"
};
var original = _connection.QuerySql<dynamic>(@"
INSERT INTO app_configuration (key, value)
VALUES (@key, @value)
RETURNING modified_at", configData)
.Single();
System.Threading.Thread.Sleep(1000);
// Act
var updated = _connection.QuerySql<dynamic>(@"
UPDATE app_configuration
SET value = @value
WHERE key = @key
RETURNING modified_at",
new { key = configData.key, value = "updated value" })
.Single();
// Assert
((DateTime)updated.modified_at).Should().BeAfter((DateTime)original.modified_at);
}
[TestMethod]
public void DeleteConfiguration_ShouldCreateHistoryRecord()
{
// Arrange
var configData = new
{
key = "test.key",
value = "test value"
};
var original = _connection.QuerySql<dynamic>(@"
INSERT INTO app_configuration (key, value)
VALUES (@key, @value)
RETURNING id", configData)
.Single();
// Act
_connection.ExecuteSql(
"DELETE FROM app_configuration WHERE id = @id",
new { id = (int)original.id });
// Assert
var history = _connection.QuerySql<dynamic>(@"
SELECT key, value, action_type
FROM app_configuration_history
WHERE id = @id AND action_type = 'D'",
new { id = (int)original.id })
.Single();
var expected = JsonConvert.SerializeObject(new
{
key = configData.key,
value = configData.value,
action_type = "D"
});
var actual = JsonConvert.SerializeObject(history) as string;
actual.Should().Be(expected);
}
[TestMethod]
public void InsertConfiguration_ShouldSetAllColumns()
{
// Arrange
var now = DateTime.UtcNow;
now = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0, DateTimeKind.Utc);
var configData = new
{
key = "test.columns",
value = "test value",
label = "Test Label",
content_type = "application/json",
valid_from = now,
expires_at = now.AddDays(30)
};
// Act
var result = _connection.QuerySql<dynamic>(@"
INSERT INTO app_configuration (
key,
value,
label,
content_type,
valid_from,
expires_at)
VALUES (
@key,
@value,
@label,
@content_type,
@valid_from,
@expires_at)
RETURNING key, value, label, content_type,
CAST(EXTRACT(EPOCH FROM date_trunc('minute', valid_from)) AS INTEGER) as valid_from,
CAST(EXTRACT(EPOCH FROM date_trunc('minute', expires_at)) AS INTEGER) as expires_at", configData)
.Single();
// Assert
var expected = JsonConvert.SerializeObject(new
{
key = configData.key,
value = configData.value,
label = configData.label,
content_type = configData.content_type,
valid_from = ((DateTimeOffset)configData.valid_from).ToUnixTimeSeconds(),
expires_at = ((DateTimeOffset)configData.expires_at).ToUnixTimeSeconds()
});
Assert.AreEqual(expected, JsonConvert.SerializeObject(result));
}
}

View file

@ -1,9 +1,7 @@
using Autofac; using Autofac;
using Shouldly; using Shouldly;
using System.Data; using System.Data;
using Insight.Database; using Insight.Database;
using Npgsql;
using PlanTempus.Tests;
using PlanTempus.Core.Configurations; using PlanTempus.Core.Configurations;
using PlanTempus.Core.Configurations.JsonConfigProvider; using PlanTempus.Core.Configurations.JsonConfigProvider;
using PlanTempus.Core.Configurations.SmartConfigProvider; using PlanTempus.Core.Configurations.SmartConfigProvider;

View file

@ -7,6 +7,11 @@
"ConnectionString": "InstrumentationKey=07d2a2b9-5e8e-4924-836e-264f8438f6c5;IngestionEndpoint=https://northeurope-2.in.applicationinsights.azure.com/;LiveEndpoint=https://northeurope.livediagnostics.monitor.azure.com/;ApplicationId=56748c39-2fa3-4880-a1e2-24068e791548", "ConnectionString": "InstrumentationKey=07d2a2b9-5e8e-4924-836e-264f8438f6c5;IngestionEndpoint=https://northeurope-2.in.applicationinsights.azure.com/;LiveEndpoint=https://northeurope.livediagnostics.monitor.azure.com/;ApplicationId=56748c39-2fa3-4880-a1e2-24068e791548",
"UseSeqLoggingTelemetryChannel": true "UseSeqLoggingTelemetryChannel": true
}, },
"SeqConfiguration": {
"IngestionEndpoint": "http://localhost:5341",
"ApiKey": null,
"Environment": "MSTEST"
},
"Authentication": "SHA256", "Authentication": "SHA256",
"Feature": { "Feature": {
"Enabled": true, "Enabled": true,

View file

@ -50,7 +50,7 @@ namespace PlanTempus.Tests.Logging
// wait for processing // wait for processing
await Task.Delay(5000); await Task.Delay(5000);
_cts.Cancel(); _cts.Cancel(); //not sure about this, we need to analyse more before this is "the way"
await _service.StopAsync(CancellationToken.None); await _service.StopAsync(CancellationToken.None);
@ -67,11 +67,5 @@ namespace PlanTempus.Tests.Logging
return Task.FromResult(new HttpResponseMessage(System.Net.HttpStatusCode.OK)); return Task.FromResult(new HttpResponseMessage(System.Net.HttpStatusCode.OK));
} }
} }
[TestCleanup]
public void Cleanup()
{
_cts?.Dispose();
}
} }
} }

View file

@ -52,19 +52,10 @@ namespace PlanTempus.Tests.Logging
// wait for processing // wait for processing
await Task.Delay(5000); await Task.Delay(5000);
//_cts.Cancel();
await _service.StopAsync(CancellationToken.None); await _service.StopAsync(CancellationToken.None);
bool hasMoreMessages = await _messageChannel.Reader.WaitToReadAsync(); bool hasMoreMessages = await _messageChannel.Reader.WaitToReadAsync();
Assert.IsFalse(hasMoreMessages, "Queue should be empty after 5 seconds"); Assert.IsFalse(hasMoreMessages, "Queue should be empty after 5 seconds");
} }
[TestCleanup]
public void Cleanup()
{
_cts?.Dispose();
}
} }
} }

View file

@ -40,7 +40,7 @@ namespace PlanTempus.Tests
// Assert // Assert
Assert.AreEqual(3, parts.Length); Assert.AreEqual(3, parts.Length);
Assert.AreEqual("600000", parts[0]); Assert.AreEqual("100000", parts[0]);
} }
[TestMethod] [TestMethod]

View file

@ -10,7 +10,7 @@ namespace PlanTempus.Tests
[TestClass] [TestClass]
public class PostgresTests : TestFixture public class PostgresTests : TestFixture
{ {
IDbConnectionFactory _connFactory; IDbConnectionFactory _connFactory;
IDatabaseOperations _databaseOperations; IDatabaseOperations _databaseOperations;
[TestInitialize] [TestInitialize]
@ -60,7 +60,6 @@ namespace PlanTempus.Tests
catch (Exception ex) catch (Exception ex)
{ {
db.Error(ex); db.Error(ex);
throw;
} }
} }
[TestMethod] [TestMethod]
@ -68,11 +67,11 @@ namespace PlanTempus.Tests
{ {
try try
{ {
await _databaseOperations.ExecuteAsync(async connection => await _databaseOperations.ExecuteAsync(async connection =>
{ {
return await connection.QuerySqlAsync<string>( return await connection.QuerySqlAsync<string>(
"SELECT tablename FROM pg_tables limit 5"); "SELECT tablename FROM pg_tables limit 5");
}, nameof(TestSimpleDatabaseOperation)); }, nameof(TestSimpleDatabaseOperation));
} }
catch (Exception ex) catch (Exception ex)
@ -80,15 +79,6 @@ namespace PlanTempus.Tests
throw; throw;
} }
} }
[TestMethod]
public async Task TryDbSetup()
{
//var conn = Container.Resolve<IDbConnection>();
//var identitySystem = new Database.Core.SetupIdentitySystem(conn);
//identitySystem.CreateSystem("swp");
}
[TestMethod] [TestMethod]
public void SetupPostgresql_LISTEN() public void SetupPostgresql_LISTEN()
{ {