Skip to content

Commit 68b21d2

Browse files
authored
Add db event trigger and cron trigger to migration v2 (#14772)
## Context Add DB events triggers and Cron triggers to migration v2 builder/runner (and adding corresponding services/resolvers)
1 parent 123202d commit 68b21d2

File tree

82 files changed

+3340
-57
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+3340
-57
lines changed

packages/twenty-front/src/generated-metadata/graphql.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,16 @@ export type CreateApprovedAccessDomainInput = {
720720
email: Scalars['String'];
721721
};
722722

723+
export type CreateCronTriggerInput = {
724+
serverlessFunctionId: Scalars['String'];
725+
settings: Scalars['JSON'];
726+
};
727+
728+
export type CreateDatabaseEventTriggerInput = {
729+
serverlessFunctionId: Scalars['String'];
730+
settings: Scalars['JSON'];
731+
};
732+
723733
export type CreateDraftFromWorkflowVersionInput = {
724734
/** Workflow ID */
725735
workflowId: Scalars['UUID'];
@@ -926,6 +936,19 @@ export type CreateWorkflowVersionStepInput = {
926936
workflowVersionId: Scalars['UUID'];
927937
};
928938

939+
export type CronTrigger = {
940+
__typename?: 'CronTrigger';
941+
createdAt: Scalars['DateTime'];
942+
id: Scalars['UUID'];
943+
serverlessFunctionId: Scalars['String'];
944+
settings: Scalars['JSON'];
945+
updatedAt: Scalars['DateTime'];
946+
};
947+
948+
export type CronTriggerIdInput = {
949+
id: Scalars['String'];
950+
};
951+
929952
export type CursorPaging = {
930953
/** Paginate after opaque cursor */
931954
after?: InputMaybe<Scalars['ConnectionCursor']>;
@@ -946,6 +969,19 @@ export enum DatabaseEventAction {
946969
UPDATED = 'UPDATED'
947970
}
948971

972+
export type DatabaseEventTrigger = {
973+
__typename?: 'DatabaseEventTrigger';
974+
createdAt: Scalars['DateTime'];
975+
id: Scalars['UUID'];
976+
serverlessFunctionId: Scalars['String'];
977+
settings: Scalars['JSON'];
978+
updatedAt: Scalars['DateTime'];
979+
};
980+
981+
export type DatabaseEventTriggerIdInput = {
982+
id: Scalars['String'];
983+
};
984+
949985
export type DateFilter = {
950986
eq?: InputMaybe<Scalars['Date']>;
951987
gt?: InputMaybe<Scalars['Date']>;
@@ -1597,6 +1633,8 @@ export type Mutation = {
15971633
createObjectEvent: Analytics;
15981634
createOneAgent: Agent;
15991635
createOneAppToken: AppToken;
1636+
createOneCronTrigger: CronTrigger;
1637+
createOneDatabaseEventTrigger: DatabaseEventTrigger;
16001638
createOneField: Field;
16011639
createOneObject: Object;
16021640
createOneRemoteServer: RemoteServer;
@@ -1623,6 +1661,8 @@ export type Mutation = {
16231661
deleteEmailingDomain: Scalars['Boolean'];
16241662
deleteFile: File;
16251663
deleteOneAgent: Agent;
1664+
deleteOneCronTrigger: CronTrigger;
1665+
deleteOneDatabaseEventTrigger: DatabaseEventTrigger;
16261666
deleteOneField: Field;
16271667
deleteOneObject: Object;
16281668
deleteOneRemoteServer: RemoteServer;
@@ -1704,6 +1744,8 @@ export type Mutation = {
17041744
updateDatabaseConfigVariable: Scalars['Boolean'];
17051745
updateLabPublicFeatureFlag: FeatureFlagDto;
17061746
updateOneAgent: Agent;
1747+
updateOneCronTrigger: CronTrigger;
1748+
updateOneDatabaseEventTrigger: DatabaseEventTrigger;
17071749
updateOneField: Field;
17081750
updateOneObject: Object;
17091751
updateOneRemoteServer: RemoteServer;
@@ -1877,6 +1919,16 @@ export type MutationCreateOneAppTokenArgs = {
18771919
};
18781920

18791921

1922+
export type MutationCreateOneCronTriggerArgs = {
1923+
input: CreateCronTriggerInput;
1924+
};
1925+
1926+
1927+
export type MutationCreateOneDatabaseEventTriggerArgs = {
1928+
input: CreateDatabaseEventTriggerInput;
1929+
};
1930+
1931+
18801932
export type MutationCreateOneFieldArgs = {
18811933
input: CreateOneFieldMetadataInput;
18821934
};
@@ -2002,6 +2054,16 @@ export type MutationDeleteOneAgentArgs = {
20022054
};
20032055

20042056

2057+
export type MutationDeleteOneCronTriggerArgs = {
2058+
input: CronTriggerIdInput;
2059+
};
2060+
2061+
2062+
export type MutationDeleteOneDatabaseEventTriggerArgs = {
2063+
input: DatabaseEventTriggerIdInput;
2064+
};
2065+
2066+
20052067
export type MutationDeleteOneFieldArgs = {
20062068
input: DeleteOneFieldInput;
20072069
};
@@ -2398,6 +2460,16 @@ export type MutationUpdateOneAgentArgs = {
23982460
};
23992461

24002462

2463+
export type MutationUpdateOneCronTriggerArgs = {
2464+
input: UpdateCronTriggerInput;
2465+
};
2466+
2467+
2468+
export type MutationUpdateOneDatabaseEventTriggerArgs = {
2469+
input: UpdateDatabaseEventTriggerInput;
2470+
};
2471+
2472+
24012473
export type MutationUpdateOneFieldArgs = {
24022474
input: UpdateOneFieldMetadataInput;
24032475
};
@@ -2873,10 +2945,14 @@ export type Query = {
28732945
findAgentHandoffs: Array<AgentHandoffDto>;
28742946
findDistantTablesWithStatus: Array<RemoteTable>;
28752947
findManyAgents: Array<Agent>;
2948+
findManyCronTriggers: Array<CronTrigger>;
2949+
findManyDatabaseEventTriggers: Array<DatabaseEventTrigger>;
28762950
findManyPublicDomains: Array<PublicDomain>;
28772951
findManyRemoteServersByType: Array<RemoteServer>;
28782952
findManyServerlessFunctions: Array<ServerlessFunction>;
28792953
findOneAgent: Agent;
2954+
findOneCronTrigger: CronTrigger;
2955+
findOneDatabaseEventTrigger: DatabaseEventTrigger;
28802956
findOneRemoteServerById: RemoteServer;
28812957
findOneServerlessFunction: ServerlessFunction;
28822958
findWorkspaceFromInviteHash: Workspace;
@@ -3007,6 +3083,16 @@ export type QueryFindOneAgentArgs = {
30073083
};
30083084

30093085

3086+
export type QueryFindOneCronTriggerArgs = {
3087+
input: CronTriggerIdInput;
3088+
};
3089+
3090+
3091+
export type QueryFindOneDatabaseEventTriggerArgs = {
3092+
input: DatabaseEventTriggerIdInput;
3093+
};
3094+
3095+
30103096
export type QueryFindOneRemoteServerByIdArgs = {
30113097
input: RemoteServerIdInput;
30123098
};
@@ -3712,6 +3798,16 @@ export type UpdateApiKeyDto = {
37123798
revokedAt?: InputMaybe<Scalars['String']>;
37133799
};
37143800

3801+
export type UpdateCronTriggerInput = {
3802+
id: Scalars['String'];
3803+
settings: Scalars['JSON'];
3804+
};
3805+
3806+
export type UpdateDatabaseEventTriggerInput = {
3807+
id: Scalars['String'];
3808+
settings: Scalars['JSON'];
3809+
};
3810+
37153811
export type UpdateFieldInput = {
37163812
defaultValue?: InputMaybe<Scalars['JSON']>;
37173813
description?: InputMaybe<Scalars['String']>;

packages/twenty-front/src/generated/graphql.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,15 @@ export type CreateWorkflowVersionStepInput = {
890890
workflowVersionId: Scalars['UUID'];
891891
};
892892

893+
export type CronTrigger = {
894+
__typename?: 'CronTrigger';
895+
createdAt: Scalars['DateTime'];
896+
id: Scalars['UUID'];
897+
serverlessFunctionId: Scalars['String'];
898+
settings: Scalars['JSON'];
899+
updatedAt: Scalars['DateTime'];
900+
};
901+
893902
export type CursorPaging = {
894903
/** Paginate after opaque cursor */
895904
after?: InputMaybe<Scalars['ConnectionCursor']>;
@@ -910,6 +919,15 @@ export enum DatabaseEventAction {
910919
UPDATED = 'UPDATED'
911920
}
912921

922+
export type DatabaseEventTrigger = {
923+
__typename?: 'DatabaseEventTrigger';
924+
createdAt: Scalars['DateTime'];
925+
id: Scalars['UUID'];
926+
serverlessFunctionId: Scalars['String'];
927+
settings: Scalars['JSON'];
928+
updatedAt: Scalars['DateTime'];
929+
};
930+
913931
export type DateFilter = {
914932
eq?: InputMaybe<Scalars['Date']>;
915933
gt?: InputMaybe<Scalars['Date']>;

packages/twenty-server/src/database/commands/cron-register-all.command.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import { Logger } from '@nestjs/common';
33
import { Command, CommandRunner } from 'nest-commander';
44

55
import { CleanupOrphanedFilesCronCommand } from 'src/engine/core-modules/file/crons/commands/cleanup-orphaned-files.cron.command';
6-
import { CronTriggerCronCommand } from 'src/engine/metadata-modules/trigger/crons/commands/cron-trigger.cron.command';
6+
import { CheckPublicDomainsValidRecordsCronCommand } from 'src/engine/core-modules/public-domain/crons/commands/check-public-domains-valid-records.cron.command';
7+
import { CheckCustomDomainValidRecordsCronCommand } from 'src/engine/core-modules/workspace/crons/commands/check-custom-domain-valid-records.cron.command';
8+
import { CronTriggerCronCommand } from 'src/engine/metadata-modules/cron-trigger/crons/commands/cron-trigger.cron.command';
79
import { CleanOnboardingWorkspacesCronCommand } from 'src/engine/workspace-manager/workspace-cleaner/commands/clean-onboarding-workspaces.cron.command';
810
import { CleanSuspendedWorkspacesCronCommand } from 'src/engine/workspace-manager/workspace-cleaner/commands/clean-suspended-workspaces.cron.command';
911
import { CalendarEventListFetchCronCommand } from 'src/modules/calendar/calendar-event-import-manager/crons/commands/calendar-event-list-fetch.cron.command';
@@ -16,8 +18,6 @@ import { WorkflowCleanWorkflowRunsCronCommand } from 'src/modules/workflow/workf
1618
import { WorkflowHandleStaledRunsCronCommand } from 'src/modules/workflow/workflow-runner/workflow-run-queue/cron/command/workflow-handle-staled-runs.cron.command';
1719
import { WorkflowRunEnqueueCronCommand } from 'src/modules/workflow/workflow-runner/workflow-run-queue/cron/command/workflow-run-enqueue.cron.command';
1820
import { WorkflowCronTriggerCronCommand } from 'src/modules/workflow/workflow-trigger/automated-trigger/crons/commands/workflow-cron-trigger.cron.command';
19-
import { CheckCustomDomainValidRecordsCronCommand } from 'src/engine/core-modules/workspace/crons/commands/check-custom-domain-valid-records.cron.command';
20-
import { CheckPublicDomainsValidRecordsCronCommand } from 'src/engine/core-modules/public-domain/crons/commands/check-public-domains-valid-records.cron.command';
2121

2222
@Command({
2323
name: 'cron:register:all',

packages/twenty-server/src/database/commands/database-command.module.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
99
import { ApiKeyModule } from 'src/engine/core-modules/api-key/api-key.module';
1010
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
1111
import { FileModule } from 'src/engine/core-modules/file/file.module';
12+
import { PublicDomainModule } from 'src/engine/core-modules/public-domain/public-domain.module';
1213
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
14+
import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module';
15+
import { CronTriggerModule } from 'src/engine/metadata-modules/cron-trigger/cron-trigger.module';
1316
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
17+
import { DatabaseEventTriggerModule } from 'src/engine/metadata-modules/database-event-trigger/database-event-trigger.module';
1418
import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module';
1519
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
16-
import { TriggerModule } from 'src/engine/metadata-modules/trigger/trigger.module';
1720
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
1821
import { DevSeederModule } from 'src/engine/workspace-manager/dev-seeder/dev-seeder.module';
1922
import { WorkspaceCleanerModule } from 'src/engine/workspace-manager/workspace-cleaner/workspace-cleaner.module';
@@ -22,8 +25,6 @@ import { CalendarEventImportManagerModule } from 'src/modules/calendar/calendar-
2225
import { MessagingImportManagerModule } from 'src/modules/messaging/message-import-manager/messaging-import-manager.module';
2326
import { WorkflowRunQueueModule } from 'src/modules/workflow/workflow-runner/workflow-run-queue/workflow-run-queue.module';
2427
import { AutomatedTriggerModule } from 'src/modules/workflow/workflow-trigger/automated-trigger/automated-trigger.module';
25-
import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module';
26-
import { PublicDomainModule } from 'src/engine/core-modules/public-domain/public-domain.module';
2728

2829
@Module({
2930
imports: [
@@ -46,7 +47,8 @@ import { PublicDomainModule } from 'src/engine/core-modules/public-domain/public
4647
WorkspaceCacheStorageModule,
4748
ApiKeyModule,
4849
FeatureFlagModule,
49-
TriggerModule,
50+
CronTriggerModule,
51+
DatabaseEventTriggerModule,
5052
WorkspaceCleanerModule,
5153
PublicDomainModule,
5254
],

packages/twenty-server/src/engine/api/graphql/workspace-query-runner/listeners/entity-events-to-db.listener.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@ import { type ObjectRecordEvent } from 'src/engine/core-modules/event-emitter/ty
1010
import { type ObjectRecordNonDestructiveEvent } from 'src/engine/core-modules/event-emitter/types/object-record-non-destructive-event';
1111
import { type ObjectRecordRestoreEvent } from 'src/engine/core-modules/event-emitter/types/object-record-restore.event';
1212
import { type ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event';
13+
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
14+
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
1315
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
1416
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
1517
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
16-
import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/types/workspace-event.type';
17-
import { UpsertTimelineActivityFromInternalEvent } from 'src/modules/timeline/jobs/upsert-timeline-activity-from-internal-event.job';
1818
import { CallWebhookJobsJob } from 'src/engine/core-modules/webhook/jobs/call-webhook-jobs.job';
1919
import { type ObjectRecordEventForWebhook } from 'src/engine/core-modules/webhook/types/object-record-event-for-webhook.type';
20-
import { CallDatabaseEventTriggerJobsJob } from 'src/engine/metadata-modules/trigger/jobs/call-database-event-trigger-jobs.job';
20+
import { CallDatabaseEventTriggerJobsJob } from 'src/engine/metadata-modules/database-event-trigger/jobs/call-database-event-trigger-jobs.job';
2121
import { SubscriptionsService } from 'src/engine/subscriptions/subscriptions.service';
22-
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
23-
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
22+
import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/types/workspace-event.type';
23+
import { UpsertTimelineActivityFromInternalEvent } from 'src/modules/timeline/jobs/upsert-timeline-activity-from-internal-event.job';
2424

2525
@Injectable()
2626
export class EntityEventsToDbListener {

packages/twenty-server/src/engine/core-modules/common/constant/all-flat-entity-maps-properties.constant.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ export const ALL_FLAT_ENTITY_MAPS_PROPERTIES = [
66
'flatViewMaps',
77
'flatIndexMaps',
88
'flatServerlessFunctionMaps',
9+
'flatDatabaseEventTriggerMaps',
10+
'flatCronTriggerMaps',
911
] as const satisfies (keyof AllFlatEntityMaps)[];

packages/twenty-server/src/engine/core-modules/common/constant/empty-all-flat-entity-maps.constant.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@ export const EMPTY_ALL_FLAT_ENTITY_MAPS = {
1010
flatViewFieldMaps: EMPTY_FLAT_ENTITY_MAPS,
1111
flatViewMaps: EMPTY_FLAT_ENTITY_MAPS,
1212
flatServerlessFunctionMaps: EMPTY_FLAT_ENTITY_MAPS,
13+
flatCronTriggerMaps: EMPTY_FLAT_ENTITY_MAPS,
14+
flatDatabaseEventTriggerMaps: EMPTY_FLAT_ENTITY_MAPS,
1315
} as const satisfies AllFlatEntityMaps;

packages/twenty-server/src/engine/core-modules/common/types/all-flat-entities-by-metadata-engine-name.type.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { type FlatViewField } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type';
22
import { type FlatView } from 'src/engine/core-modules/view/flat-view/types/flat-view.type';
3+
import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
4+
import { type FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/database-event-trigger/types/flat-database-event-trigger.type';
35
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
46
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
57
import { type FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type';
@@ -11,4 +13,6 @@ export type AllFlatEntitiesByMetadataEngineName = {
1113
viewField: FlatViewField;
1214
index: FlatIndexMetadata;
1315
serverlessFunction: FlatServerlessFunction;
16+
cronTrigger: FlatCronTrigger;
17+
databaseEventTrigger: FlatDatabaseEventTrigger;
1418
};

packages/twenty-server/src/engine/core-modules/message-queue/jobs.module.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,15 @@ import { EmailModule } from 'src/engine/core-modules/email/email.module';
1414
import { UserWorkspaceModule } from 'src/engine/core-modules/user-workspace/user-workspace.module';
1515
import { UserVarsModule } from 'src/engine/core-modules/user/user-vars/user-vars.module';
1616
import { UserModule } from 'src/engine/core-modules/user/user.module';
17+
import { WebhookJobModule } from 'src/engine/core-modules/webhook/jobs/webhook-job.module';
1718
import { HandleWorkspaceMemberDeletedJob } from 'src/engine/core-modules/workspace/handle-workspace-member-deleted.job';
1819
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
1920
import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module';
21+
import { CronTriggerModule } from 'src/engine/metadata-modules/cron-trigger/cron-trigger.module';
2022
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
23+
import { DatabaseEventTriggerModule } from 'src/engine/metadata-modules/database-event-trigger/database-event-trigger.module';
2124
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
25+
import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module';
2226
import { SubscriptionsModule } from 'src/engine/subscriptions/subscriptions.module';
2327
import { CleanOnboardingWorkspacesJob } from 'src/engine/workspace-manager/workspace-cleaner/crons/clean-onboarding-workspaces.job';
2428
import { CleanSuspendedWorkspacesJob } from 'src/engine/workspace-manager/workspace-cleaner/crons/clean-suspended-workspaces.job';
@@ -31,10 +35,7 @@ import { FavoriteModule } from 'src/modules/favorite/favorite.module';
3135
import { MessagingModule } from 'src/modules/messaging/messaging.module';
3236
import { TimelineJobModule } from 'src/modules/timeline/jobs/timeline-job.module';
3337
import { TimelineActivityModule } from 'src/modules/timeline/timeline-activity.module';
34-
import { WebhookJobModule } from 'src/engine/core-modules/webhook/jobs/webhook-job.module';
3538
import { WorkflowModule } from 'src/modules/workflow/workflow.module';
36-
import { TriggerModule } from 'src/engine/metadata-modules/trigger/trigger.module';
37-
import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module';
3839

3940
@Module({
4041
imports: [
@@ -62,7 +63,8 @@ import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless
6263
WorkspaceCleanerModule,
6364
SubscriptionsModule,
6465
AuditJobModule,
65-
TriggerModule,
66+
CronTriggerModule,
67+
DatabaseEventTriggerModule,
6668
ServerlessFunctionModule,
6769
],
6870
providers: [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
2+
3+
export const FLAT_CRON_TRIGGER_EDITABLE_PROPERTIES = [
4+
'settings',
5+
] as const satisfies (keyof FlatCronTrigger)[];

0 commit comments

Comments
 (0)