From 5ea391cf2987833fa3d68b90aaa6bf530ba3530f Mon Sep 17 00:00:00 2001 From: Mauro Servienti Date: Wed, 17 Dec 2025 17:14:32 +0100 Subject: [PATCH 1/9] Add a license status check to ensure the RavenDB licence is correctly applied after the database is created before configuring expiration --- .../DatabaseSetup.cs | 3 ++ .../LicenseStatusCheck.cs | 47 +++++++++++++++++++ .../DatabaseSetup.cs | 1 + .../LicenseStatusCheck.cs | 47 +++++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs create mode 100644 src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/DatabaseSetup.cs b/src/ServiceControl.Audit.Persistence.RavenDB/DatabaseSetup.cs index a10410408c..e2def6dfc0 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/DatabaseSetup.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/DatabaseSetup.cs @@ -2,6 +2,8 @@ using System; using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Raven.Client.Documents; @@ -25,6 +27,7 @@ public async Task Execute(IDocumentStore documentStore, CancellationToken cancel await CreateIndexes(documentStore, configuration.EnableFullTextSearch, cancellationToken); + await LicenseStatusCheck.WaitForLicenseOrThrow(configuration, cancellationToken); await ConfigureExpiration(documentStore, cancellationToken); } diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs new file mode 100644 index 0000000000..e5e616487a --- /dev/null +++ b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs @@ -0,0 +1,47 @@ +namespace ServiceControl.Audit.Persistence.RavenDB; + +using System; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +static class LicenseStatusCheck +{ + class LicenseStatusFragment + { + public string Id { get; set; } + public string LicensedTo { get; set; } + public string Status { get; set; } + public bool Expired { get; set; } + } + + public static async Task WaitForLicenseOrThrow(DatabaseConfiguration configuration, CancellationToken cancellationToken) + { + var client = new HttpClient() { BaseAddress = new Uri(configuration.ServerConfiguration.ConnectionString ?? configuration.ServerConfiguration.ServerUrl) }; + var licenseCorrectlySetup = false; + var attempts = 0; + while (!licenseCorrectlySetup) + { + var httpResponse = await client.GetAsync("/license/status", cancellationToken); + var responseJsonString = await httpResponse.Content.ReadAsStringAsync(cancellationToken); + var licenseStatus = JsonSerializer.Deserialize(responseJsonString); + if (licenseStatus.Expired) + { + throw new NotSupportedException("The current RavenDB license is expired. Please, contact support"); + } + + if (licenseStatus.LicensedTo != null && licenseStatus.Id != null) + { + licenseCorrectlySetup = true; + } + + if (++attempts > 10) + { + throw new NotSupportedException("Cannot validate the current RavenDB license. Please, contact support"); + } + + await Task.Delay(500, cancellationToken); + } + } +} \ No newline at end of file diff --git a/src/ServiceControl.Persistence.RavenDB/DatabaseSetup.cs b/src/ServiceControl.Persistence.RavenDB/DatabaseSetup.cs index 89ea46ec3a..c77342946b 100644 --- a/src/ServiceControl.Persistence.RavenDB/DatabaseSetup.cs +++ b/src/ServiceControl.Persistence.RavenDB/DatabaseSetup.cs @@ -23,6 +23,7 @@ public async Task Execute(CancellationToken cancellationToken) await IndexCreation.CreateIndexesAsync(typeof(DatabaseSetup).Assembly, documentStore, null, null, cancellationToken); + await LicenseStatusCheck.WaitForLicenseOrThrow(settings, cancellationToken); await ConfigureExpiration(settings, cancellationToken); } diff --git a/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs new file mode 100644 index 0000000000..c2d4cff591 --- /dev/null +++ b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs @@ -0,0 +1,47 @@ +namespace ServiceControl.Persistence.RavenDB; + +using System; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +static class LicenseStatusCheck +{ + class LicenseStatusFragment + { + public string Id { get; set; } + public string LicensedTo { get; set; } + public string Status { get; set; } + public bool Expired { get; set; } + } + + public static async Task WaitForLicenseOrThrow(RavenPersisterSettings configuration, CancellationToken cancellationToken) + { + var client = new HttpClient() { BaseAddress = new Uri(configuration.ConnectionString ?? configuration.ServerUrl) }; + var licenseCorrectlySetup = false; + var attempts = 0; + while (!licenseCorrectlySetup) + { + var httpResponse = await client.GetAsync("/license/status", cancellationToken); + var responseJsonString = await httpResponse.Content.ReadAsStringAsync(cancellationToken); + var licenseStatus = JsonSerializer.Deserialize(responseJsonString); + if (licenseStatus.Expired) + { + throw new NotSupportedException("The current RavenDB license is expired. Please, contact support"); + } + + if (licenseStatus.LicensedTo != null && licenseStatus.Id != null) + { + licenseCorrectlySetup = true; + } + + if (++attempts > 10) + { + throw new NotSupportedException("Cannot validate the current RavenDB license. Please, contact support"); + } + + await Task.Delay(500, cancellationToken); + } + } +} \ No newline at end of file From 40e0258cfa8fa0ff62664c12259561e1b439afa9 Mon Sep 17 00:00:00 2001 From: Ramon Smits Date: Thu, 18 Dec 2025 12:54:31 +0100 Subject: [PATCH 2/9] record type --- .../LicenseStatusCheck.cs | 8 +------- .../LicenseStatusCheck.cs | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs index e5e616487a..9506c1ea60 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs @@ -8,13 +8,7 @@ namespace ServiceControl.Audit.Persistence.RavenDB; static class LicenseStatusCheck { - class LicenseStatusFragment - { - public string Id { get; set; } - public string LicensedTo { get; set; } - public string Status { get; set; } - public bool Expired { get; set; } - } + record LicenseStatusFragment(string Id, string LicensedTo, string Status, bool Expired); public static async Task WaitForLicenseOrThrow(DatabaseConfiguration configuration, CancellationToken cancellationToken) { diff --git a/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs index c2d4cff591..fa34fbd48a 100644 --- a/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs +++ b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs @@ -8,13 +8,7 @@ namespace ServiceControl.Persistence.RavenDB; static class LicenseStatusCheck { - class LicenseStatusFragment - { - public string Id { get; set; } - public string LicensedTo { get; set; } - public string Status { get; set; } - public bool Expired { get; set; } - } + record LicenseStatusFragment(string Id, string LicensedTo, string Status, bool Expired); public static async Task WaitForLicenseOrThrow(RavenPersisterSettings configuration, CancellationToken cancellationToken) { From e7456ff9bf8d6a8a58645427ca4492b4d546b770 Mon Sep 17 00:00:00 2001 From: Ramon Smits Date: Thu, 18 Dec 2025 12:56:25 +0100 Subject: [PATCH 3/9] Using `/` would override BaseAddress path value --- .../LicenseStatusCheck.cs | 2 +- src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs index 9506c1ea60..6a095b80ac 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs @@ -17,7 +17,7 @@ public static async Task WaitForLicenseOrThrow(DatabaseConfiguration configurati var attempts = 0; while (!licenseCorrectlySetup) { - var httpResponse = await client.GetAsync("/license/status", cancellationToken); + var httpResponse = await client.GetAsync("license/status", cancellationToken); var responseJsonString = await httpResponse.Content.ReadAsStringAsync(cancellationToken); var licenseStatus = JsonSerializer.Deserialize(responseJsonString); if (licenseStatus.Expired) diff --git a/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs index fa34fbd48a..3918ab817e 100644 --- a/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs +++ b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs @@ -17,7 +17,7 @@ public static async Task WaitForLicenseOrThrow(RavenPersisterSettings configurat var attempts = 0; while (!licenseCorrectlySetup) { - var httpResponse = await client.GetAsync("/license/status", cancellationToken); + var httpResponse = await client.GetAsync("license/status", cancellationToken); var responseJsonString = await httpResponse.Content.ReadAsStringAsync(cancellationToken); var licenseStatus = JsonSerializer.Deserialize(responseJsonString); if (licenseStatus.Expired) From 912080456ad1515c6a46870b780512d3fa81fc58 Mon Sep 17 00:00:00 2001 From: Ramon Smits Date: Thu, 18 Dec 2025 13:55:12 +0100 Subject: [PATCH 4/9] ReadFromJsonAsync --- .../LicenseStatusCheck.cs | 4 ++-- src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs index 6a095b80ac..beaf189565 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs @@ -2,6 +2,7 @@ namespace ServiceControl.Audit.Persistence.RavenDB; using System; using System.Net.Http; +using System.Net.Http.Json; using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -18,8 +19,7 @@ public static async Task WaitForLicenseOrThrow(DatabaseConfiguration configurati while (!licenseCorrectlySetup) { var httpResponse = await client.GetAsync("license/status", cancellationToken); - var responseJsonString = await httpResponse.Content.ReadAsStringAsync(cancellationToken); - var licenseStatus = JsonSerializer.Deserialize(responseJsonString); + var licenseStatus = await httpResponse.Content.ReadFromJsonAsync if (licenseStatus.Expired) { throw new NotSupportedException("The current RavenDB license is expired. Please, contact support"); diff --git a/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs index 3918ab817e..c20f4b3331 100644 --- a/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs +++ b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs @@ -2,6 +2,7 @@ namespace ServiceControl.Persistence.RavenDB; using System; using System.Net.Http; +using System.Net.Http.Json; using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -18,8 +19,7 @@ public static async Task WaitForLicenseOrThrow(RavenPersisterSettings configurat while (!licenseCorrectlySetup) { var httpResponse = await client.GetAsync("license/status", cancellationToken); - var responseJsonString = await httpResponse.Content.ReadAsStringAsync(cancellationToken); - var licenseStatus = JsonSerializer.Deserialize(responseJsonString); + var licenseStatus = await httpResponse.Content.ReadFromJsonAsync if (licenseStatus.Expired) { throw new NotSupportedException("The current RavenDB license is expired. Please, contact support"); From 36fd29e63b2979ba96fb72eacc512f5512a3b974 Mon Sep 17 00:00:00 2001 From: Ramon Smits Date: Thu, 18 Dec 2025 13:58:40 +0100 Subject: [PATCH 5/9] fix --- .../LicenseStatusCheck.cs | 2 +- src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs index beaf189565..856ca34e92 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs @@ -19,7 +19,7 @@ public static async Task WaitForLicenseOrThrow(DatabaseConfiguration configurati while (!licenseCorrectlySetup) { var httpResponse = await client.GetAsync("license/status", cancellationToken); - var licenseStatus = await httpResponse.Content.ReadFromJsonAsync + var licenseStatus = await httpResponse.Content.ReadFromJsonAsync(); if (licenseStatus.Expired) { throw new NotSupportedException("The current RavenDB license is expired. Please, contact support"); diff --git a/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs index c20f4b3331..29d405a08f 100644 --- a/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs +++ b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs @@ -19,7 +19,7 @@ public static async Task WaitForLicenseOrThrow(RavenPersisterSettings configurat while (!licenseCorrectlySetup) { var httpResponse = await client.GetAsync("license/status", cancellationToken); - var licenseStatus = await httpResponse.Content.ReadFromJsonAsync + var licenseStatus = await httpResponse.Content.ReadFromJsonAsync(); if (licenseStatus.Expired) { throw new NotSupportedException("The current RavenDB license is expired. Please, contact support"); From 903539f0f5cba4ae2af9aeebe7b43eade014bcf1 Mon Sep 17 00:00:00 2001 From: Ramon Smits Date: Thu, 18 Dec 2025 13:59:34 +0100 Subject: [PATCH 6/9] As we are not re-using HttpClient it can be immediately disposed --- .../LicenseStatusCheck.cs | 2 +- src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs index 856ca34e92..9d887df000 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs @@ -13,7 +13,7 @@ record LicenseStatusFragment(string Id, string LicensedTo, string Status, bool E public static async Task WaitForLicenseOrThrow(DatabaseConfiguration configuration, CancellationToken cancellationToken) { - var client = new HttpClient() { BaseAddress = new Uri(configuration.ServerConfiguration.ConnectionString ?? configuration.ServerConfiguration.ServerUrl) }; + using var client = new HttpClient() { BaseAddress = new Uri(configuration.ServerConfiguration.ConnectionString ?? configuration.ServerConfiguration.ServerUrl) }; var licenseCorrectlySetup = false; var attempts = 0; while (!licenseCorrectlySetup) diff --git a/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs index 29d405a08f..3aef7bacfe 100644 --- a/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs +++ b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs @@ -13,7 +13,7 @@ record LicenseStatusFragment(string Id, string LicensedTo, string Status, bool E public static async Task WaitForLicenseOrThrow(RavenPersisterSettings configuration, CancellationToken cancellationToken) { - var client = new HttpClient() { BaseAddress = new Uri(configuration.ConnectionString ?? configuration.ServerUrl) }; + using var client = new HttpClient() { BaseAddress = new Uri(configuration.ConnectionString ?? configuration.ServerUrl) }; var licenseCorrectlySetup = false; var attempts = 0; while (!licenseCorrectlySetup) From 1fa9f5d8b191f2b02e3aace6cd082dcc3a8e7277 Mon Sep 17 00:00:00 2001 From: Ramon Smits Date: Thu, 18 Dec 2025 14:02:48 +0100 Subject: [PATCH 7/9] Forward cancellation token --- .../LicenseStatusCheck.cs | 2 +- src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs index 9d887df000..c1c2c71980 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs @@ -19,7 +19,7 @@ public static async Task WaitForLicenseOrThrow(DatabaseConfiguration configurati while (!licenseCorrectlySetup) { var httpResponse = await client.GetAsync("license/status", cancellationToken); - var licenseStatus = await httpResponse.Content.ReadFromJsonAsync(); + var licenseStatus = await httpResponse.Content.ReadFromJsonAsync(cancellationToken); if (licenseStatus.Expired) { throw new NotSupportedException("The current RavenDB license is expired. Please, contact support"); diff --git a/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs index 3aef7bacfe..d9074dcd95 100644 --- a/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs +++ b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs @@ -19,7 +19,7 @@ public static async Task WaitForLicenseOrThrow(RavenPersisterSettings configurat while (!licenseCorrectlySetup) { var httpResponse = await client.GetAsync("license/status", cancellationToken); - var licenseStatus = await httpResponse.Content.ReadFromJsonAsync(); + var licenseStatus = await httpResponse.Content.ReadFromJsonAsync(cancellationToken); if (licenseStatus.Expired) { throw new NotSupportedException("The current RavenDB license is expired. Please, contact support"); From dbd04c6294f0614eb59942a9dd0aa8b72627b90c Mon Sep 17 00:00:00 2001 From: Ramon Smits Date: Thu, 18 Dec 2025 15:26:32 +0100 Subject: [PATCH 8/9] Improve license validation logic and exception handling - Refactored license check to use `CancellationTokenSource` for a more robust timeout mechanism. - Simplified loop logic by removing redundant variables. - Replaced `NotSupportedException` with `InvalidOperationException` for better error clarity. --- .../LicenseStatusCheck.cs | 25 +++++++++---------- .../LicenseStatusCheck.cs | 25 +++++++++---------- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs index c1c2c71980..cd9606abaf 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs @@ -3,7 +3,6 @@ namespace ServiceControl.Audit.Persistence.RavenDB; using System; using System.Net.Http; using System.Net.Http.Json; -using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -13,29 +12,29 @@ record LicenseStatusFragment(string Id, string LicensedTo, string Status, bool E public static async Task WaitForLicenseOrThrow(DatabaseConfiguration configuration, CancellationToken cancellationToken) { - using var client = new HttpClient() { BaseAddress = new Uri(configuration.ServerConfiguration.ConnectionString ?? configuration.ServerConfiguration.ServerUrl) }; - var licenseCorrectlySetup = false; - var attempts = 0; - while (!licenseCorrectlySetup) + using var client = new HttpClient + { + BaseAddress = new Uri(configuration.ServerConfiguration.ConnectionString ?? configuration.ServerConfiguration.ServerUrl) + }; + using var cts = new CancellationTokenSource(30_000); + + while (!cts.IsCancellationRequested) { var httpResponse = await client.GetAsync("license/status", cancellationToken); var licenseStatus = await httpResponse.Content.ReadFromJsonAsync(cancellationToken); if (licenseStatus.Expired) { - throw new NotSupportedException("The current RavenDB license is expired. Please, contact support"); + throw new InvalidOperationException("The current RavenDB license is expired. Please, contact support"); } if (licenseStatus.LicensedTo != null && licenseStatus.Id != null) { - licenseCorrectlySetup = true; - } - - if (++attempts > 10) - { - throw new NotSupportedException("Cannot validate the current RavenDB license. Please, contact support"); + return; } - await Task.Delay(500, cancellationToken); + await Task.Delay(200, cancellationToken); } + + throw new InvalidOperationException("Cannot validate the current RavenDB license. Please, contact support"); } } \ No newline at end of file diff --git a/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs index d9074dcd95..12b922b36b 100644 --- a/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs +++ b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs @@ -3,7 +3,6 @@ namespace ServiceControl.Persistence.RavenDB; using System; using System.Net.Http; using System.Net.Http.Json; -using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -13,29 +12,29 @@ record LicenseStatusFragment(string Id, string LicensedTo, string Status, bool E public static async Task WaitForLicenseOrThrow(RavenPersisterSettings configuration, CancellationToken cancellationToken) { - using var client = new HttpClient() { BaseAddress = new Uri(configuration.ConnectionString ?? configuration.ServerUrl) }; - var licenseCorrectlySetup = false; - var attempts = 0; - while (!licenseCorrectlySetup) + using var client = new HttpClient + { + BaseAddress = new Uri(configuration.ConnectionString ?? configuration.ServerUrl) + }; + using var cts = new CancellationTokenSource(30_000); + + while (!cts.IsCancellationRequested) { var httpResponse = await client.GetAsync("license/status", cancellationToken); var licenseStatus = await httpResponse.Content.ReadFromJsonAsync(cancellationToken); if (licenseStatus.Expired) { - throw new NotSupportedException("The current RavenDB license is expired. Please, contact support"); + throw new InvalidOperationException("The current RavenDB license is expired. Please, contact support"); } if (licenseStatus.LicensedTo != null && licenseStatus.Id != null) { - licenseCorrectlySetup = true; - } - - if (++attempts > 10) - { - throw new NotSupportedException("Cannot validate the current RavenDB license. Please, contact support"); + return; } - await Task.Delay(500, cancellationToken); + await Task.Delay(200, cancellationToken); } + + throw new InvalidOperationException("Cannot validate the current RavenDB license. Please, contact support"); } } \ No newline at end of file From d8d206ebe0c1a86cffbdfbfb213b6e53bcc07ba4 Mon Sep 17 00:00:00 2001 From: Mauro Servienti Date: Fri, 19 Dec 2025 10:47:03 +0100 Subject: [PATCH 9/9] Add a comment for posterity --- .../LicenseStatusCheck.cs | 3 ++- src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs index cd9606abaf..9aee22a425 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/LicenseStatusCheck.cs @@ -16,8 +16,9 @@ public static async Task WaitForLicenseOrThrow(DatabaseConfiguration configurati { BaseAddress = new Uri(configuration.ServerConfiguration.ConnectionString ?? configuration.ServerConfiguration.ServerUrl) }; - using var cts = new CancellationTokenSource(30_000); + // Not linking to the incoming cancellationToken to ensure no OperationCancelledException prevents the last InvalidOperationException to be thrown + using var cts = new CancellationTokenSource(30_000); while (!cts.IsCancellationRequested) { var httpResponse = await client.GetAsync("license/status", cancellationToken); diff --git a/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs index 12b922b36b..deb1956cc6 100644 --- a/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs +++ b/src/ServiceControl.Persistence.RavenDB/LicenseStatusCheck.cs @@ -16,8 +16,9 @@ public static async Task WaitForLicenseOrThrow(RavenPersisterSettings configurat { BaseAddress = new Uri(configuration.ConnectionString ?? configuration.ServerUrl) }; - using var cts = new CancellationTokenSource(30_000); + // Not linking to the incoming cancellationToken to ensure no OperationCancelledException prevents the last InvalidOperationException to be thrown + using var cts = new CancellationTokenSource(30_000); while (!cts.IsCancellationRequested) { var httpResponse = await client.GetAsync("license/status", cancellationToken);