App uninstall lambda, layers cleanup (#21749)
# Introduction On a logic function deletion also remove the driver entry On a app uninstall also remove the sdk layer ( keeps the dep one as it can be shared across several lambda ) | Resource | Scope | Before this PR | After | |---|---|---|---| | DB metadata (functions, objects, fields…) | per-app | deleted | deleted | | Source folder (`FileFolder.Source`) | per-function | deleted | deleted | | Built handler file (`FileFolder.BuiltLogicFunction`) | per-function | deleted | deleted | | **Lambda function** | per-function | **leaked** | **deleted** (driver `delete`) | | **SDK layer** `sdk-<wsId>-<appId>` (all versions) | per-app | **leaked** | **deleted** (driver `deleteApplicationResources` → `deleteSdkLayer`) | | Deps layer `deps-<checksum>` | shared across apps/workspaces | not deleted | **intentionally not deleted** (content-addressed, GC'd) | ## What I don't like about all that Right now there's some non reversible side effect inside the workspace migration transaction - If the transaction fails we're facing data loss - It also slows down everything I'm about to create a new PR that allow population post transaction commit side effect / cleanup to be run later <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/21749?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
+34
-4
@@ -1,4 +1,4 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { Inject, Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { type Manifest } from 'twenty-shared/application';
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
@@ -6,17 +6,19 @@ import { FileFolder } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { PackageJson } from 'type-fest';
|
||||
|
||||
import { ApplicationManifestMigrationService } from 'src/engine/core-modules/application/application-manifest/application-manifest-migration.service';
|
||||
import { buildFromToAllUniversalFlatEntityMaps } from 'src/engine/core-modules/application/application-manifest/utils/build-from-to-all-universal-flat-entity-maps.util';
|
||||
import { getApplicationSubAllFlatEntityMaps } from 'src/engine/core-modules/application/application-manifest/utils/get-application-sub-all-flat-entity-maps.util';
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import {
|
||||
ApplicationException,
|
||||
ApplicationExceptionCode,
|
||||
} from 'src/engine/core-modules/application/application.exception';
|
||||
import { ApplicationManifestMigrationService } from 'src/engine/core-modules/application/application-manifest/application-manifest-migration.service';
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { buildFromToAllUniversalFlatEntityMaps } from 'src/engine/core-modules/application/application-manifest/utils/build-from-to-all-universal-flat-entity-maps.util';
|
||||
import { getApplicationSubAllFlatEntityMaps } from 'src/engine/core-modules/application/application-manifest/utils/get-application-sub-all-flat-entity-maps.util';
|
||||
import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service';
|
||||
import { LOGIC_FUNCTION_DRIVER_FACTORY_TOKEN } from 'src/engine/core-modules/logic-function/logic-function-drivers/constants/logic-function-driver-factory.token';
|
||||
import { type LogicFunctionDriverFactory } from 'src/engine/core-modules/logic-function/logic-function-drivers/logic-function-driver.factory';
|
||||
import { createEmptyAllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-all-flat-entity-maps.constant';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
@@ -35,6 +37,8 @@ export class ApplicationSyncService {
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
private readonly fileStorageService: FileStorageService,
|
||||
@Inject(LOGIC_FUNCTION_DRIVER_FACTORY_TOKEN)
|
||||
private readonly logicFunctionDriverFactory: LogicFunctionDriverFactory,
|
||||
) {}
|
||||
|
||||
public async synchronizeFromManifest({
|
||||
@@ -247,6 +251,32 @@ export class ApplicationSyncService {
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.cleanupApplicationRuntimeResources({
|
||||
workspaceId,
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
return validateAndBuildResult.workspaceMigration;
|
||||
}
|
||||
|
||||
private async cleanupApplicationRuntimeResources({
|
||||
workspaceId,
|
||||
applicationUniversalIdentifier,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
applicationUniversalIdentifier: string;
|
||||
}): Promise<void> {
|
||||
try {
|
||||
const driver = this.logicFunctionDriverFactory.getCurrentDriver();
|
||||
|
||||
await driver.deleteApplicationResources({
|
||||
workspaceId,
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
} catch (error) {
|
||||
this.logger.warn(
|
||||
`Failed to clean up runtime resources for application ${applicationUniversalIdentifier} in workspace ${workspaceId}: ${error instanceof Error ? error.message : String(error)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user