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,27 +0,0 @@
import gql from 'graphql-tag';
import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { type CreateCronTriggerInput } from 'src/engine/metadata-modules/cron-trigger/dtos/create-cron-trigger.input';
export type CreateOneCronTriggerFactoryInput = CreateCronTriggerInput;
const DEFAULT_CRON_TRIGGER_GQL_FIELDS = `
id
settings
`;
export const createOneCronTriggerQueryFactory = ({
input,
gqlFields = DEFAULT_CRON_TRIGGER_GQL_FIELDS,
}: PerformMetadataQueryParams<CreateOneCronTriggerFactoryInput>) => ({
query: gql`
mutation CreateOneCronTrigger($input: CreateCronTriggerInput!) {
createOneCronTrigger(input: $input) {
${gqlFields}
}
}
`,
variables: {
input,
},
});
@@ -1,43 +0,0 @@
import {
type CreateOneCronTriggerFactoryInput,
createOneCronTriggerQueryFactory,
} from 'test/integration/metadata/suites/serverless-function/utils/create-one-cron-trigger-query-factory.util';
import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
import { type CommonResponseBody } from 'test/integration/metadata/types/common-response-body.type';
import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { warnIfErrorButNotExpectedToFail } from 'test/integration/metadata/utils/warn-if-error-but-not-expected-to-fail.util';
import { warnIfNoErrorButExpectedToFail } from 'test/integration/metadata/utils/warn-if-no-error-but-expected-to-fail.util';
import { type CronTriggerDTO } from 'src/engine/metadata-modules/cron-trigger/dtos/cron-trigger.dto';
export const createOneCronTrigger = async ({
input,
gqlFields,
expectToFail = false,
token,
}: PerformMetadataQueryParams<CreateOneCronTriggerFactoryInput>): CommonResponseBody<{
createOneCronTrigger: CronTriggerDTO;
}> => {
const graphqlOperation = createOneCronTriggerQueryFactory({
input,
gqlFields,
});
const response = await makeMetadataAPIRequest(graphqlOperation, token);
if (expectToFail === true) {
warnIfNoErrorButExpectedToFail({
response,
errorMessage: 'Cron Trigger creation should have failed but did not',
});
}
if (expectToFail === false) {
warnIfErrorButNotExpectedToFail({
response,
errorMessage: 'Cron Trigger creation has failed but should not',
});
}
return { data: response.body.data, errors: response.body.errors };
};
@@ -1,28 +0,0 @@
import gql from 'graphql-tag';
import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { type CreateDatabaseEventTriggerInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/create-database-event-trigger.input';
export type CreateOneDatabaseEventTriggerFactoryInput =
CreateDatabaseEventTriggerInput;
const DEFAULT_DATABASE_EVENT_TRIGGER_GQL_FIELDS = `
id
settings
`;
export const createOneDatabaseEventTriggerQueryFactory = ({
input,
gqlFields = DEFAULT_DATABASE_EVENT_TRIGGER_GQL_FIELDS,
}: PerformMetadataQueryParams<CreateOneDatabaseEventTriggerFactoryInput>) => ({
query: gql`
mutation CreateOneDatabaseEventTrigger($input: CreateDatabaseEventTriggerInput!) {
createOneDatabaseEventTrigger(input: $input) {
${gqlFields}
}
}
`,
variables: {
input,
},
});
@@ -1,44 +0,0 @@
import {
type CreateOneDatabaseEventTriggerFactoryInput,
createOneDatabaseEventTriggerQueryFactory,
} from 'test/integration/metadata/suites/serverless-function/utils/create-one-database-event-trigger-query-factory.util';
import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
import { type CommonResponseBody } from 'test/integration/metadata/types/common-response-body.type';
import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { warnIfErrorButNotExpectedToFail } from 'test/integration/metadata/utils/warn-if-error-but-not-expected-to-fail.util';
import { warnIfNoErrorButExpectedToFail } from 'test/integration/metadata/utils/warn-if-no-error-but-expected-to-fail.util';
import { type DatabaseEventTriggerDTO } from 'src/engine/metadata-modules/database-event-trigger/dtos/database-event-trigger.dto';
export const createOneDatabaseEventTrigger = async ({
input,
gqlFields,
expectToFail = false,
token,
}: PerformMetadataQueryParams<CreateOneDatabaseEventTriggerFactoryInput>): CommonResponseBody<{
createOneDatabaseEventTrigger: DatabaseEventTriggerDTO;
}> => {
const graphqlOperation = createOneDatabaseEventTriggerQueryFactory({
input,
gqlFields,
});
const response = await makeMetadataAPIRequest(graphqlOperation, token);
if (expectToFail === true) {
warnIfNoErrorButExpectedToFail({
response,
errorMessage:
'Database Event Trigger creation should have failed but did not',
});
}
if (expectToFail === false) {
warnIfErrorButNotExpectedToFail({
response,
errorMessage: 'Database Event Trigger creation has failed but should not',
});
}
return { data: response.body.data, errors: response.body.errors };
};
@@ -1,29 +0,0 @@
import gql from 'graphql-tag';
import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { type CreateRouteTriggerInput } from 'src/engine/metadata-modules/route-trigger/dtos/create-route-trigger.input';
export type CreateOneRouteTriggerFactoryInput = CreateRouteTriggerInput;
const DEFAULT_ROUTE_TRIGGER_GQL_FIELDS = `
id
path
isAuthRequired
httpMethod
`;
export const createOneRouteTriggerQueryFactory = ({
input,
gqlFields = DEFAULT_ROUTE_TRIGGER_GQL_FIELDS,
}: PerformMetadataQueryParams<CreateOneRouteTriggerFactoryInput>) => ({
query: gql`
mutation CreateOneRouteTrigger($input: CreateRouteTriggerInput!) {
createOneRouteTrigger(input: $input) {
${gqlFields}
}
}
`,
variables: {
input,
},
});
@@ -1,43 +0,0 @@
import {
type CreateOneRouteTriggerFactoryInput,
createOneRouteTriggerQueryFactory,
} from 'test/integration/metadata/suites/serverless-function/utils/create-one-route-trigger-query-factory.util';
import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
import { type CommonResponseBody } from 'test/integration/metadata/types/common-response-body.type';
import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { warnIfErrorButNotExpectedToFail } from 'test/integration/metadata/utils/warn-if-error-but-not-expected-to-fail.util';
import { warnIfNoErrorButExpectedToFail } from 'test/integration/metadata/utils/warn-if-no-error-but-expected-to-fail.util';
import { type RouteTriggerDTO } from 'src/engine/metadata-modules/route-trigger/dtos/route-trigger.dto';
export const createOneRouteTrigger = async ({
input,
gqlFields,
expectToFail = false,
token,
}: PerformMetadataQueryParams<CreateOneRouteTriggerFactoryInput>): CommonResponseBody<{
createOneRouteTrigger: RouteTriggerDTO;
}> => {
const graphqlOperation = createOneRouteTriggerQueryFactory({
input,
gqlFields,
});
const response = await makeMetadataAPIRequest(graphqlOperation, token);
if (expectToFail === true) {
warnIfNoErrorButExpectedToFail({
response,
errorMessage: 'Route Trigger creation should have failed but did not',
});
}
if (expectToFail === false) {
warnIfErrorButNotExpectedToFail({
response,
errorMessage: 'Route Trigger creation has failed but should not',
});
}
return { data: response.body.data, errors: response.body.errors };
};