bugfix: escape destroyed objects on workers (#9719)
# This PR - Fixes #9358 @FelixMalfait please check this workaround --------- Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
@ -1,17 +1,21 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { OnDatabaseBatchEvent } from 'src/engine/api/graphql/graphql-query-runner/decorators/on-database-batch-event.decorator';
|
||||
import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action';
|
||||
import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event';
|
||||
import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event';
|
||||
import { ObjectRecordDestroyEvent } from 'src/engine/core-modules/event-emitter/types/object-record-destroy.event';
|
||||
import { ObjectRecordEvent } from 'src/engine/core-modules/event-emitter/types/object-record-event.event';
|
||||
import { ObjectRecordNonDestructiveEvent } from 'src/engine/core-modules/event-emitter/types/object-record-non-destructive-event';
|
||||
import { ObjectRecordRestoreEvent } from 'src/engine/core-modules/event-emitter/types/object-record-restore.event';
|
||||
import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event';
|
||||
import { ObjectRecordBaseEvent } from 'src/engine/core-modules/event-emitter/types/object-record.base.event';
|
||||
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
|
||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
|
||||
import { WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/types/workspace-event.type';
|
||||
import { CreateAuditLogFromInternalEvent } from 'src/modules/timeline/jobs/create-audit-log-from-internal-event';
|
||||
import { UpsertTimelineActivityFromInternalEvent } from 'src/modules/timeline/jobs/upsert-timeline-activity-from-internal-event.job';
|
||||
import { OnDatabaseBatchEvent } from 'src/engine/api/graphql/graphql-query-runner/decorators/on-database-batch-event.decorator';
|
||||
import { CallWebhookJobsJob } from 'src/modules/webhook/jobs/call-webhook-jobs.job';
|
||||
import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action';
|
||||
|
||||
@Injectable()
|
||||
export class EntityEventsToDbListener {
|
||||
@ -24,47 +28,66 @@ export class EntityEventsToDbListener {
|
||||
|
||||
@OnDatabaseBatchEvent('*', DatabaseEventAction.CREATED)
|
||||
async handleCreate(batchEvent: WorkspaceEventBatch<ObjectRecordCreateEvent>) {
|
||||
return this.handle(batchEvent);
|
||||
return this.handleEvent(batchEvent, DatabaseEventAction.CREATED);
|
||||
}
|
||||
|
||||
@OnDatabaseBatchEvent('*', DatabaseEventAction.UPDATED)
|
||||
async handleUpdate(batchEvent: WorkspaceEventBatch<ObjectRecordUpdateEvent>) {
|
||||
return this.handle(batchEvent);
|
||||
return this.handleEvent(batchEvent, DatabaseEventAction.UPDATED);
|
||||
}
|
||||
|
||||
@OnDatabaseBatchEvent('*', DatabaseEventAction.DELETED)
|
||||
async handleDelete(batchEvent: WorkspaceEventBatch<ObjectRecordUpdateEvent>) {
|
||||
return this.handle(batchEvent);
|
||||
async handleDelete(batchEvent: WorkspaceEventBatch<ObjectRecordDeleteEvent>) {
|
||||
return this.handleEvent(batchEvent, DatabaseEventAction.DELETED);
|
||||
}
|
||||
|
||||
@OnDatabaseBatchEvent('*', DatabaseEventAction.RESTORED)
|
||||
async handleRestore(
|
||||
batchEvent: WorkspaceEventBatch<ObjectRecordRestoreEvent>,
|
||||
) {
|
||||
return this.handleEvent(batchEvent, DatabaseEventAction.RESTORED);
|
||||
}
|
||||
|
||||
@OnDatabaseBatchEvent('*', DatabaseEventAction.DESTROYED)
|
||||
async handleDestroy(
|
||||
batchEvent: WorkspaceEventBatch<ObjectRecordUpdateEvent>,
|
||||
batchEvent: WorkspaceEventBatch<ObjectRecordDestroyEvent>,
|
||||
) {
|
||||
return this.handle(batchEvent);
|
||||
return this.handleEvent(batchEvent, DatabaseEventAction.DESTROYED);
|
||||
}
|
||||
|
||||
private async handle(batchEvent: WorkspaceEventBatch<ObjectRecordBaseEvent>) {
|
||||
private async handleEvent<T extends ObjectRecordEvent>(
|
||||
batchEvent: WorkspaceEventBatch<T>,
|
||||
action: DatabaseEventAction,
|
||||
) {
|
||||
const filteredEvents = batchEvent.events.filter(
|
||||
(event) => event.objectMetadata?.isAuditLogged,
|
||||
);
|
||||
|
||||
await this.entityEventsToDbQueueService.add<
|
||||
WorkspaceEventBatch<ObjectRecordBaseEvent>
|
||||
>(CreateAuditLogFromInternalEvent.name, {
|
||||
...batchEvent,
|
||||
events: filteredEvents,
|
||||
});
|
||||
|
||||
await this.entityEventsToDbQueueService.add<
|
||||
WorkspaceEventBatch<ObjectRecordBaseEvent>
|
||||
>(UpsertTimelineActivityFromInternalEvent.name, {
|
||||
...batchEvent,
|
||||
events: filteredEvents,
|
||||
});
|
||||
|
||||
await this.webhookQueueService.add<
|
||||
WorkspaceEventBatch<ObjectRecordBaseEvent>
|
||||
>(CallWebhookJobsJob.name, batchEvent, { retryLimit: 3 });
|
||||
await Promise.all([
|
||||
this.webhookQueueService.add<WorkspaceEventBatch<T>>(
|
||||
CallWebhookJobsJob.name,
|
||||
batchEvent,
|
||||
{
|
||||
retryLimit: 3,
|
||||
},
|
||||
),
|
||||
this.entityEventsToDbQueueService.add<WorkspaceEventBatch<T>>(
|
||||
CreateAuditLogFromInternalEvent.name,
|
||||
{
|
||||
...batchEvent,
|
||||
events: filteredEvents,
|
||||
},
|
||||
),
|
||||
...(action !== DatabaseEventAction.DESTROYED
|
||||
? [
|
||||
this.entityEventsToDbQueueService.add<
|
||||
WorkspaceEventBatch<ObjectRecordNonDestructiveEvent>
|
||||
>(UpsertTimelineActivityFromInternalEvent.name, {
|
||||
...batchEvent,
|
||||
events: filteredEvents,
|
||||
}),
|
||||
]
|
||||
: []),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ import { MicrosoftAPIsService } from 'src/engine/core-modules/auth/services/micr
|
||||
// import { OAuthService } from 'src/engine/core-modules/auth/services/oauth.service';
|
||||
import { ResetPasswordService } from 'src/engine/core-modules/auth/services/reset-password.service';
|
||||
import { SignInUpService } from 'src/engine/core-modules/auth/services/sign-in-up.service';
|
||||
import { SocialSsoService } from 'src/engine/core-modules/auth/services/social-sso.service';
|
||||
import { SamlAuthStrategy } from 'src/engine/core-modules/auth/strategies/saml.auth.strategy';
|
||||
import { AccessTokenService } from 'src/engine/core-modules/auth/token/services/access-token.service';
|
||||
import { LoginTokenService } from 'src/engine/core-modules/auth/token/services/login-token.service';
|
||||
@ -43,7 +44,6 @@ import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-s
|
||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||
import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module';
|
||||
import { ConnectedAccountModule } from 'src/modules/connected-account/connected-account.module';
|
||||
import { SocialSsoService } from 'src/engine/core-modules/auth/services/social-sso.service';
|
||||
|
||||
import { AuthResolver } from './auth.resolver';
|
||||
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event';
|
||||
import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event';
|
||||
import { ObjectRecordDestroyEvent } from 'src/engine/core-modules/event-emitter/types/object-record-destroy.event';
|
||||
import { ObjectRecordRestoreEvent } from 'src/engine/core-modules/event-emitter/types/object-record-restore.event';
|
||||
import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event';
|
||||
|
||||
export type ObjectRecordEvent<T = object> =
|
||||
| ObjectRecordUpdateEvent<T>
|
||||
| ObjectRecordDeleteEvent<T>
|
||||
| ObjectRecordCreateEvent<T>
|
||||
| ObjectRecordDestroyEvent<T>
|
||||
| ObjectRecordRestoreEvent<T>;
|
||||
@ -0,0 +1,10 @@
|
||||
import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event';
|
||||
import { ObjectRecordDeleteEvent } from 'src/engine/core-modules/event-emitter/types/object-record-delete.event';
|
||||
import { ObjectRecordRestoreEvent } from 'src/engine/core-modules/event-emitter/types/object-record-restore.event';
|
||||
import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-update.event';
|
||||
|
||||
export type ObjectRecordNonDestructiveEvent =
|
||||
| ObjectRecordCreateEvent
|
||||
| ObjectRecordUpdateEvent
|
||||
| ObjectRecordDeleteEvent
|
||||
| ObjectRecordRestoreEvent;
|
||||
@ -1,9 +1,9 @@
|
||||
import { ObjectRecordBaseEvent } from 'src/engine/core-modules/event-emitter/types/object-record.base.event';
|
||||
import { ObjectRecordCreateEvent } from 'src/engine/core-modules/event-emitter/types/object-record-create.event';
|
||||
|
||||
export class ObjectRecordRestoreEvent<
|
||||
T = object,
|
||||
> extends ObjectRecordBaseEvent<T> {
|
||||
> extends ObjectRecordCreateEvent<T> {
|
||||
properties: {
|
||||
before: T;
|
||||
after: T;
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { ObjectRecordBaseEvent } from 'src/engine/core-modules/event-emitter/types/object-record.base.event';
|
||||
import { ObjectRecordDiff } from 'src/engine/core-modules/event-emitter/types/object-record-diff';
|
||||
import { ObjectRecordBaseEvent } from 'src/engine/core-modules/event-emitter/types/object-record.base.event';
|
||||
|
||||
export class ObjectRecordUpdateEvent<
|
||||
T = object,
|
||||
> extends ObjectRecordBaseEvent<T> {
|
||||
properties: {
|
||||
updatedFields?: string[];
|
||||
diff?: Partial<ObjectRecordDiff<T>>;
|
||||
before: T;
|
||||
after: T;
|
||||
diff?: Partial<ObjectRecordDiff<T>>;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user