Add option to synchronize all active workspaces at once (#6221)

In the longer term, we want to improve the efficiency and reliability of
the sync-metadata command, by choosing an error handling strategy and
paying greater attention to health checks.
In the meantime, this PR adds an option to run the sync-metadata command
on all active workspaces at once.

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Marie
2024-07-11 19:48:07 +02:00
committed by GitHub
parent 5cb7f68b7c
commit 5ad287baf5
11 changed files with 195 additions and 112 deletions

View File

@ -0,0 +1,74 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Any, Repository } from 'typeorm';
import {
BillingSubscription,
SubscriptionStatus,
} from 'src/engine/core-modules/billing/entities/billing-subscription.entity';
import {
FeatureFlagEntity,
FeatureFlagKeys,
} from 'src/engine/core-modules/feature-flag/feature-flag.entity';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
@Injectable()
export class WorkspaceStatusService {
constructor(
private readonly environmentService: EnvironmentService,
@InjectRepository(Workspace, 'core')
private readonly workspaceRepository: Repository<Workspace>,
@InjectRepository(BillingSubscription, 'core')
private readonly billingSubscriptionRepository: Repository<BillingSubscription>,
@InjectRepository(FeatureFlagEntity, 'core')
private readonly featureFlagRepository: Repository<FeatureFlagEntity>,
) {}
async getActiveWorkspaceIds(): Promise<string[]> {
const workspaces = await this.workspaceRepository.find();
const workspaceIds = workspaces.map((workspace) => workspace.id);
if (!this.environmentService.get('IS_BILLING_ENABLED')) {
return workspaceIds;
}
const billingSubscriptionForWorkspaces =
await this.billingSubscriptionRepository.find({
where: {
workspaceId: Any(workspaceIds),
status: Any([
SubscriptionStatus.PastDue,
SubscriptionStatus.Active,
SubscriptionStatus.Trialing,
]),
},
});
const workspaceIdsWithActiveSubscription =
billingSubscriptionForWorkspaces.map(
(billingSubscription) => billingSubscription.workspaceId,
);
const freeAccessEnabledFeatureFlagForWorkspace =
await this.featureFlagRepository.find({
where: {
workspaceId: Any(workspaceIds),
key: FeatureFlagKeys.IsFreeAccessEnabled,
value: true,
},
});
const workspaceIdsWithFreeAccessEnabled =
freeAccessEnabledFeatureFlagForWorkspace.map(
(featureFlag) => featureFlag.workspaceId,
);
return workspaceIds.filter(
(workspaceId) =>
workspaceIdsWithActiveSubscription.includes(workspaceId) ||
workspaceIdsWithFreeAccessEnabled.includes(workspaceId),
);
}
}

View File

@ -0,0 +1,21 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity';
import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module';
import { WorkspaceStatusService } from 'src/engine/workspace-manager/workspace-status/services/workspace-status.service';
@Module({
imports: [
EnvironmentModule,
TypeOrmModule.forFeature(
[Workspace, BillingSubscription, FeatureFlagEntity],
'core',
),
],
exports: [WorkspaceStatusService],
providers: [WorkspaceStatusService],
})
export class WorkspaceStatusModule {}