refactor(core): Send active workflow IDs during license renewal (#9804)

This commit is contained in:
Iván Ovejero 2024-06-19 12:35:42 +02:00 committed by GitHub
parent de3981cbde
commit cfc4db00e3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 83 additions and 8 deletions

View file

@ -99,7 +99,7 @@
"@n8n/n8n-nodes-langchain": "workspace:*", "@n8n/n8n-nodes-langchain": "workspace:*",
"@n8n/permissions": "workspace:*", "@n8n/permissions": "workspace:*",
"@n8n/typeorm": "0.3.20-10", "@n8n/typeorm": "0.3.20-10",
"@n8n_io/license-sdk": "2.12.0", "@n8n_io/license-sdk": "2.13.0",
"@oclif/core": "3.26.6", "@oclif/core": "3.26.6",
"@pinecone-database/pinecone": "2.1.0", "@pinecone-database/pinecone": "2.1.0",
"@rudderstack/rudder-sdk-node": "2.0.7", "@rudderstack/rudder-sdk-node": "2.0.7",

View file

@ -84,6 +84,9 @@ export class License {
const collectUsageMetrics = isMainInstance const collectUsageMetrics = isMainInstance
? async () => await this.usageMetricsService.collectUsageMetrics() ? async () => await this.usageMetricsService.collectUsageMetrics()
: async () => []; : async () => [];
const collectPassthroughData = isMainInstance
? async () => await this.usageMetricsService.getActiveWorkflowIds()
: async () => ({});
const renewalEnabled = this.renewalEnabled(instanceType); const renewalEnabled = this.renewalEnabled(instanceType);
@ -101,6 +104,7 @@ export class License {
saveCertStr, saveCertStr,
deviceFingerprint: () => this.instanceSettings.instanceId, deviceFingerprint: () => this.instanceSettings.instanceId,
collectUsageMetrics, collectUsageMetrics,
collectPassthroughData,
onFeatureChange, onFeatureChange,
}); });

View file

@ -1,9 +1,13 @@
import { UsageMetricsRepository } from '@/databases/repositories/usageMetrics.repository'; import { UsageMetricsRepository } from '@/databases/repositories/usageMetrics.repository';
import { Service } from 'typedi'; import { Service } from 'typedi';
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
@Service() @Service()
export class UsageMetricsService { export class UsageMetricsService {
constructor(private readonly usageMetricsRepository: UsageMetricsRepository) {} constructor(
private readonly usageMetricsRepository: UsageMetricsRepository,
private readonly workflowRepository: WorkflowRepository,
) {}
async collectUsageMetrics() { async collectUsageMetrics() {
const { const {
@ -26,4 +30,10 @@ export class UsageMetricsService {
{ name: 'manualExecutions', value: manualExecutions }, { name: 'manualExecutions', value: manualExecutions },
]; ];
} }
async getActiveWorkflowIds() {
return {
activeWorkflowIds: await this.workflowRepository.getActiveIds(),
};
}
} }

View file

@ -3,7 +3,11 @@ import Container from 'typedi';
import { WorkflowRepository } from '@/databases/repositories/workflow.repository'; import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
import * as testDb from '../../shared/testDb'; import * as testDb from '../../shared/testDb';
import { createWorkflowWithTrigger, getAllWorkflows } from '../../shared/db/workflows'; import {
createWorkflowWithTrigger,
createWorkflow,
getAllWorkflows,
} from '../../shared/db/workflows';
describe('WorkflowRepository', () => { describe('WorkflowRepository', () => {
beforeAll(async () => { beforeAll(async () => {
@ -67,4 +71,27 @@ describe('WorkflowRepository', () => {
expect(after).toMatchObject([{ active: false }, { active: false }]); expect(after).toMatchObject([{ active: false }, { active: false }]);
}); });
}); });
describe('getActiveIds', () => {
it('should return active workflow IDs', async () => {
//
// ARRANGE
//
const workflows = await Promise.all([
createWorkflow({ active: true }),
createWorkflow({ active: false }),
createWorkflow({ active: false }),
]);
//
// ACT
//
const activeIds = await Container.get(WorkflowRepository).getActiveIds();
//
// ASSERT
//
expect(activeIds).toEqual([workflows[0].id]);
});
});
}); });

View file

@ -0,0 +1,32 @@
import { mock } from 'jest-mock-extended';
import { UsageMetricsService } from '@/services/usageMetrics.service';
import type { WorkflowRepository } from '@/databases/repositories/workflow.repository';
import type { UsageMetricsRepository } from '@/databases/repositories/usageMetrics.repository';
describe('UsageMetricsService', () => {
const workflowRepository = mock<WorkflowRepository>();
const usageMetricsService = new UsageMetricsService(
mock<UsageMetricsRepository>(),
workflowRepository,
);
describe('getActiveWorkflowIds', () => {
test('should return active workflow IDs', async () => {
/**
* Arrange
*/
const activeWorkflowIds = ['1', '2'];
workflowRepository.getActiveIds.mockResolvedValue(activeWorkflowIds);
/**
* Act
*/
const result = await usageMetricsService.getActiveWorkflowIds();
/**
* Assert
*/
expect(result).toEqual({ activeWorkflowIds });
});
});
});

View file

@ -48,6 +48,7 @@ describe('License', () => {
saveCertStr: expect.any(Function), saveCertStr: expect.any(Function),
onFeatureChange: expect.any(Function), onFeatureChange: expect.any(Function),
collectUsageMetrics: expect.any(Function), collectUsageMetrics: expect.any(Function),
collectPassthroughData: expect.any(Function),
server: MOCK_SERVER_URL, server: MOCK_SERVER_URL,
tenantId: 1, tenantId: 1,
}); });
@ -68,6 +69,7 @@ describe('License', () => {
saveCertStr: expect.any(Function), saveCertStr: expect.any(Function),
onFeatureChange: expect.any(Function), onFeatureChange: expect.any(Function),
collectUsageMetrics: expect.any(Function), collectUsageMetrics: expect.any(Function),
collectPassthroughData: expect.any(Function),
server: MOCK_SERVER_URL, server: MOCK_SERVER_URL,
tenantId: 1, tenantId: 1,
}); });

View file

@ -550,8 +550,8 @@ importers:
specifier: 0.3.20-10 specifier: 0.3.20-10
version: 0.3.20-10(@sentry/node@7.87.0)(ioredis@5.3.2)(mssql@10.0.2)(mysql2@3.10.0)(pg@8.11.3)(redis@4.6.13)(sqlite3@5.1.7) version: 0.3.20-10(@sentry/node@7.87.0)(ioredis@5.3.2)(mssql@10.0.2)(mysql2@3.10.0)(pg@8.11.3)(redis@4.6.13)(sqlite3@5.1.7)
'@n8n_io/license-sdk': '@n8n_io/license-sdk':
specifier: 2.12.0 specifier: 2.13.0
version: 2.12.0 version: 2.13.0
'@oclif/core': '@oclif/core':
specifier: 3.26.6 specifier: 3.26.6
version: 3.26.6 version: 3.26.6
@ -4124,8 +4124,8 @@ packages:
engines: {node: '>=18.10', pnpm: '>=8.6.12'} engines: {node: '>=18.10', pnpm: '>=8.6.12'}
hasBin: true hasBin: true
'@n8n_io/license-sdk@2.12.0': '@n8n_io/license-sdk@2.13.0':
resolution: {integrity: sha512-hxXdaFlzd1moR5NWPCdGiKHyIuDTuiM8AYcH5qo2/Cbu93C8za8a0x19q5gZ1ahADRPfO48k9eYMTjxGhqNkBg==} resolution: {integrity: sha512-iVER9RjR6pP4ujceG7rSMoHU0IMI5HvwNHhC8ezq1VwbRq8W1ecYQpTbIrUTgK6gNMyeLRfySkNlVGejKXJ3MQ==}
engines: {node: '>=18.12.1'} engines: {node: '>=18.12.1'}
'@n8n_io/riot-tmpl@4.0.0': '@n8n_io/riot-tmpl@4.0.0':
@ -17121,7 +17121,7 @@ snapshots:
acorn: 8.11.2 acorn: 8.11.2
acorn-walk: 8.2.0 acorn-walk: 8.2.0
'@n8n_io/license-sdk@2.12.0': '@n8n_io/license-sdk@2.13.0':
dependencies: dependencies:
crypto-js: 4.2.0 crypto-js: 4.2.0
node-machine-id: 1.1.12 node-machine-id: 1.1.12