Update Environment to TimescaleDB

This commit is contained in:
2024-01-31 21:03:11 -05:00
parent 0fa45d13ae
commit f2c585c9d7
7 changed files with 100 additions and 72 deletions

View File

@@ -1,7 +1,7 @@
using System.Reflection; using Dapper;
using Dapper;
using DbUp; using DbUp;
using Microsoft.Data.SqlClient; using Npgsql;
using System.Reflection;
namespace ChrisKaczor.HomeMonitor.Environment.Service.Data; namespace ChrisKaczor.HomeMonitor.Environment.Service.Data;
@@ -9,12 +9,13 @@ public class Database(IConfiguration configuration)
{ {
private string GetConnectionString() private string GetConnectionString()
{ {
var connectionStringBuilder = new SqlConnectionStringBuilder var connectionStringBuilder = new NpgsqlConnectionStringBuilder
{ {
DataSource = $"{configuration["Environment:Database:Host"]},{configuration["Environment:Database:Port"]}", Host = configuration["Environment:Database:Host"],
UserID = configuration["Environment:Database:User"], Port = configuration.GetValue<int>("Environment:Database:Port"),
Username = configuration["Environment:Database:User"],
Password = configuration["Environment:Database:Password"], Password = configuration["Environment:Database:Password"],
InitialCatalog = configuration["Environment:Database:Name"], Database = configuration["Environment:Database:Name"],
TrustServerCertificate = bool.Parse(configuration["Environment:Database:TrustServerCertificate"] ?? "false") TrustServerCertificate = bool.Parse(configuration["Environment:Database:TrustServerCertificate"] ?? "false")
}; };
@@ -25,16 +26,16 @@ public class Database(IConfiguration configuration)
{ {
var connectionString = GetConnectionString(); var connectionString = GetConnectionString();
DbUp.EnsureDatabase.For.SqlDatabase(connectionString); DbUp.EnsureDatabase.For.PostgresqlDatabase(connectionString);
var upgradeEngine = DeployChanges.To.SqlDatabase(connectionString).WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly(), s => s.Contains(".Schema.")).LogToConsole().Build(); var upgradeEngine = DeployChanges.To.PostgresqlDatabase(connectionString).WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly(), s => s.Contains(".Schema.")).LogToConsole().Build();
upgradeEngine.PerformUpgrade(); upgradeEngine.PerformUpgrade();
} }
private SqlConnection CreateConnection() private NpgsqlConnection CreateConnection()
{ {
var connection = new SqlConnection(GetConnectionString()); var connection = new NpgsqlConnection(GetConnectionString());
connection.Open(); connection.Open();
return connection; return connection;

View File

@@ -1,25 +1,30 @@
BEGIN TRANSACTION INSERT INTO
reading
INSERT Reading (
(Timestamp, Name, Model, Temperature, Pressure, Humidity, Luminance, GasResistance, ColorTemperature, AirQualityIndex) time,
SELECT name,
@Timestamp, model,
@Name, temperature,
@Model, pressure,
@Temperature, humidity,
@Pressure, luminance,
@Humidity, gas_resistance,
@Luminance, color_temperature,
@GasResistance, air_quality_index
@ColorTemperature, )
@AirQualityIndex VALUES
WHERE NOT EXISTS (
( @Timestamp,
SELECT @Name,
1 @Model,
FROM @Temperature,
Reading WITH (UPDLOCK, SERIALIZABLE) @Pressure,
WHERE Timestamp = @Timestamp AND Name = @Name AND Model = @Model @Humidity,
) @Luminance,
@GasResistance,
COMMIT TRANSACTION @ColorTemperature,
@AirQualityIndex
)
ON CONFLICT
ON CONSTRAINT reading_pk
DO NOTHING

View File

@@ -1,14 +1,17 @@
CREATE TABLE Reading CREATE TABLE
( reading (
Timestamp datetimeoffset NOT NULL, time timestamptz NOT NULL,
Name nvarchar(50) NOT NULL, name text NOT NULL,
Model nvarchar(50) NOT NULL, model text NOT NULL,
Temperature decimal(5, 2) NOT NULL, temperature DECIMAL NOT NULL,
Pressure decimal(6, 2) NOT NULL, pressure DECIMAL NOT NULL,
Humidity decimal(5, 2) NOT NULL, humidity DECIMAL NOT NULL,
Luminance int NOT NULL, luminance INT NOT NULL,
GasResistance int NOT NULL, gas_resistance INT NOT NULL,
ColorTemperature int NOT NULL, color_temperature INT NOT NULL,
AirQualityIndex decimal(4, 1) NOT NULL, air_quality_index DECIMAL NOT NULL,
CONSTRAINT reading_pk PRIMARY KEY (Timestamp, Name, Model) CONSTRAINT reading_pk PRIMARY KEY (time, name, model)
); );
SELECT
create_hypertable('reading', by_range('time'));

View File

@@ -14,7 +14,7 @@ public class MessageHandler : IHostedService
private readonly MqttFactory _mqttFactory; private readonly MqttFactory _mqttFactory;
private readonly string _topic; private readonly string _topic;
private readonly HubConnection _hubConnection; private readonly HubConnection? _hubConnection;
public MessageHandler(IConfiguration configuration, Database database) public MessageHandler(IConfiguration configuration, Database database)
{ {
@@ -33,12 +33,16 @@ public class MessageHandler : IHostedService
_mqttClient.ApplicationMessageReceivedAsync += OnApplicationMessageReceivedAsync; _mqttClient.ApplicationMessageReceivedAsync += OnApplicationMessageReceivedAsync;
_hubConnection = new HubConnectionBuilder().WithUrl(configuration["Environment:Hub:Url"] ?? string.Empty).Build(); var hubUrl = configuration["Environment:Hub:Url"];
if (!string.IsNullOrEmpty(hubUrl))
_hubConnection = new HubConnectionBuilder().WithUrl(hubUrl).Build();
} }
public async Task StartAsync(CancellationToken cancellationToken) public async Task StartAsync(CancellationToken cancellationToken)
{ {
await _hubConnection.StartAsync(cancellationToken); if (_hubConnection != null)
await _hubConnection.StartAsync(cancellationToken);
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer(_configuration["Mqtt:Server"]).Build(); var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer(_configuration["Mqtt:Server"]).Build();
await _mqttClient.ConnectAsync(mqttClientOptions, cancellationToken); await _mqttClient.ConnectAsync(mqttClientOptions, cancellationToken);
@@ -51,7 +55,8 @@ public class MessageHandler : IHostedService
{ {
await _mqttClient.DisconnectAsync(new MqttClientDisconnectOptionsBuilder().Build(), cancellationToken); await _mqttClient.DisconnectAsync(new MqttClientDisconnectOptionsBuilder().Build(), cancellationToken);
await _hubConnection.StopAsync(cancellationToken); if (_hubConnection != null)
await _hubConnection.StopAsync(cancellationToken);
} }
private async Task OnApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs arg) private async Task OnApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs arg)
@@ -75,6 +80,9 @@ public class MessageHandler : IHostedService
{ {
try try
{ {
if (_hubConnection == null)
return;
if (_hubConnection.State == HubConnectionState.Disconnected) if (_hubConnection.State == HubConnectionState.Disconnected)
await _hubConnection.StartAsync(); await _hubConnection.StartAsync();

View File

@@ -20,9 +20,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ChrisKaczor.Common.OpenTelemetry" Version="1.0.1" /> <PackageReference Include="ChrisKaczor.Common.OpenTelemetry" Version="1.0.2" />
<PackageReference Include="Dapper" Version="2.1.28" /> <PackageReference Include="Dapper" Version="2.1.28" />
<PackageReference Include="dbup-sqlserver" Version="5.0.37" /> <PackageReference Include="dbup-postgresql" Version="5.0.40" />
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" /> <PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.1" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.1" />
<PackageReference Include="MQTTnet.AspNetCore" Version="4.3.3.952" /> <PackageReference Include="MQTTnet.AspNetCore" Version="4.3.3.952" />

View File

@@ -15,9 +15,9 @@
"Host": "", "Host": "",
"User": "", "User": "",
"Password": "", "Password": "",
"Name": "Environment", "Name": "environment",
"TrustServerCertificate": true, "TrustServerCertificate": true,
"Port": 1435 "Port": 5432
}, },
"Hub": { "Hub": {
"Url": "http://hub-server/environment" "Url": "http://hub-server/environment"

View File

@@ -19,27 +19,31 @@ spec:
spec: spec:
containers: containers:
- name: environment-database - name: environment-database
image: mcr.microsoft.com/mssql/server image: timescale/timescaledb:latest-pg16
terminationMessagePath: "/dev/termination-log"
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
env: env:
- name: SA_PASSWORD - name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: environment-database-credentials
key: username
- name: POSTGRES_PASSWORD
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: environment-database-credentials name: environment-database-credentials
key: password key: password
- name: ACCEPT_EULA - name: POSTGRES_DB
value: "Y" value: environment
- name: MSSQL_PID
value: Express
- name: MSSQL_TCP_PORT
value: "1435"
- name: TZ
value: America/New_York
volumeMounts: volumeMounts:
- name: data - name: data
mountPath: /var/opt/mssql mountPath: /var/lib/postgresql/data
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
restartPolicy: Always restartPolicy: Always
terminationGracePeriodSeconds: 30 terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst dnsPolicy: ClusterFirst
@@ -63,7 +67,7 @@ metadata:
spec: spec:
ports: ports:
- name: client - name: client
port: 1435 port: 5432
selector: selector:
app: environment-database app: environment-database
type: LoadBalancer type: LoadBalancer
@@ -108,6 +112,13 @@ spec:
key: password key: password
- name: Environment__Hub__Url - name: Environment__Hub__Url
value: http://hub-service/environment value: http://hub-service/environment
resources:
limits:
cpu: 1
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
restartPolicy: Always restartPolicy: Always
terminationGracePeriodSeconds: 30 terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst dnsPolicy: ClusterFirst