disable workflow execution if billing issue (#11374)
closes https://github.com/twentyhq/core-team-issues/issues/404
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { BillingModule } from 'src/engine/core-modules/billing/billing.module';
|
||||
import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory';
|
||||
import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-common.module';
|
||||
import { WorkflowExecutorFactory } from 'src/modules/workflow/workflow-executor/factories/workflow-executor.factory';
|
||||
@ -18,6 +19,7 @@ import { WorkflowRunModule } from 'src/modules/workflow/workflow-runner/workflow
|
||||
RecordCRUDActionModule,
|
||||
FormActionModule,
|
||||
WorkflowRunModule,
|
||||
BillingModule,
|
||||
],
|
||||
providers: [
|
||||
WorkflowExecutorWorkspaceService,
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { BILLING_FEATURE_USED } from 'src/engine/core-modules/billing/constants/billing-feature-used.constant';
|
||||
import { BILLING_WORKFLOW_EXECUTION_ERROR_MESSAGE } from 'src/engine/core-modules/billing/constants/billing-workflow-execution-error-message.constant';
|
||||
import { BillingMeterEventName } from 'src/engine/core-modules/billing/enums/billing-meter-event-names';
|
||||
import { BillingService } from 'src/engine/core-modules/billing/services/billing.service';
|
||||
import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory';
|
||||
import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter';
|
||||
import { WorkflowExecutorFactory } from 'src/modules/workflow/workflow-executor/factories/workflow-executor.factory';
|
||||
@ -39,6 +41,11 @@ describe('WorkflowExecutorWorkspaceService', () => {
|
||||
saveWorkflowRunState: jest.fn(),
|
||||
};
|
||||
|
||||
const mockBillingService = {
|
||||
isBillingEnabled: jest.fn(),
|
||||
canBillMeteredProduct: jest.fn(),
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
@ -63,6 +70,10 @@ describe('WorkflowExecutorWorkspaceService', () => {
|
||||
provide: WorkflowRunWorkspaceService,
|
||||
useValue: mockWorkflowRunWorkspaceService,
|
||||
},
|
||||
{
|
||||
provide: BillingService,
|
||||
useValue: mockBillingService,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
@ -376,6 +387,35 @@ describe('WorkflowExecutorWorkspaceService', () => {
|
||||
});
|
||||
expect(result).toEqual(errorOutput);
|
||||
});
|
||||
|
||||
it('should stop when billing validation fails', async () => {
|
||||
mockBillingService.isBillingEnabled.mockReturnValueOnce(true);
|
||||
mockBillingService.canBillMeteredProduct.mockReturnValueOnce(false);
|
||||
|
||||
const result = await service.execute({
|
||||
workflowRunId: mockWorkflowRunId,
|
||||
currentStepIndex: 0,
|
||||
steps: mockSteps,
|
||||
context: mockContext,
|
||||
});
|
||||
|
||||
expect(workflowExecutorFactory.get).toHaveBeenCalledTimes(1);
|
||||
expect(
|
||||
workflowRunWorkspaceService.saveWorkflowRunState,
|
||||
).toHaveBeenCalledWith({
|
||||
workflowRunId: mockWorkflowRunId,
|
||||
stepOutput: {
|
||||
id: 'step-1',
|
||||
output: {
|
||||
error: BILLING_WORKFLOW_EXECUTION_ERROR_MESSAGE,
|
||||
},
|
||||
},
|
||||
context: mockContext,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
error: BILLING_WORKFLOW_EXECUTION_ERROR_MESSAGE,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('sendWorkflowNodeRunEvent', () => {
|
||||
|
||||
@ -3,7 +3,10 @@ import { Injectable } from '@nestjs/common';
|
||||
import { WorkflowExecutor } from 'src/modules/workflow/workflow-executor/interfaces/workflow-executor.interface';
|
||||
|
||||
import { BILLING_FEATURE_USED } from 'src/engine/core-modules/billing/constants/billing-feature-used.constant';
|
||||
import { BILLING_WORKFLOW_EXECUTION_ERROR_MESSAGE } from 'src/engine/core-modules/billing/constants/billing-workflow-execution-error-message.constant';
|
||||
import { BillingMeterEventName } from 'src/engine/core-modules/billing/enums/billing-meter-event-names';
|
||||
import { BillingProductKey } from 'src/engine/core-modules/billing/enums/billing-product-key.enum';
|
||||
import { BillingService } from 'src/engine/core-modules/billing/services/billing.service';
|
||||
import { BillingUsageEvent } from 'src/engine/core-modules/billing/types/billing-usage-event.type';
|
||||
import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory';
|
||||
import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter';
|
||||
@ -31,6 +34,7 @@ export class WorkflowExecutorWorkspaceService implements WorkflowExecutor {
|
||||
private readonly workspaceEventEmitter: WorkspaceEventEmitter,
|
||||
private readonly scopedWorkspaceContextFactory: ScopedWorkspaceContextFactory,
|
||||
private readonly workflowRunWorkspaceService: WorkflowRunWorkspaceService,
|
||||
private readonly billingService: BillingService,
|
||||
) {}
|
||||
|
||||
async execute({
|
||||
@ -54,6 +58,26 @@ export class WorkflowExecutorWorkspaceService implements WorkflowExecutor {
|
||||
|
||||
let actionOutput: WorkflowExecutorOutput;
|
||||
|
||||
if (
|
||||
this.billingService.isBillingEnabled() &&
|
||||
!(await this.canBillWorkflowNodeExecution())
|
||||
) {
|
||||
const billingOutput = {
|
||||
error: BILLING_WORKFLOW_EXECUTION_ERROR_MESSAGE,
|
||||
};
|
||||
|
||||
await this.workflowRunWorkspaceService.saveWorkflowRunState({
|
||||
workflowRunId,
|
||||
stepOutput: {
|
||||
id: step.id,
|
||||
output: billingOutput,
|
||||
},
|
||||
context,
|
||||
});
|
||||
|
||||
return billingOutput;
|
||||
}
|
||||
|
||||
try {
|
||||
actionOutput = await workflowExecutor.execute({
|
||||
currentStepIndex,
|
||||
@ -159,4 +183,14 @@ export class WorkflowExecutorWorkspaceService implements WorkflowExecutor {
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
|
||||
private async canBillWorkflowNodeExecution() {
|
||||
const workspaceId =
|
||||
this.scopedWorkspaceContextFactory.create().workspaceId ?? '';
|
||||
|
||||
return this.billingService.canBillMeteredProduct(
|
||||
workspaceId,
|
||||
BillingProductKey.WORKFLOW_NODE_EXECUTION,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user