Rename serverlessFunction to logicFunction (#17494)
## Summary Rename "Serverless Function" to "Logic Function" across the codebase for clearer naming. ### Environment Variable Changes | Old | New | |-----|-----| | `SERVERLESS_TYPE` | `LOGIC_FUNCTION_TYPE` | | `SERVERLESS_LAMBDA_REGION` | `LOGIC_FUNCTION_LAMBDA_REGION` | | `SERVERLESS_LAMBDA_ROLE` | `LOGIC_FUNCTION_LAMBDA_ROLE` | | `SERVERLESS_LAMBDA_SUBHOSTING_URL` | `LOGIC_FUNCTION_LAMBDA_SUBHOSTING_URL` | | `SERVERLESS_LAMBDA_ACCESS_KEY_ID` | `LOGIC_FUNCTION_LAMBDA_ACCESS_KEY_ID` | | `SERVERLESS_LAMBDA_SECRET_ACCESS_KEY` | `LOGIC_FUNCTION_LAMBDA_SECRET_ACCESS_KEY` | ### Breaking Changes - Environment variables must be updated in production deployments - Database migration renames `serverlessFunction` → `logicFunction` tables
This commit is contained in:
+15
@@ -0,0 +1,15 @@
|
||||
import { ArgsType, Field } from '@nestjs/graphql';
|
||||
|
||||
import { IsString } from 'class-validator';
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
import { PackageJson } from 'twenty-shared/application';
|
||||
|
||||
@ArgsType()
|
||||
export class CreateLogicFunctionLayerInput {
|
||||
@Field(() => GraphQLJSON, { nullable: false })
|
||||
packageJson: PackageJson;
|
||||
|
||||
@IsString()
|
||||
@Field(() => String, { nullable: false })
|
||||
yarnLock: string;
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { Field, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import { IsDateString } from 'class-validator';
|
||||
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
|
||||
@ObjectType('LogicFunctionLayer')
|
||||
export class LogicFunctionLayerDTO {
|
||||
@IDField(() => UUIDScalarType)
|
||||
id: string;
|
||||
|
||||
@IDField(() => UUIDScalarType, { nullable: true })
|
||||
applicationId?: string;
|
||||
|
||||
@IsDateString()
|
||||
@Field()
|
||||
createdAt: Date;
|
||||
|
||||
@IsDateString()
|
||||
@Field()
|
||||
updatedAt: Date;
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
import { PackageJson } from 'twenty-shared/application';
|
||||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
OneToMany,
|
||||
PrimaryGeneratedColumn,
|
||||
Relation,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
import { LogicFunctionEntity } from 'src/engine/metadata-modules/logic-function/logic-function.entity';
|
||||
import { WorkspaceRelatedEntity } from 'src/engine/workspace-manager/types/workspace-related-entity';
|
||||
|
||||
@Entity('logicFunctionLayer')
|
||||
export class LogicFunctionLayerEntity extends WorkspaceRelatedEntity {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column({ type: 'jsonb', nullable: false })
|
||||
packageJson: PackageJson;
|
||||
|
||||
@Column({ type: 'text', nullable: false })
|
||||
yarnLock: string;
|
||||
|
||||
@Column({ type: 'text', nullable: false })
|
||||
checksum: string;
|
||||
|
||||
@OneToMany(
|
||||
() => LogicFunctionEntity,
|
||||
(logicFunction) => logicFunction.logicFunctionLayer,
|
||||
{
|
||||
onDelete: 'RESTRICT',
|
||||
},
|
||||
)
|
||||
logicFunctions: Relation<LogicFunctionEntity[]>;
|
||||
|
||||
@CreateDateColumn({ type: 'timestamptz' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ type: 'timestamptz' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { LogicFunctionLayerEntity } from 'src/engine/metadata-modules/logic-function-layer/logic-function-layer.entity';
|
||||
import { LogicFunctionLayerResolver } from 'src/engine/metadata-modules/logic-function-layer/logic-function-layer.resolver';
|
||||
import { LogicFunctionLayerService } from 'src/engine/metadata-modules/logic-function-layer/logic-function-layer.service';
|
||||
import { WorkspaceLogicFunctionLayerMapCacheService } from 'src/engine/metadata-modules/logic-function-layer/services/workspace-logic-function-layer-map-cache.service';
|
||||
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
PermissionsModule,
|
||||
TypeOrmModule.forFeature([LogicFunctionLayerEntity]),
|
||||
WorkspaceCacheModule,
|
||||
],
|
||||
providers: [
|
||||
LogicFunctionLayerService,
|
||||
LogicFunctionLayerResolver,
|
||||
WorkspaceLogicFunctionLayerMapCacheService,
|
||||
],
|
||||
exports: [
|
||||
LogicFunctionLayerService,
|
||||
WorkspaceLogicFunctionLayerMapCacheService,
|
||||
],
|
||||
})
|
||||
export class LogicFunctionLayerModule {}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import { UseGuards } from '@nestjs/common';
|
||||
import { Args, Mutation, Resolver } from '@nestjs/graphql';
|
||||
|
||||
import { PermissionFlagType } from 'twenty-shared/constants';
|
||||
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { SettingsPermissionGuard } from 'src/engine/guards/settings-permission.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { CreateLogicFunctionLayerInput } from 'src/engine/metadata-modules/logic-function-layer/dtos/create-logic-function-layer.input';
|
||||
import { LogicFunctionLayerDTO } from 'src/engine/metadata-modules/logic-function-layer/dtos/logic-function-layer.dto';
|
||||
import { LogicFunctionLayerService } from 'src/engine/metadata-modules/logic-function-layer/logic-function-layer.service';
|
||||
|
||||
@UseGuards(WorkspaceAuthGuard)
|
||||
@Resolver()
|
||||
export class LogicFunctionLayerResolver {
|
||||
constructor(
|
||||
private readonly logicFunctionLayerService: LogicFunctionLayerService,
|
||||
) {}
|
||||
|
||||
@Mutation(() => LogicFunctionLayerDTO)
|
||||
@UseGuards(SettingsPermissionGuard(PermissionFlagType.WORKFLOWS))
|
||||
async createOneLogicFunctionLayer(
|
||||
@Args()
|
||||
createLogicFunctionLayerInput: CreateLogicFunctionLayerInput,
|
||||
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
|
||||
) {
|
||||
return this.logicFunctionLayerService.create(
|
||||
createLogicFunctionLayerInput,
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import type { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
|
||||
|
||||
import { LogicFunctionLayerEntity } from 'src/engine/metadata-modules/logic-function-layer/logic-function-layer.entity';
|
||||
import { CreateLogicFunctionLayerInput } from 'src/engine/metadata-modules/logic-function-layer/dtos/create-logic-function-layer.input';
|
||||
import { getLastCommonLayerDependencies } from 'src/engine/core-modules/logic-function-executor/drivers/utils/get-last-common-layer-dependencies';
|
||||
import { logicFunctionCreateHash } from 'src/engine/metadata-modules/logic-function/utils/logic-function-create-hash.utils';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
|
||||
@Injectable()
|
||||
export class LogicFunctionLayerService {
|
||||
constructor(
|
||||
@InjectRepository(LogicFunctionLayerEntity)
|
||||
private readonly logicFunctionLayerRepository: Repository<LogicFunctionLayerEntity>,
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
) {}
|
||||
|
||||
async create(
|
||||
{ packageJson, yarnLock }: CreateLogicFunctionLayerInput,
|
||||
workspaceId: string,
|
||||
) {
|
||||
const checksum = logicFunctionCreateHash(yarnLock);
|
||||
|
||||
const logicFunctionLayer = this.logicFunctionLayerRepository.create({
|
||||
packageJson,
|
||||
yarnLock,
|
||||
checksum,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
const savedLayer =
|
||||
await this.logicFunctionLayerRepository.save(logicFunctionLayer);
|
||||
|
||||
await this.workspaceCacheService.invalidateAndRecompute(workspaceId, [
|
||||
'logicFunctionLayerMaps',
|
||||
]);
|
||||
|
||||
return savedLayer;
|
||||
}
|
||||
|
||||
async update(
|
||||
id: string,
|
||||
data: QueryDeepPartialEntity<LogicFunctionLayerEntity>,
|
||||
workspaceId: string,
|
||||
) {
|
||||
const checksum = data.yarnLock
|
||||
? logicFunctionCreateHash(data.yarnLock as string)
|
||||
: undefined;
|
||||
|
||||
const updateData = { ...data, ...(checksum && { checksum }) };
|
||||
|
||||
const result = await this.logicFunctionLayerRepository.update(
|
||||
id,
|
||||
updateData,
|
||||
);
|
||||
|
||||
await this.workspaceCacheService.invalidateAndRecompute(workspaceId, [
|
||||
'logicFunctionLayerMaps',
|
||||
]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async createCommonLayerIfNotExist(workspaceId: string) {
|
||||
const { packageJson, yarnLock } = await getLastCommonLayerDependencies();
|
||||
const checksum = logicFunctionCreateHash(yarnLock);
|
||||
const commonLayer = await this.logicFunctionLayerRepository.findOne({
|
||||
where: {
|
||||
checksum,
|
||||
workspaceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (isDefined(commonLayer)) {
|
||||
return commonLayer;
|
||||
}
|
||||
|
||||
return this.create({ packageJson, yarnLock }, workspaceId);
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
|
||||
|
||||
import { LogicFunctionLayerEntity } from 'src/engine/metadata-modules/logic-function-layer/logic-function-layer.entity';
|
||||
import { type LogicFunctionLayerCacheMaps } from 'src/engine/metadata-modules/logic-function-layer/types/logic-function-layer-cache-maps.type';
|
||||
import { fromLogicFunctionLayerEntityToFlatLogicFunctionLayer } from 'src/engine/metadata-modules/logic-function-layer/utils/from-logic-function-layer-entity-to-flat-logic-function-layer.util';
|
||||
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
|
||||
|
||||
@Injectable()
|
||||
@WorkspaceCache('logicFunctionLayerMaps')
|
||||
export class WorkspaceLogicFunctionLayerMapCacheService extends WorkspaceCacheProvider<LogicFunctionLayerCacheMaps> {
|
||||
constructor(
|
||||
@InjectRepository(LogicFunctionLayerEntity)
|
||||
private readonly logicFunctionLayerRepository: Repository<LogicFunctionLayerEntity>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async computeForCache(
|
||||
workspaceId: string,
|
||||
): Promise<LogicFunctionLayerCacheMaps> {
|
||||
const logicFunctionLayerEntities =
|
||||
await this.logicFunctionLayerRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
},
|
||||
});
|
||||
|
||||
const logicFunctionLayerMaps: LogicFunctionLayerCacheMaps = {
|
||||
byId: {},
|
||||
};
|
||||
|
||||
for (const entity of logicFunctionLayerEntities) {
|
||||
const flatLogicFunctionLayer =
|
||||
fromLogicFunctionLayerEntityToFlatLogicFunctionLayer(entity);
|
||||
|
||||
logicFunctionLayerMaps.byId[flatLogicFunctionLayer.id] =
|
||||
flatLogicFunctionLayer;
|
||||
}
|
||||
|
||||
return logicFunctionLayerMaps;
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import { type FlatEntityFrom } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type LogicFunctionLayerEntity } from 'src/engine/metadata-modules/logic-function-layer/logic-function-layer.entity';
|
||||
|
||||
export type FlatLogicFunctionLayer = FlatEntityFrom<LogicFunctionLayerEntity>;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { type FlatLogicFunctionLayer } from 'src/engine/metadata-modules/logic-function-layer/types/flat-logic-function-layer.type';
|
||||
|
||||
export type LogicFunctionLayerCacheMaps = {
|
||||
byId: Partial<Record<string, FlatLogicFunctionLayer>>;
|
||||
};
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { type LogicFunctionLayerEntity } from 'src/engine/metadata-modules/logic-function-layer/logic-function-layer.entity';
|
||||
import { type FlatLogicFunctionLayer } from 'src/engine/metadata-modules/logic-function-layer/types/flat-logic-function-layer.type';
|
||||
|
||||
export const fromLogicFunctionLayerEntityToFlatLogicFunctionLayer = (
|
||||
entity: LogicFunctionLayerEntity,
|
||||
): FlatLogicFunctionLayer => ({
|
||||
id: entity.id,
|
||||
packageJson: entity.packageJson,
|
||||
yarnLock: entity.yarnLock,
|
||||
checksum: entity.checksum,
|
||||
workspaceId: entity.workspaceId,
|
||||
createdAt: entity.createdAt.toISOString(),
|
||||
updatedAt: entity.updatedAt.toISOString(),
|
||||
logicFunctionIds: entity.logicFunctions?.map((lf) => lf.id) ?? [],
|
||||
});
|
||||
Reference in New Issue
Block a user