Skip to content

Commit 6081aad

Browse files
authored
angular, dotnet upgrades, db speed improvements (#109)
* no tracking (cherry picked from commit 3b2d903) * package upgrades (cherry picked from commit 95a69b2) * improve stats query * remove debug * rename front end app * rename app * correct dist folder * fix logging out * icons aligned, mobile response * this too * hook searching back up * handle slow internet better * try tracking * downgrade ef * image compression * set temp folder to config folder * optimize filters query * upgraded to dotnet7, reworked statistics query * fix windows build, fix migrate * get rid of rest of fx styling * more mobile responsive * move images to another table * fix logger * add cleanup vacuum * outside transaction * fix images in queries * loading icon styling * added pwa * add push notifications * generate keys on startup if missing * turn service worker off locally
1 parent a331007 commit 6081aad

281 files changed

Lines changed: 7595 additions & 692 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dockerignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,7 @@
2121
**/obj
2222
**/secrets.dev.yaml
2323
**/values.dev.yaml
24+
**/.angular
25+
**/config
2426
LICENSE
2527
README.md

.github/workflows/docker-publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
- name: Setup Buildx
3535
uses: actions/setup-dotnet@v1
3636
with:
37-
dotnet-version: '6.0.x'
37+
dotnet-version: '7.x'
3838
include-prerelease: true
3939

4040
- name: Build Artifact

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,4 +356,4 @@ dist/
356356
**/log*.txt
357357
*db-shm
358358
*db-wal
359-
OpenAlprWebhookProcessor/ClientApp/.angular/*
359+
OpenAlprWebhookProcessor/angularapp/.angular/*

OpenAlprWebhookProcessor/Alerts/AlertService.cs

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using OpenAlprWebhookProcessor.Data;
77
using System;
88
using System.Collections.Concurrent;
9+
using System.Collections.Generic;
910
using System.Linq;
1011
using System.Threading;
1112
using System.Threading.Tasks;
@@ -24,20 +25,20 @@ public class AlertService : IHostedService
2425

2526
private readonly IHubContext<ProcessorHub.ProcessorHub, ProcessorHub.IProcessorHub> _processorHub;
2627

27-
private readonly IAlertClient _alertClient;
28+
private readonly IEnumerable<IAlertClient> _alertClients;
2829

2930
public AlertService(
3031
IServiceProvider serviceProvider,
3132
ILogger<AlertService> logger,
3233
IHubContext<ProcessorHub.ProcessorHub, ProcessorHub.IProcessorHub> processorHub,
33-
IAlertClient alertClient)
34+
IEnumerable<IAlertClient> alertClients)
3435
{
3536
_logger = logger;
3637
_serviceProvider = serviceProvider;
3738
_cancellationTokenSource = new CancellationTokenSource();
3839
_alertsToProcess = new BlockingCollection<AlertUpdateRequest>();
3940
_processorHub = processorHub;
40-
_alertClient = alertClient;
41+
_alertClients = alertClients;
4142
}
4243

4344
public void AddJob(AlertUpdateRequest request)
@@ -81,27 +82,32 @@ private async Task ProcessAlertsAsync()
8182
plateGroups = plateGroups.Where(x => x.Id == job.LicensePlateId);
8283
}
8384

84-
var result = await plateGroups.FirstOrDefaultAsync(_cancellationTokenSource.Token);
85+
var result = await plateGroups
86+
.Include(x => x.PlateImage)
87+
.FirstOrDefaultAsync(_cancellationTokenSource.Token);
8588

8689
if (result != null)
8790
{
8891
_logger.LogInformation("alerting for: {alertId}", result.Id);
8992
await _processorHub.Clients.All.LicensePlateAlerted(result.Id.ToString());
9093

91-
try
94+
foreach (var alertClient in _alertClients)
9295
{
93-
await _alertClient.SendAlertAsync(new Alert()
96+
try
9497
{
95-
Description = job.Description,
96-
Id = result.Id,
97-
PlateNumber = result.BestNumber,
98-
},
99-
result.PlatePreviewJpeg,
100-
_cancellationTokenSource.Token);
101-
}
102-
catch (Exception ex)
103-
{
104-
_logger.LogError(ex, $"failed to send alert to {nameof(_alertClient)}");
98+
await alertClient.SendAlertAsync(new Alert()
99+
{
100+
Description = job.Description,
101+
Id = result.Id,
102+
PlateNumber = result.BestNumber,
103+
},
104+
result.PlateImage.Jpeg,
105+
_cancellationTokenSource.Token);
106+
}
107+
catch (Exception ex)
108+
{
109+
_logger.LogError(ex, $"failed to send alert to {nameof(alertClient)}");
110+
}
105111
}
106112
}
107113
}

OpenAlprWebhookProcessor/Alerts/AlertsController.cs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Microsoft.AspNetCore.Authorization;
22
using Microsoft.AspNetCore.Mvc;
33
using OpenAlprWebhookProcessor.Alerts.Pushover;
4+
using OpenAlprWebhookProcessor.Alerts.WebPush;
45
using System.Collections.Generic;
56
using System.Threading;
67
using System.Threading.Tasks;
@@ -22,18 +23,30 @@ public class AlertsController : Controller
2223

2324
private readonly TestPushoverClientRequestHandler _testPushoverClientRequestHandler;
2425

26+
private readonly UpsertWebPushClientRequestHandler _upsertWebPushRequestHandler;
27+
28+
private readonly GetWebPushClientRequestHandler _getWebPushClientRequestHandler;
29+
30+
private readonly TestWebPushClientRequestHandler _testWebPushClientRequestHandler;
31+
2532
public AlertsController(
2633
GetAlertsRequestHandler getAlertsRequestHandler,
2734
UpsertAlertsRequestHandler upsertAlertsRequestHandler,
2835
UpsertPushoverClientRequestHandler upsertPushoverRequestHandler,
2936
GetPushoverClientRequestHandler getPushoverClientRequestHandler,
30-
TestPushoverClientRequestHandler testPushoverClientRequestHandler)
37+
TestPushoverClientRequestHandler testPushoverClientRequestHandler,
38+
UpsertWebPushClientRequestHandler upsertWebPushRequestHandler,
39+
GetWebPushClientRequestHandler getWebPushClientRequestHandler,
40+
TestWebPushClientRequestHandler testWebPushClientRequestHandler)
3141
{
3242
_getAlertsRequestHandler = getAlertsRequestHandler;
3343
_upsertAlertsRequestHandler = upsertAlertsRequestHandler;
3444
_upsertPushoverRequestHandler = upsertPushoverRequestHandler;
3545
_getPushoverClientRequestHandler = getPushoverClientRequestHandler;
3646
_testPushoverClientRequestHandler = testPushoverClientRequestHandler;
47+
_upsertWebPushRequestHandler = upsertWebPushRequestHandler;
48+
_getWebPushClientRequestHandler = getWebPushClientRequestHandler;
49+
_testWebPushClientRequestHandler = testWebPushClientRequestHandler;
3750
}
3851

3952
[HttpPost("add")]
@@ -71,5 +84,23 @@ public async Task<PushoverRequest> GetPushover(CancellationToken cancellationTok
7184
{
7285
return await _getPushoverClientRequestHandler.HandleAsync(cancellationToken);
7386
}
87+
88+
[HttpPost("webpush")]
89+
public async Task UpsertWebpush([FromBody] WebPushRequest request)
90+
{
91+
await _upsertWebPushRequestHandler.HandleAsync(request);
92+
}
93+
94+
[HttpPost("webpush/test")]
95+
public async Task UpsertWebpush(CancellationToken cancellationToken)
96+
{
97+
await _testWebPushClientRequestHandler.HandleAsync(cancellationToken);
98+
}
99+
100+
[HttpGet("webpush")]
101+
public async Task<WebPushRequest> GetWebpush(CancellationToken cancellationToken)
102+
{
103+
return await _getWebPushClientRequestHandler.HandleAsync(cancellationToken);
104+
}
74105
}
75106
}

OpenAlprWebhookProcessor/Alerts/IAlertClient.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Threading;
1+
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
2+
using System.Threading;
23
using System.Threading.Tasks;
34

45
namespace OpenAlprWebhookProcessor.Alerts
@@ -7,7 +8,7 @@ public interface IAlertClient
78
{
89
Task SendAlertAsync(
910
Alert alert,
10-
string base64PreviewJpeg,
11+
byte[] plateJpeg,
1112
CancellationToken cancellationToken);
1213

1314
Task VerifyCredentialsAsync(

OpenAlprWebhookProcessor/Alerts/Pushover/PushoverClient.cs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public PushoverClient(IServiceProvider serviceProvider)
2828

2929
public async Task SendAlertAsync(
3030
Alert alert,
31-
string base64PreviewJpeg,
31+
byte[] plateJpeg,
3232
CancellationToken cancellationToken)
3333
{
3434
using (var scope = _serviceProvider.CreateScope())
@@ -39,7 +39,9 @@ public async Task SendAlertAsync(
3939

4040
var processorContext = scope.ServiceProvider.GetRequiredService<ProcessorContext>();
4141

42-
var clientSettings = await processorContext.PushoverAlertClients.FirstOrDefaultAsync(cancellationToken);
42+
var clientSettings = await processorContext.PushoverAlertClients
43+
.AsNoTracking()
44+
.FirstOrDefaultAsync(cancellationToken);
4345

4446
var boundary = Guid.NewGuid().ToString();
4547
using (var content = new MultipartFormDataContent(boundary))
@@ -51,9 +53,9 @@ public async Task SendAlertAsync(
5153
content.Add(new StringContent(alert.PlateNumber + " " + alert.Description), "message");
5254
content.Add(new StringContent("openalpr alert"), "title");
5355

54-
if (clientSettings.SendPlatePreview)
56+
if (clientSettings.SendPlatePreview && plateJpeg != null)
5557
{
56-
content.Add(new ByteArrayContent(Convert.FromBase64String(base64PreviewJpeg)), "attachment", "attachment.jpg");
58+
content.Add(new ByteArrayContent(plateJpeg), "attachment", "attachment.jpg");
5759
}
5860

5961
try
@@ -67,15 +69,15 @@ public async Task SendAlertAsync(
6769
{
6870
var result = await response.Content.ReadAsStringAsync(cancellationToken);
6971

70-
logger.LogError("Failed to send alert via Pushover: " + result);
72+
logger.LogError("Failed to send alert via Pushover: {result}", result);
7173
throw new InvalidOperationException("failed");
7274
}
7375

7476
logger.LogInformation("Alert sent via Pushover.");
7577
}
7678
catch (Exception ex)
7779
{
78-
logger.LogError(ex, "Failed to send alert via Pushover: " + ex.Message);
80+
logger.LogError(ex, "Failed to send alert via Pushover: {exception}", ex.Message);
7981
throw new InvalidOperationException("failed");
8082
}
8183
}
@@ -92,27 +94,29 @@ public async Task VerifyCredentialsAsync(CancellationToken cancellationToken)
9294

9395
var processorContext = scope.ServiceProvider.GetRequiredService<ProcessorContext>();
9496

95-
var clientSettings = await processorContext.PushoverAlertClients.FirstOrDefaultAsync(cancellationToken);
97+
var clientSettings = await processorContext.PushoverAlertClients
98+
.AsNoTracking()
99+
.FirstOrDefaultAsync(cancellationToken);
96100

97101
try
98102
{
99103
var result = await _httpClient.PostAsync(VerifyCredentialsUrl
100-
.Replace("{0}", clientSettings.ApiToken)
101-
.Replace("{1}", clientSettings.UserKey),
104+
.Replace("{0}", clientSettings.ApiToken)
105+
.Replace("{1}", clientSettings.UserKey),
102106
null,
103107
cancellationToken);
104108

105109
if (!result.IsSuccessStatusCode)
106110
{
107111
var message = await result.Content.ReadAsStringAsync(cancellationToken);
108-
logger.LogError("Pushover credential check failed: " + message);
112+
logger.LogError("Pushover credential check failed: {message}", message);
109113
}
110114

111115
logger.LogInformation("Pushover credentials are valid.");
112116
}
113117
catch (Exception ex)
114118
{
115-
logger.LogError(ex, "Pushover credential check failed: " + ex.Message);
119+
logger.LogError(ex, "Pushover credential check failed: {exception}", ex.Message);
116120
}
117121
}
118122
}

OpenAlprWebhookProcessor/Alerts/Pushover/TestPushoverClientRequestHandler.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using Microsoft.EntityFrameworkCore;
22
using OpenAlprWebhookProcessor.Data;
3+
using OpenAlprWebhookProcessor.WebPushSubscriptions;
34
using System;
5+
using System.Collections.Generic;
46
using System.Linq;
57
using System.Threading;
68
using System.Threading.Tasks;
@@ -14,16 +16,17 @@ public class TestPushoverClientRequestHandler
1416
private readonly IAlertClient _alertClient;
1517

1618
public TestPushoverClientRequestHandler(ProcessorContext processorContext,
17-
IAlertClient alertClient)
19+
IEnumerable<IAlertClient> alertClients)
1820
{
1921
_processorContext = processorContext;
20-
_alertClient = alertClient;
22+
_alertClient = alertClients.First(x => x is WebPushNotificationProducer);
2123
}
2224

2325
public async Task HandleAsync(CancellationToken cancellationToken)
2426
{
2527
var testPlateGroup = await _processorContext.PlateGroups
26-
.Where(x => x.PlatePreviewJpeg != null)
28+
.Include(x => x.PlateImage)
29+
.Where(x => x.PlateImage != null)
2730
.FirstOrDefaultAsync(cancellationToken);
2831

2932
await _alertClient.VerifyCredentialsAsync(cancellationToken);
@@ -35,7 +38,7 @@ await _alertClient.SendAlertAsync(new Alert()
3538
PlateNumber = testPlateGroup.BestNumber,
3639
StrictMatch = false,
3740
},
38-
testPlateGroup.PlatePreviewJpeg,
41+
testPlateGroup.PlateImage.Jpeg,
3942
cancellationToken);
4043
}
4144
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using OpenAlprWebhookProcessor.Data;
2+
using System.Threading.Tasks;
3+
using System.Threading;
4+
using Microsoft.EntityFrameworkCore;
5+
using OpenAlprWebhookProcessor.WebPushSubscriptions.VapidKeys;
6+
7+
namespace OpenAlprWebhookProcessor.Alerts.WebPush
8+
{
9+
public class GetWebPushClientRequestHandler
10+
{
11+
private readonly ProcessorContext _processorContext;
12+
13+
public GetWebPushClientRequestHandler(ProcessorContext processorContext)
14+
{
15+
_processorContext = processorContext;
16+
}
17+
18+
public async Task<WebPushRequest> HandleAsync(CancellationToken cancellationToken)
19+
{
20+
var client = await _processorContext.WebPushSettings.FirstOrDefaultAsync(cancellationToken);
21+
22+
if (client == null)
23+
{
24+
client = VapidKeyHelper.AddVapidKeys(_processorContext);
25+
}
26+
27+
return new WebPushRequest()
28+
{
29+
IsEnabled = client.IsEnabled,
30+
EmailAddress = client.Subject,
31+
PublicKey = client.PublicKey,
32+
PrivateKey = client.PrivateKey,
33+
};
34+
}
35+
}
36+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using Microsoft.EntityFrameworkCore;
2+
using OpenAlprWebhookProcessor.Data;
3+
using OpenAlprWebhookProcessor.WebPushSubscriptions;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Threading;
8+
using System.Threading.Tasks;
9+
10+
namespace OpenAlprWebhookProcessor.Alerts.WebPush
11+
{
12+
public class TestWebPushClientRequestHandler
13+
{
14+
private readonly ProcessorContext _processorContext;
15+
16+
private readonly IAlertClient _alertClient;
17+
18+
public TestWebPushClientRequestHandler(ProcessorContext processorContext,
19+
IEnumerable<IAlertClient> alertClients)
20+
{
21+
_processorContext = processorContext;
22+
_alertClient = alertClients.First(x => x is WebPushNotificationProducer);
23+
}
24+
25+
public async Task HandleAsync(CancellationToken cancellationToken)
26+
{
27+
var testPlateGroup = await _processorContext.PlateGroups
28+
.Include(x => x.PlateImage)
29+
.Where(x => x.PlateImage != null)
30+
.FirstOrDefaultAsync(cancellationToken);
31+
32+
await _alertClient.VerifyCredentialsAsync(cancellationToken);
33+
34+
await _alertClient.SendAlertAsync(new Alert()
35+
{
36+
Description = "was seen on " + DateTimeOffset.Now.ToString("g"),
37+
Id = testPlateGroup.Id,
38+
PlateNumber = testPlateGroup.BestNumber,
39+
StrictMatch = false,
40+
},
41+
testPlateGroup.PlateImage.Jpeg,
42+
cancellationToken);
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)