Migrate cron, databaseEventTrigger, httpRoute triggers to serverless functions (#17488)

## Summary

Migrates trigger entities (`CronTriggerEntity`,
`DatabaseEventTriggerEntity`, `RouteTriggerEntity`) into
`ServerlessFunctionEntity` by storing trigger settings as JSONB columns
directly on the serverless function. This simplifies the architecture
since these relationships were effectively one-to-one.

## Changes

### Schema Changes
- Added three new nullable JSONB columns to `ServerlessFunctionEntity`:
  - `cronTriggerSettings` - stores cron pattern
- `databaseEventTriggerSettings` - stores event name and updated fields
filter
- `httpRouteTriggerSettings` - stores path, HTTP method, auth
requirements, and forwarded headers

### Core Logic Updates
- `CronTriggerCronJob` - now queries `ServerlessFunctionEntity` directly
instead of `CronTriggerEntity`
- `CallDatabaseEventTriggerJobsJob` - now queries
`ServerlessFunctionEntity` directly
- `RouteTriggerService` - now queries `ServerlessFunctionEntity`
directly
- `ApplicationSyncService` - extracts trigger settings from manifest and
writes to serverless function
This commit is contained in:
Charles Bochet
2026-01-27 20:54:09 +01:00
committed by GitHub
parent e1f92bd951
commit a4499d21bb
110 changed files with 439 additions and 5193 deletions
@@ -1,7 +1,5 @@
import { type AllMetadataName } from 'twenty-shared/metadata';
import { FLAT_CRON_TRIGGER_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/cron-trigger/constants/flat-cron-trigger-editable-properties.constant';
import { FLAT_DATABASE_EVENT_TRIGGER_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/database-event-trigger/constants/flat-database-event-trigger-editable-properties.constant';
import { FLAT_AGENT_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-agent/constants/flat-agent-editable-properties.constant';
import { FLAT_COMMAND_MENU_ITEM_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-command-menu-item/constants/flat-command-menu-item-editable-properties.constant';
import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type';
@@ -22,7 +20,6 @@ import { FLAT_VIEW_FILTER_GROUP_EDITABLE_PROPERTIES } from 'src/engine/metadata-
import { FLAT_VIEW_FILTER_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-editable-properties.constant';
import { FLAT_VIEW_GROUP_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-group/constants/flat-view-group-editable-properties.constant';
import { FLAT_VIEW_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view/constants/flat-view-editable-properties.constant';
import { FLAT_ROUTE_TRIGGER_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/route-trigger/constants/flat-route-trigger-editable-properties.constant';
import { FLAT_SERVERLESS_FUNCTION_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/serverless-function/constants/flat-serverless-function-editable-properties.constant';
type OneFlatEntityConfiguration<T extends AllMetadataName> = {
@@ -88,15 +85,15 @@ export const ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY = {
propertiesToStringify: ['toolInputSchema', 'publishedVersions'],
},
cronTrigger: {
propertiesToCompare: [...FLAT_CRON_TRIGGER_EDITABLE_PROPERTIES],
propertiesToStringify: ['settings'],
propertiesToCompare: [],
propertiesToStringify: [],
},
databaseEventTrigger: {
propertiesToCompare: [...FLAT_DATABASE_EVENT_TRIGGER_EDITABLE_PROPERTIES],
propertiesToStringify: ['settings'],
propertiesToCompare: [],
propertiesToStringify: [],
},
routeTrigger: {
propertiesToCompare: [...FLAT_ROUTE_TRIGGER_EDITABLE_PROPERTIES],
propertiesToCompare: [],
propertiesToStringify: [],
},
viewFilter: {
@@ -3,8 +3,6 @@ import { type EntityTarget, type ObjectLiteral } from 'typeorm';
import { AgentEntity } from 'src/engine/metadata-modules/ai/ai-agent/entities/agent.entity';
import { CommandMenuItemEntity } from 'src/engine/metadata-modules/command-menu-item/entities/command-menu-item.entity';
import { CronTriggerEntity } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
import { DatabaseEventTriggerEntity } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { FrontComponentEntity } from 'src/engine/metadata-modules/front-component/entities/front-component.entity';
import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
@@ -16,7 +14,6 @@ import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout-
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { RouteTriggerEntity } from 'src/engine/metadata-modules/route-trigger/route-trigger.entity';
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity';
@@ -39,9 +36,9 @@ export const ALL_METADATA_ENTITY_BY_METADATA_NAME = {
view: ViewEntity,
index: IndexMetadataEntity,
pageLayoutTab: PageLayoutTabEntity,
routeTrigger: RouteTriggerEntity,
cronTrigger: CronTriggerEntity,
databaseEventTrigger: DatabaseEventTriggerEntity,
routeTrigger: ServerlessFunctionEntity,
cronTrigger: ServerlessFunctionEntity,
databaseEventTrigger: ServerlessFunctionEntity,
frontComponent: FrontComponentEntity,
fieldMetadata: FieldMetadataEntity,
pageLayout: PageLayoutEntity,
@@ -267,45 +267,29 @@ export const ALL_METADATA_RELATIONS = {
application: null,
serverlessFunctionLayer: null,
},
oneToMany: {
cronTriggers: { metadataName: 'cronTrigger' },
databaseEventTriggers: { metadataName: 'databaseEventTrigger' },
routeTriggers: { metadataName: 'routeTrigger' },
},
oneToMany: {},
},
cronTrigger: {
manyToOne: {
serverlessFunction: {
metadataName: 'serverlessFunction',
flatEntityForeignKeyAggregator: 'cronTriggerIds',
foreignKey: 'serverlessFunctionId',
},
workspace: null,
application: null,
serverlessFunctionLayer: null,
workspace: null,
},
oneToMany: {},
},
databaseEventTrigger: {
manyToOne: {
serverlessFunction: {
metadataName: 'serverlessFunction',
flatEntityForeignKeyAggregator: 'databaseEventTriggerIds',
foreignKey: 'serverlessFunctionId',
},
workspace: null,
application: null,
serverlessFunctionLayer: null,
workspace: null,
},
oneToMany: {},
},
routeTrigger: {
manyToOne: {
serverlessFunction: {
metadataName: 'serverlessFunction',
flatEntityForeignKeyAggregator: 'routeTriggerIds',
foreignKey: 'serverlessFunctionId',
},
workspace: null,
application: null,
serverlessFunctionLayer: null,
workspace: null,
},
oneToMany: {},
},