mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 10:02:05 +00:00
refactor(core): Make instances more resilient to license sync issues (#16627)
This commit is contained in:
@@ -214,6 +214,64 @@ describe('License', () => {
|
|||||||
const mainPlan = license.getMainPlan();
|
const mainPlan = license.getMainPlan();
|
||||||
expect(mainPlan).toBeUndefined();
|
expect(mainPlan).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('onExpirySoon', () => {
|
||||||
|
it.each([
|
||||||
|
{
|
||||||
|
instanceType: 'main' as const,
|
||||||
|
isLeader: true,
|
||||||
|
shouldReload: false,
|
||||||
|
description: 'Leader main should not reload',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instanceType: 'main' as const,
|
||||||
|
isLeader: false,
|
||||||
|
shouldReload: true,
|
||||||
|
description: 'Follower main should reload',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instanceType: 'worker' as const,
|
||||||
|
isLeader: false,
|
||||||
|
shouldReload: true,
|
||||||
|
description: 'Worker should reload',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instanceType: 'webhook' as const,
|
||||||
|
isLeader: false,
|
||||||
|
shouldReload: true,
|
||||||
|
description: 'Webhook should reload',
|
||||||
|
},
|
||||||
|
])('$description', async ({ instanceType, isLeader, shouldReload }) => {
|
||||||
|
const logger = mockLogger();
|
||||||
|
const reloadSpy = jest.spyOn(License.prototype, 'reload').mockResolvedValueOnce();
|
||||||
|
const instanceSettings = mock<InstanceSettings>({ instanceType });
|
||||||
|
Object.defineProperty(instanceSettings, 'isLeader', { get: () => isLeader });
|
||||||
|
|
||||||
|
license = new License(
|
||||||
|
logger,
|
||||||
|
instanceSettings,
|
||||||
|
mock(),
|
||||||
|
mock(),
|
||||||
|
mock<GlobalConfig>({ license: licenseConfig }),
|
||||||
|
);
|
||||||
|
|
||||||
|
await license.init();
|
||||||
|
|
||||||
|
const licenseManager = LicenseManager as jest.MockedClass<typeof LicenseManager>;
|
||||||
|
const calls = licenseManager.mock.calls;
|
||||||
|
const licenseManagerCall = calls[calls.length - 1][0];
|
||||||
|
const onExpirySoon = licenseManagerCall.onExpirySoon;
|
||||||
|
|
||||||
|
if (shouldReload) {
|
||||||
|
expect(onExpirySoon).toBeDefined();
|
||||||
|
onExpirySoon!();
|
||||||
|
expect(reloadSpy).toHaveBeenCalled();
|
||||||
|
} else {
|
||||||
|
expect(onExpirySoon).toBeUndefined();
|
||||||
|
expect(reloadSpy).not.toHaveBeenCalled();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('License', () => {
|
describe('License', () => {
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ export class License implements LicenseProvider {
|
|||||||
const collectPassthroughData = isMainInstance
|
const collectPassthroughData = isMainInstance
|
||||||
? async () => await this.licenseMetricsService.collectPassthroughData()
|
? async () => await this.licenseMetricsService.collectPassthroughData()
|
||||||
: async () => ({});
|
: async () => ({});
|
||||||
|
const onExpirySoon = !this.instanceSettings.isLeader ? () => this.onExpirySoon() : undefined;
|
||||||
|
const expirySoonOffsetMins = !this.instanceSettings.isLeader ? 120 : undefined;
|
||||||
|
|
||||||
const { isLeader } = this.instanceSettings;
|
const { isLeader } = this.instanceSettings;
|
||||||
const { autoRenewalEnabled } = this.globalConfig.license;
|
const { autoRenewalEnabled } = this.globalConfig.license;
|
||||||
@@ -107,6 +109,8 @@ export class License implements LicenseProvider {
|
|||||||
collectPassthroughData,
|
collectPassthroughData,
|
||||||
onFeatureChange,
|
onFeatureChange,
|
||||||
onLicenseRenewed,
|
onLicenseRenewed,
|
||||||
|
onExpirySoon,
|
||||||
|
expirySoonOffsetMins,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.manager.initialize();
|
await this.manager.initialize();
|
||||||
@@ -433,4 +437,20 @@ export class License implements LicenseProvider {
|
|||||||
disableAutoRenewals() {
|
disableAutoRenewals() {
|
||||||
this.manager?.disableAutoRenewals();
|
this.manager?.disableAutoRenewals();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onExpirySoon() {
|
||||||
|
this.logger.info('License is about to expire soon, reloading license...');
|
||||||
|
|
||||||
|
// reload in background to avoid blocking SDK
|
||||||
|
|
||||||
|
void this.reload()
|
||||||
|
.then(() => {
|
||||||
|
this.logger.info('Reloaded license on expiry soon');
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.logger.error('Failed to reload license on expiry soon', {
|
||||||
|
error: error instanceof Error ? error.message : error,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user