[DB-1606] Reflect license renewals without restarting the node - #5648
[DB-1606] Reflect license renewals without restarting the node#5648timothycoleman wants to merge 5 commits into
Conversation
PR Summary by QodoRevalidate licenses at runtime, live-refresh admin License page, and add single-node fallback Description
Diagram
High-Level Assessment
Files changed (13)
|
A node with a valid license now periodically revalidates with the licensing server while running, instead of only validating once at startup. A renewed expiry date (or changed entitlements) is picked up without a restart. The License page in the admin UI now updates live when the license changes, instead of only showing the license as it was when the page was first opened. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
42b54e8 to
548cb50
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates KurrentDB’s licensing flow so that a running node periodically revalidates with the licensing server (allowing renewed expiries/entitlements to be picked up without restart), and the Admin UI License page reflects license changes live.
Changes:
- Add periodic revalidation in
KeygenLifecycleServicebased on a configurable “heartbeats per revalidation” cadence. - Introduce a single-node fallback license provider (granting
ALLentitlements when no usable license is available in single-node mode). - Make the License admin page subscribe to license changes so it updates while open.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/KurrentDB/Components/Pages/License.razor | Subscribes to license updates to refresh the page live; adds prerender vs interactive handling. |
| src/KurrentDB.Plugins/Licensing/License.cs | Extends minted JWT expiration window to avoid short-lived self-signed licenses expiring. |
| src/KurrentDB.Licensing/SingleNodeFallbackLicenseProvider.cs | Adds single-node “grant ALL” fallback when the inner provider errors. |
| src/KurrentDB.Licensing/NoLicenseKeyException.cs | Introduces a dedicated exception type for “no license configured”. |
| src/KurrentDB.Licensing/LicensingPlugin.cs | Wires periodic revalidation and the single-node fallback provider into DI/service setup. |
| src/KurrentDB.Licensing/LicenseSummary.cs | Adds helper to mint a license token from a summary + entitlements. |
| src/KurrentDB.Licensing/Keygen/KeygenLifecycleService.cs | Implements periodic revalidation by restarting after N successful heartbeats. |
| src/KurrentDB.Licensing/Keygen/KeygenLicenseProvider.cs | Refactors to use LicenseSummary.CreateLicense. |
| src/KurrentDB.Licensing.Tests/SingleNodeFallbackLicenseProviderTests.cs | Adds tests for pass-through vs fallback behavior in single- vs multi-node. |
| src/KurrentDB.Licensing.Tests/LicensingPluginTests.cs | Updates construction for new isSingleNode parameter. |
| src/KurrentDB.Licensing.Tests/Keygen/KeygenSimulator.Replies.cs | Allows test simulator to vary expiry in validation responses. |
| src/KurrentDB.Licensing.Tests/Keygen/KeygenLifecycleServiceTests.cs | Adds coverage ensuring revalidation picks up renewed expiry. |
| src/KurrentDB.Core/ClusterVNode.cs | Passes isSingleNode into LicensingPlugin. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Code Review by Qodo
1. LicensingPlugin bool arg unnamed
|
| new Fingerprint(clientOptions.Licensing.IncludePortInFingerprint ? clientOptions.NodePort : null), | ||
| heartbeatsPerRevalidation: 4, | ||
| revalidationDelay: TimeSpan.FromSeconds(10)); |
There was a problem hiding this comment.
3. heartbeatsperrevalidation magic number 📘 Rule violation ⚙ Maintainability
heartbeatsPerRevalidation: 4 is a magic number embedded at the call site. This violates the guideline to use a named constant/config value so the meaning and tuning intent are explicit.
Agent Prompt
## Issue description
A numeric literal (`4`) is used for `heartbeatsPerRevalidation`, making the behavior/tuning intent unclear and violating the no-magic-numbers convention.
## Issue Context
Introduce a named constant (or configuration) that documents why `4` is chosen, and use that value at the call site.
## Fix Focus Areas
- src/KurrentDB.Licensing/LicensingPlugin.cs[85-87]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Switch the License page to the modern nullable-reference-types style, replacing the JetBrains [CanBeNull] annotations with `?`. The _subscription field is left null during the prerender pass, matching the Dispose null-check. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A node with a valid license now periodically revalidates with the licensing server while running, instead of only validating once at
startup. A renewed expiry date (or changed entitlements) is picked up without a restart.
The License page in the admin UI now updates live when the license changes, instead of only showing the license as it was when the page was first opened.