Skip to content

Commit

Permalink
restore 0.24 commands and move soft-delete-command to 0.30
Browse files Browse the repository at this point in the history
  • Loading branch information
Weiko committed Sep 12, 2024
1 parent 5a9b33a commit 7f7b000
Show file tree
Hide file tree
Showing 6 changed files with 372 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { DataSeedDemoWorkspaceCommand } from 'src/database/commands/data-seed-de
import { DataSeedDemoWorkspaceModule } from 'src/database/commands/data-seed-demo-workspace/data-seed-demo-workspace.module';
import { DataSeedWorkspaceCommand } from 'src/database/commands/data-seed-dev-workspace.command';
import { ConfirmationQuestion } from 'src/database/commands/questions/confirmation.question';
import { UpgradeTo0_24CommandModule } from 'src/database/commands/upgrade-version/0-24/0-24-upgrade-version.module';
import { UpgradeTo0_30CommandModule } from 'src/database/commands/upgrade-version/0-30/0-30-upgrade-version.module';
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity';
Expand Down Expand Up @@ -45,6 +46,7 @@ import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/worksp
FieldMetadataModule,
DataSeedDemoWorkspaceModule,
WorkspaceMetadataVersionModule,
UpgradeTo0_24CommandModule,
UpgradeTo0_30CommandModule,
],
providers: [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
import { Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';

import chalk from 'chalk';
import { Command, CommandRunner, Option } from 'nest-commander';
import { Any, Repository } from 'typeorm';

import {
Workspace,
WorkspaceActivationStatus,
} from 'src/engine/core-modules/workspace/workspace.entity';
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { MessageDirection } from 'src/modules/messaging/common/enums/message-direction.enum';
import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';

interface SetMessageDirectionCommandOptions {
workspaceId?: string;
}

const MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_BATCH_SIZE = 10;

@Command({
name: 'upgrade-0.24:set-message-direction',
description: 'Set message direction',
})
export class SetMessageDirectionCommand extends CommandRunner {
private readonly logger = new Logger(SetMessageDirectionCommand.name);
constructor(
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
@InjectRepository(Workspace, 'core')
private readonly workspaceRepository: Repository<Workspace>,
) {
super();
}

@Option({
flags: '-w, --workspace-id [workspace_id]',
description: 'workspace id. Command runs on all workspaces if not provided',
required: false,
})
parseWorkspaceId(value: string): string {
return value;
}

async run(
_passedParam: string[],
options: SetMessageDirectionCommandOptions,
): Promise<void> {
let activeWorkspaceIds: string[] = [];

if (options.workspaceId) {
activeWorkspaceIds = [options.workspaceId];
} else {
const activeWorkspaces = await this.workspaceRepository.find({
where: {
activationStatus: WorkspaceActivationStatus.ACTIVE,
...(options.workspaceId && { id: options.workspaceId }),
},
});

activeWorkspaceIds = activeWorkspaces.map((workspace) => workspace.id);
}

if (!activeWorkspaceIds.length) {
this.logger.log(chalk.yellow('No workspace found'));

return;
} else {
this.logger.log(
chalk.green(
`Running command on ${activeWorkspaceIds.length} workspaces`,
),
);
}

for (const workspaceId of activeWorkspaceIds) {
try {
const messageChannelMessageAssociationRepository =
await this.twentyORMGlobalManager.getRepositoryForWorkspace<MessageChannelMessageAssociationWorkspaceEntity>(
workspaceId,
'messageChannelMessageAssociation',
);

const workspaceDataSource =
await this.twentyORMGlobalManager.getDataSourceForWorkspace(
workspaceId,
);

await workspaceDataSource.transaction(async (transactionManager) => {
try {
const messageChannelMessageAssociationCount =
await messageChannelMessageAssociationRepository.count(
{},
transactionManager,
);

for (
let i = 0;
i < messageChannelMessageAssociationCount;
i += MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_BATCH_SIZE
) {
const messageChannelMessageAssociationsPage =
await messageChannelMessageAssociationRepository.find(
{
where: {
message: {
messageParticipants: {
role: 'from',
},
},
},
relations: {
message: {
messageParticipants: true,
},
messageChannel: {
connectedAccount: true,
},
},
take: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_BATCH_SIZE,
skip: i,
},
transactionManager,
);

const { incoming, outgoing } =
messageChannelMessageAssociationsPage.reduce(
(
acc: {
incoming: string[];
outgoing: string[];
},
messageChannelMessageAssociation,
) => {
const connectedAccountHandle =
messageChannelMessageAssociation?.messageChannel
?.connectedAccount?.handle;
const connectedAccountHandleAliases =
messageChannelMessageAssociation?.messageChannel
?.connectedAccount?.handleAliases;
const fromHandle =
messageChannelMessageAssociation?.message
?.messageParticipants?.[0]?.handle ?? '';

if (
connectedAccountHandle === fromHandle ||
connectedAccountHandleAliases?.includes(fromHandle)
) {
acc.outgoing.push(messageChannelMessageAssociation.id);
} else {
acc.incoming.push(messageChannelMessageAssociation.id);
}

return acc;
},
{ incoming: [], outgoing: [] },
);

await messageChannelMessageAssociationRepository.update(
{
id: Any(incoming),
},
{
direction: MessageDirection.INCOMING,
},
transactionManager,
);

await messageChannelMessageAssociationRepository.update(
{
id: Any(outgoing),
},
{
direction: MessageDirection.OUTGOING,
},
transactionManager,
);

const numberOfProcessedAssociations =
i + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_BATCH_SIZE;

if (
numberOfProcessedAssociations %
(MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_BATCH_SIZE * 10) ===
0 ||
numberOfProcessedAssociations >=
messageChannelMessageAssociationCount
) {
this.logger.log(
chalk.green(
`Processed ${Math.min(numberOfProcessedAssociations, messageChannelMessageAssociationCount)} of ${messageChannelMessageAssociationCount} message channel message associations`,
),
);
}
}
} catch (error) {
this.logger.log(
chalk.red(`Running command on workspace ${workspaceId} failed`),
);
throw error;
}
});

await this.workspaceMetadataVersionService.incrementMetadataVersion(
workspaceId,
);

this.logger.log(
chalk.green(`Running command on workspace ${workspaceId} done`),
);
} catch (error) {
this.logger.error(
`Migration failed for workspace ${workspaceId}: ${error.message}`,
);
}
}

this.logger.log(chalk.green(`Command completed!`));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Command, CommandRunner, Option } from 'nest-commander';

import { SetMessageDirectionCommand } from 'src/database/commands/upgrade-version/0-24/0-24-set-message-direction.command';
import { SyncWorkspaceMetadataCommand } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command';

interface UpdateTo0_24CommandOptions {
workspaceId?: string;
}

@Command({
name: 'upgrade-0.24',
description: 'Upgrade to 0.24',
})
export class UpgradeTo0_24Command extends CommandRunner {
constructor(
private readonly syncWorkspaceMetadataCommand: SyncWorkspaceMetadataCommand,
private readonly setMessagesDirectionCommand: SetMessageDirectionCommand,
) {
super();
}

@Option({
flags: '-w, --workspace-id [workspace_id]',
description:
'workspace id. Command runs on all active workspaces if not provided',
required: false,
})
parseWorkspaceId(value: string): string {
return value;
}

async run(
passedParam: string[],
options: UpdateTo0_24CommandOptions,
): Promise<void> {
await this.syncWorkspaceMetadataCommand.run(passedParam, {
...options,
force: true,
});
await this.setMessagesDirectionCommand.run(passedParam, options);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';

import { SetMessageDirectionCommand } from 'src/database/commands/upgrade-version/0-24/0-24-set-message-direction.command';
import { UpgradeTo0_24Command } from 'src/database/commands/upgrade-version/0-24/0-24-upgrade-version.command';
import { SetCustomObjectIsSoftDeletableCommand } from 'src/database/commands/upgrade-version/0-30/0-30-set-custom-object-is-soft-deletable.command';
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
import { KeyValuePair } from 'src/engine/core-modules/key-value-pair/key-value-pair.entity';
import { OnboardingModule } from 'src/engine/core-modules/onboarding/onboarding.module';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { FileStorageModule } from 'src/engine/integrations/file-storage/file-storage.module';
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
import { WorkspaceStatusModule } from 'src/engine/workspace-manager/workspace-status/workspace-manager.module';
import { WorkspaceSyncMetadataCommandsModule } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/workspace-sync-metadata-commands.module';

@Module({
imports: [
TypeOrmModule.forFeature([Workspace, KeyValuePair], 'core'),
WorkspaceSyncMetadataCommandsModule,
FileStorageModule,
OnboardingModule,
TypeORMModule,
DataSourceModule,
WorkspaceMetadataVersionModule,
FieldMetadataModule,
WorkspaceStatusModule,
TypeOrmModule.forFeature(
[FieldMetadataEntity, ObjectMetadataEntity],
'metadata',
),
TypeORMModule,
],
providers: [
UpgradeTo0_24Command,
SetMessageDirectionCommand,
SetCustomObjectIsSoftDeletableCommand,
],
})
export class UpgradeTo0_24CommandModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { InjectRepository } from '@nestjs/typeorm';

import { Command } from 'nest-commander';
import { In, Repository } from 'typeorm';

import {
ActiveWorkspacesCommandOptions,
ActiveWorkspacesCommandRunner,
} from 'src/database/commands/active-workspaces.command';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';

type SetCustomObjectIsSoftDeletableCommandOptions =
ActiveWorkspacesCommandOptions;

@Command({
name: 'upgrade-0.30:set-custom-object-is-soft-deletable',
description: 'Set custom object is soft deletable',
})
export class SetCustomObjectIsSoftDeletableCommand extends ActiveWorkspacesCommandRunner {
constructor(
@InjectRepository(Workspace, 'core')
protected readonly workspaceRepository: Repository<Workspace>,
@InjectRepository(ObjectMetadataEntity, 'metadata')
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
) {
super(workspaceRepository);
}

async executeActiveWorkspacesCommand(
_passedParam: string[],
options: SetCustomObjectIsSoftDeletableCommandOptions,
workspaceIds: string[],
): Promise<void> {
const updateCriteria = {
workspaceId: In(workspaceIds),
isCustom: true,
isSoftDeletable: false,
};

if (options.dryRun) {
const objectsToUpdate = await this.objectMetadataRepository.find({
select: ['id'],
where: updateCriteria,
});

this.logger.log(
`Dry run: ${objectsToUpdate.length} objects would be updated`,
);

return;
}

const result = await this.objectMetadataRepository.update(updateCriteria, {
isSoftDeletable: true,
});

this.logger.log(`Updated ${result.affected} objects`);
}
}
Loading

0 comments on commit 7f7b000

Please sign in to comment.