Improve performance twenty orm (#6691)
## Context As we grow, the messaging scripts are experiencing performance issues forcing us to temporarily disable them on the cloud. While investigating the performance, I have noticed that generating the entity schema (for twentyORM) in the repository is taking ~500ms locally on my Mac M2 so likely more on pods. Caching the entitySchema then! I'm also clarifying naming around schemaVersion and cacheVersions ==> both are renamed workspaceMetadataVersion and migrated to the workspace table (the workspaceCacheVersion table is dropped).
This commit is contained in:
@ -7455,7 +7455,7 @@ export type Workspace = {
|
|||||||
billingSubscriptions?: Maybe<Array<BillingSubscription>>;
|
billingSubscriptions?: Maybe<Array<BillingSubscription>>;
|
||||||
createdAt: Scalars['DateTime'];
|
createdAt: Scalars['DateTime'];
|
||||||
currentBillingSubscription?: Maybe<BillingSubscription>;
|
currentBillingSubscription?: Maybe<BillingSubscription>;
|
||||||
currentCacheVersion?: Maybe<Scalars['String']>;
|
metadataVersion?: Maybe<Scalars['String']>;
|
||||||
deletedAt?: Maybe<Scalars['DateTime']>;
|
deletedAt?: Maybe<Scalars['DateTime']>;
|
||||||
displayName?: Maybe<Scalars['String']>;
|
displayName?: Maybe<Scalars['String']>;
|
||||||
domainName?: Maybe<Scalars['String']>;
|
domainName?: Maybe<Scalars['String']>;
|
||||||
|
|||||||
@ -1380,7 +1380,9 @@ export type Workspace = {
|
|||||||
billingSubscriptions?: Maybe<Array<BillingSubscription>>;
|
billingSubscriptions?: Maybe<Array<BillingSubscription>>;
|
||||||
createdAt: Scalars['DateTime']['output'];
|
createdAt: Scalars['DateTime']['output'];
|
||||||
currentBillingSubscription?: Maybe<BillingSubscription>;
|
currentBillingSubscription?: Maybe<BillingSubscription>;
|
||||||
currentCacheVersion?: Maybe<Scalars['String']['output']>;
|
currentMetadataVersion: Scalars['Float']['output'];
|
||||||
|
databaseSchema: Scalars['String']['output'];
|
||||||
|
databaseUrl: Scalars['String']['output'];
|
||||||
deletedAt?: Maybe<Scalars['DateTime']['output']>;
|
deletedAt?: Maybe<Scalars['DateTime']['output']>;
|
||||||
displayName?: Maybe<Scalars['String']['output']>;
|
displayName?: Maybe<Scalars['String']['output']>;
|
||||||
domainName?: Maybe<Scalars['String']['output']>;
|
domainName?: Maybe<Scalars['String']['output']>;
|
||||||
@ -1388,6 +1390,7 @@ export type Workspace = {
|
|||||||
id: Scalars['UUID']['output'];
|
id: Scalars['UUID']['output'];
|
||||||
inviteHash?: Maybe<Scalars['String']['output']>;
|
inviteHash?: Maybe<Scalars['String']['output']>;
|
||||||
logo?: Maybe<Scalars['String']['output']>;
|
logo?: Maybe<Scalars['String']['output']>;
|
||||||
|
metadataVersion: Scalars['Float']['output'];
|
||||||
updatedAt: Scalars['DateTime']['output'];
|
updatedAt: Scalars['DateTime']['output'];
|
||||||
workspaceMembersCount?: Maybe<Scalars['Float']['output']>;
|
workspaceMembersCount?: Maybe<Scalars['Float']['output']>;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1067,7 +1067,8 @@ export type Workspace = {
|
|||||||
billingSubscriptions?: Maybe<Array<BillingSubscription>>;
|
billingSubscriptions?: Maybe<Array<BillingSubscription>>;
|
||||||
createdAt: Scalars['DateTime'];
|
createdAt: Scalars['DateTime'];
|
||||||
currentBillingSubscription?: Maybe<BillingSubscription>;
|
currentBillingSubscription?: Maybe<BillingSubscription>;
|
||||||
currentCacheVersion?: Maybe<Scalars['String']>;
|
databaseSchema: Scalars['String'];
|
||||||
|
databaseUrl: Scalars['String'];
|
||||||
deletedAt?: Maybe<Scalars['DateTime']>;
|
deletedAt?: Maybe<Scalars['DateTime']>;
|
||||||
displayName?: Maybe<Scalars['String']>;
|
displayName?: Maybe<Scalars['String']>;
|
||||||
domainName?: Maybe<Scalars['String']>;
|
domainName?: Maybe<Scalars['String']>;
|
||||||
@ -1075,6 +1076,7 @@ export type Workspace = {
|
|||||||
id: Scalars['UUID'];
|
id: Scalars['UUID'];
|
||||||
inviteHash?: Maybe<Scalars['String']>;
|
inviteHash?: Maybe<Scalars['String']>;
|
||||||
logo?: Maybe<Scalars['String']>;
|
logo?: Maybe<Scalars['String']>;
|
||||||
|
metadataVersion: Scalars['Float'];
|
||||||
updatedAt: Scalars['DateTime'];
|
updatedAt: Scalars['DateTime'];
|
||||||
workspaceMembersCount?: Maybe<Scalars['Float']>;
|
workspaceMembersCount?: Maybe<Scalars['Float']>;
|
||||||
};
|
};
|
||||||
@ -1360,7 +1362,7 @@ export type ImpersonateMutationVariables = Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type ImpersonateMutation = { __typename?: 'Mutation', impersonate: { __typename?: 'Verify', user: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, currentCacheVersion?: string | null, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } };
|
export type ImpersonateMutation = { __typename?: 'Mutation', impersonate: { __typename?: 'Verify', user: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } };
|
||||||
|
|
||||||
export type RenewTokenMutationVariables = Exact<{
|
export type RenewTokenMutationVariables = Exact<{
|
||||||
appToken: Scalars['String'];
|
appToken: Scalars['String'];
|
||||||
@ -1392,7 +1394,7 @@ export type VerifyMutationVariables = Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type VerifyMutation = { __typename?: 'Mutation', verify: { __typename?: 'Verify', user: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, currentCacheVersion?: string | null, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } };
|
export type VerifyMutation = { __typename?: 'Mutation', verify: { __typename?: 'Verify', user: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } };
|
||||||
|
|
||||||
export type CheckUserExistsQueryVariables = Exact<{
|
export type CheckUserExistsQueryVariables = Exact<{
|
||||||
email: Scalars['String'];
|
email: Scalars['String'];
|
||||||
@ -1453,7 +1455,7 @@ export type GetAisqlQueryQueryVariables = Exact<{
|
|||||||
|
|
||||||
export type GetAisqlQueryQuery = { __typename?: 'Query', getAISQLQuery: { __typename?: 'AISQLQueryResult', sqlQuery: string, sqlQueryResult?: string | null, queryFailedErrorMessage?: string | null } };
|
export type GetAisqlQueryQuery = { __typename?: 'Query', getAISQLQuery: { __typename?: 'AISQLQueryResult', sqlQuery: string, sqlQueryResult?: string | null, queryFailedErrorMessage?: string | null } };
|
||||||
|
|
||||||
export type UserQueryFragmentFragment = { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, currentCacheVersion?: string | null, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> };
|
export type UserQueryFragmentFragment = { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> };
|
||||||
|
|
||||||
export type DeleteUserAccountMutationVariables = Exact<{ [key: string]: never; }>;
|
export type DeleteUserAccountMutationVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
@ -1470,7 +1472,7 @@ export type UploadProfilePictureMutation = { __typename?: 'Mutation', uploadProf
|
|||||||
export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
|
export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, currentCacheVersion?: string | null, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> } };
|
export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> } };
|
||||||
|
|
||||||
export type WorkspaceMemberQueryFragmentFragment = { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } };
|
export type WorkspaceMemberQueryFragmentFragment = { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } };
|
||||||
|
|
||||||
@ -1652,7 +1654,7 @@ export const UserQueryFragmentFragmentDoc = gql`
|
|||||||
value
|
value
|
||||||
workspaceId
|
workspaceId
|
||||||
}
|
}
|
||||||
currentCacheVersion
|
metadataVersion
|
||||||
currentBillingSubscription {
|
currentBillingSubscription {
|
||||||
id
|
id
|
||||||
status
|
status
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
|
import { InMemoryCache, NormalizedCacheObject } from '@apollo/client';
|
||||||
import { useMemo, useRef } from 'react';
|
import { useMemo, useRef } from 'react';
|
||||||
import { useLocation, useNavigate } from 'react-router-dom';
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
import { InMemoryCache, NormalizedCacheObject } from '@apollo/client';
|
|
||||||
import { useRecoilState, useSetRecoilState } from 'recoil';
|
import { useRecoilState, useSetRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentUserState } from '@/auth/states/currentUserState';
|
||||||
@ -49,8 +49,8 @@ export const useApolloFactory = (options: Partial<Options<any>> = {}) => {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
headers: {
|
headers: {
|
||||||
...(currentWorkspace?.currentCacheVersion && {
|
...(currentWorkspace?.metadataVersion && {
|
||||||
'X-Schema-Version': currentWorkspace.currentCacheVersion,
|
'X-Schema-Version': `${currentWorkspace.metadataVersion}`,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
@ -95,7 +95,7 @@ export const useApolloFactory = (options: Partial<Options<any>> = {}) => {
|
|||||||
setCurrentWorkspace,
|
setCurrentWorkspace,
|
||||||
setWorkspaces,
|
setWorkspaces,
|
||||||
isDebugMode,
|
isDebugMode,
|
||||||
currentWorkspace?.currentCacheVersion,
|
currentWorkspace?.metadataVersion,
|
||||||
setPreviousUrl,
|
setPreviousUrl,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ export type CurrentWorkspace = Pick<
|
|||||||
| 'activationStatus'
|
| 'activationStatus'
|
||||||
| 'currentBillingSubscription'
|
| 'currentBillingSubscription'
|
||||||
| 'workspaceMembersCount'
|
| 'workspaceMembersCount'
|
||||||
| 'currentCacheVersion'
|
| 'metadataVersion'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export const currentWorkspaceState = createState<CurrentWorkspace | null>({
|
export const currentWorkspaceState = createState<CurrentWorkspace | null>({
|
||||||
|
|||||||
@ -29,7 +29,7 @@ export const USER_QUERY_FRAGMENT = gql`
|
|||||||
value
|
value
|
||||||
workspaceId
|
workspaceId
|
||||||
}
|
}
|
||||||
currentCacheVersion
|
metadataVersion
|
||||||
currentBillingSubscription {
|
currentBillingSubscription {
|
||||||
id
|
id
|
||||||
status
|
status
|
||||||
|
|||||||
@ -63,7 +63,7 @@ export const mockDefaultWorkspace: Workspace = {
|
|||||||
],
|
],
|
||||||
createdAt: '2023-04-26T10:23:42.33625+00:00',
|
createdAt: '2023-04-26T10:23:42.33625+00:00',
|
||||||
updatedAt: '2023-04-26T10:23:42.33625+00:00',
|
updatedAt: '2023-04-26T10:23:42.33625+00:00',
|
||||||
currentCacheVersion: '1',
|
metadataVersion: 1,
|
||||||
currentBillingSubscription: {
|
currentBillingSubscription: {
|
||||||
__typename: 'BillingSubscription',
|
__typename: 'BillingSubscription',
|
||||||
id: '7efbc3f7-6e5e-4128-957e-8d86808cdf6a',
|
id: '7efbc3f7-6e5e-4128-957e-8d86808cdf6a',
|
||||||
@ -71,6 +71,8 @@ export const mockDefaultWorkspace: Workspace = {
|
|||||||
status: SubscriptionStatus.Active,
|
status: SubscriptionStatus.Active,
|
||||||
},
|
},
|
||||||
workspaceMembersCount: 1,
|
workspaceMembersCount: 1,
|
||||||
|
databaseSchema: '',
|
||||||
|
databaseUrl: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mockedWorkspaceMemberData: WorkspaceMember = {
|
export const mockedWorkspaceMemberData: WorkspaceMember = {
|
||||||
|
|||||||
2
packages/twenty-server/@types/express.d.ts
vendored
2
packages/twenty-server/@types/express.d.ts
vendored
@ -8,6 +8,6 @@ declare module 'express-serve-static-core' {
|
|||||||
apiKey?: ApiKeyWorkspaceEntity | null;
|
apiKey?: ApiKeyWorkspaceEntity | null;
|
||||||
workspace?: Workspace;
|
workspace?: Workspace;
|
||||||
workspaceId?: string;
|
workspaceId?: string;
|
||||||
cacheVersion?: string | null;
|
workspaceMetadataVersion?: number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,7 @@ index 16843949d8589a299d8195b0a349ac4dac0bacbf..21e7fe2bbcba36b04a274be9d2219fd3
|
|||||||
...options,
|
...options,
|
||||||
+ schema: async (request) => {
|
+ schema: async (request) => {
|
||||||
+ const workspaceId = request.req.workspace?.id ?? 'anonymous'
|
+ const workspaceId = request.req.workspace?.id ?? 'anonymous'
|
||||||
+ const workspaceCacheVersion = request.req.cacheVersion ?? '0'
|
+ const workspaceCacheVersion = request.req.workspaceMetadataVersion ?? '0'
|
||||||
+ const workspaceUserId = request.req.user?.id ?? 'anonymous'
|
+ const workspaceUserId = request.req.user?.id ?? 'anonymous'
|
||||||
+ const url = request.req.baseUrl
|
+ const url = request.req.baseUrl
|
||||||
+
|
+
|
||||||
@ -79,7 +79,7 @@ index 16843949d8589a299d8195b0a349ac4dac0bacbf..21e7fe2bbcba36b04a274be9d2219fd3
|
|||||||
...options,
|
...options,
|
||||||
+ schema: async (request) => {
|
+ schema: async (request) => {
|
||||||
+ const workspaceId = request.req.workspace?.id ?? 'anonymous'
|
+ const workspaceId = request.req.workspace?.id ?? 'anonymous'
|
||||||
+ const workspaceCacheVersion = request.req.cacheVersion ?? '0'
|
+ const workspaceCacheVersion = request.req.workspaceMetadataVersion ?? '0'
|
||||||
+ const workspaceUserId = request.req.user?.id ?? 'anonymous'
|
+ const workspaceUserId = request.req.user?.id ?? 'anonymous'
|
||||||
+ const url = request.req.baseUrl
|
+ const url = request.req.baseUrl
|
||||||
+
|
+
|
||||||
@ -146,7 +146,7 @@ index 7068c519320b379917c46763cd280b1cdd3e48f0..418e1030373fc1e0fb85a932ac8da9b3
|
|||||||
...options,
|
...options,
|
||||||
+ schema: async (request) => {
|
+ schema: async (request) => {
|
||||||
+ const workspaceId = request.req.workspace?.id ?? 'anonymous'
|
+ const workspaceId = request.req.workspace?.id ?? 'anonymous'
|
||||||
+ const workspaceCacheVersion = request.req.cacheVersion ?? '0'
|
+ const workspaceCacheVersion = request.req.workspaceMetadataVersion ?? '0'
|
||||||
+ const workspaceUserId = request.req.user?.id ?? 'anonymous'
|
+ const workspaceUserId = request.req.user?.id ?? 'anonymous'
|
||||||
+ const url = request.req.baseUrl
|
+ const url = request.req.baseUrl
|
||||||
+
|
+
|
||||||
@ -193,7 +193,7 @@ index 7068c519320b379917c46763cd280b1cdd3e48f0..418e1030373fc1e0fb85a932ac8da9b3
|
|||||||
...options,
|
...options,
|
||||||
+ schema: async (request) => {
|
+ schema: async (request) => {
|
||||||
+ const workspaceId = request.req.workspace?.id ?? 'anonymous'
|
+ const workspaceId = request.req.workspace?.id ?? 'anonymous'
|
||||||
+ const workspaceCacheVersion = request.req.cacheVersion ?? '0'
|
+ const workspaceCacheVersion = request.req.workspaceMetadataVersion ?? '0'
|
||||||
+ const workspaceUserId = request.req.user?.id ?? 'anonymous'
|
+ const workspaceUserId = request.req.user?.id ?? 'anonymous'
|
||||||
+ const url = request.req.baseUrl
|
+ const url = request.req.baseUrl
|
||||||
+
|
+
|
||||||
@ -387,7 +387,7 @@ index ce142f61ede52499485b19d8af057f4cb828d0f7..5888d31cae1b7aca57ed0819209812ac
|
|||||||
...options,
|
...options,
|
||||||
+ schema: async request => {
|
+ schema: async request => {
|
||||||
+ const workspaceId = request.req.workspace.id
|
+ const workspaceId = request.req.workspace.id
|
||||||
+ const workspaceCacheVersion = request.req.cacheVersion
|
+ const workspaceCacheVersion = request.req.workspaceMetadataVersion
|
||||||
+ const workspaceUserId = request.req.user?.id ?? 'anonymous'
|
+ const workspaceUserId = request.req.user?.id ?? 'anonymous'
|
||||||
+ const url = request.req.baseUrl
|
+ const url = request.req.baseUrl
|
||||||
+
|
+
|
||||||
@ -448,7 +448,7 @@ index ce142f61ede52499485b19d8af057f4cb828d0f7..5888d31cae1b7aca57ed0819209812ac
|
|||||||
...options,
|
...options,
|
||||||
+ schema: async request => {
|
+ schema: async request => {
|
||||||
+ const workspaceId = request.req.workspace.id
|
+ const workspaceId = request.req.workspace.id
|
||||||
+ const workspaceCacheVersion = request.req.cacheVersion
|
+ const workspaceCacheVersion = request.req.workspaceMetadataVersion
|
||||||
+ const workspaceUserId = request.req.user?.id ?? 'anonymous'
|
+ const workspaceUserId = request.req.user?.id ?? 'anonymous'
|
||||||
+ const url = request.req.baseUrl
|
+ const url = request.req.baseUrl
|
||||||
+
|
+
|
||||||
|
|||||||
@ -5,27 +5,27 @@ import {
|
|||||||
RequestMethod,
|
RequestMethod,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { ConfigModule } from '@nestjs/config';
|
import { ConfigModule } from '@nestjs/config';
|
||||||
import { ServeStaticModule } from '@nestjs/serve-static';
|
|
||||||
import { GraphQLModule } from '@nestjs/graphql';
|
import { GraphQLModule } from '@nestjs/graphql';
|
||||||
|
import { ServeStaticModule } from '@nestjs/serve-static';
|
||||||
|
|
||||||
import { existsSync } from 'fs';
|
import { existsSync } from 'fs';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
|
||||||
import { YogaDriverConfig, YogaDriver } from '@graphql-yoga/nestjs';
|
import { YogaDriver, YogaDriverConfig } from '@graphql-yoga/nestjs';
|
||||||
|
|
||||||
import { RestApiModule } from 'src/engine/api/rest/rest-api.module';
|
|
||||||
import { ModulesModule } from 'src/modules/modules.module';
|
|
||||||
import { CoreGraphQLApiModule } from 'src/engine/api/graphql/core-graphql-api.module';
|
import { CoreGraphQLApiModule } from 'src/engine/api/graphql/core-graphql-api.module';
|
||||||
import { MetadataGraphQLApiModule } from 'src/engine/api/graphql/metadata-graphql-api.module';
|
|
||||||
import { GraphQLConfigModule } from 'src/engine/api/graphql/graphql-config/graphql-config.module';
|
import { GraphQLConfigModule } from 'src/engine/api/graphql/graphql-config/graphql-config.module';
|
||||||
import { GraphQLConfigService } from 'src/engine/api/graphql/graphql-config/graphql-config.service';
|
import { GraphQLConfigService } from 'src/engine/api/graphql/graphql-config/graphql-config.service';
|
||||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
import { MetadataGraphQLApiModule } from 'src/engine/api/graphql/metadata-graphql-api.module';
|
||||||
import { GraphQLHydrateRequestFromTokenMiddleware } from 'src/engine/middlewares/graphql-hydrate-request-from-token.middleware';
|
import { RestApiModule } from 'src/engine/api/rest/rest-api.module';
|
||||||
import { MessageQueueModule } from 'src/engine/integrations/message-queue/message-queue.module';
|
|
||||||
import { MessageQueueDriverType } from 'src/engine/integrations/message-queue/interfaces';
|
import { MessageQueueDriverType } from 'src/engine/integrations/message-queue/interfaces';
|
||||||
|
import { MessageQueueModule } from 'src/engine/integrations/message-queue/message-queue.module';
|
||||||
|
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||||
|
import { GraphQLHydrateRequestFromTokenMiddleware } from 'src/engine/middlewares/graphql-hydrate-request-from-token.middleware';
|
||||||
|
import { ModulesModule } from 'src/modules/modules.module';
|
||||||
|
|
||||||
import { IntegrationsModule } from './engine/integrations/integrations.module';
|
|
||||||
import { CoreEngineModule } from './engine/core-modules/core-engine.module';
|
import { CoreEngineModule } from './engine/core-modules/core-engine.module';
|
||||||
|
import { IntegrationsModule } from './engine/integrations/integrations.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@ -52,7 +52,7 @@ import { CoreEngineModule } from './engine/core-modules/core-engine.module';
|
|||||||
// Modules module, contains all business logic modules
|
// Modules module, contains all business logic modules
|
||||||
ModulesModule,
|
ModulesModule,
|
||||||
// Needed for the user workspace middleware
|
// Needed for the user workspace middleware
|
||||||
WorkspaceCacheVersionModule,
|
WorkspaceMetadataVersionModule,
|
||||||
// Api modules
|
// Api modules
|
||||||
CoreGraphQLApiModule,
|
CoreGraphQLApiModule,
|
||||||
MetadataGraphQLApiModule,
|
MetadataGraphQLApiModule,
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
import { Logger } from '@nestjs/common';
|
import { Logger } from '@nestjs/common';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
|
||||||
|
|
||||||
import { Command, CommandRunner } from 'nest-commander';
|
import { Command, CommandRunner } from 'nest-commander';
|
||||||
import { EntityManager, Repository } from 'typeorm';
|
import { EntityManager } from 'typeorm';
|
||||||
|
|
||||||
import { seedCoreSchema } from 'src/database/typeorm-seeds/core';
|
import { seedCoreSchema } from 'src/database/typeorm-seeds/core';
|
||||||
import {
|
import {
|
||||||
@ -39,7 +38,6 @@ import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-
|
|||||||
import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service';
|
import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service';
|
||||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
|
||||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||||
import { viewPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/view';
|
import { viewPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/view';
|
||||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||||
@ -61,12 +59,9 @@ export class DataSeedWorkspaceCommand extends CommandRunner {
|
|||||||
private readonly workspaceSyncMetadataService: WorkspaceSyncMetadataService,
|
private readonly workspaceSyncMetadataService: WorkspaceSyncMetadataService,
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
private readonly fieldMetadataService: FieldMetadataService,
|
private readonly fieldMetadataService: FieldMetadataService,
|
||||||
@InjectRepository(ObjectMetadataEntity, 'metadata')
|
|
||||||
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
|
|
||||||
private readonly objectMetadataService: ObjectMetadataService,
|
private readonly objectMetadataService: ObjectMetadataService,
|
||||||
@InjectCacheStorage(CacheStorageNamespace.WorkspaceSchema)
|
@InjectCacheStorage(CacheStorageNamespace.EngineWorkspace)
|
||||||
private readonly workspaceSchemaCache: CacheStorageService,
|
private readonly workspaceSchemaCache: CacheStorageService,
|
||||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@ -75,7 +70,6 @@ export class DataSeedWorkspaceCommand extends CommandRunner {
|
|||||||
try {
|
try {
|
||||||
for (const workspaceId of this.workspaceIds) {
|
for (const workspaceId of this.workspaceIds) {
|
||||||
await this.workspaceSchemaCache.flush();
|
await this.workspaceSchemaCache.flush();
|
||||||
await this.workspaceCacheVersionService.deleteVersion(workspaceId);
|
|
||||||
|
|
||||||
await rawDataSource.initialize();
|
await rawDataSource.initialize();
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/
|
|||||||
import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module';
|
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 { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||||
import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module';
|
import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module';
|
||||||
import { WorkspaceStatusModule } from 'src/engine/workspace-manager/workspace-status/workspace-manager.module';
|
import { WorkspaceStatusModule } from 'src/engine/workspace-manager/workspace-status/workspace-manager.module';
|
||||||
@ -45,7 +45,7 @@ import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/worksp
|
|||||||
ObjectMetadataModule,
|
ObjectMetadataModule,
|
||||||
FieldMetadataModule,
|
FieldMetadataModule,
|
||||||
DataSeedDemoWorkspaceModule,
|
DataSeedDemoWorkspaceModule,
|
||||||
WorkspaceCacheVersionModule,
|
WorkspaceMetadataVersionModule,
|
||||||
UpgradeTo0_23CommandModule,
|
UpgradeTo0_23CommandModule,
|
||||||
UpgradeVersionModule,
|
UpgradeVersionModule,
|
||||||
],
|
],
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { TypeORMService } from 'src/database/typeorm/typeorm.service';
|
|||||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||||
import { WorkspaceStatusService } from 'src/engine/workspace-manager/workspace-status/services/workspace-status.service';
|
import { WorkspaceStatusService } from 'src/engine/workspace-manager/workspace-status/services/workspace-status.service';
|
||||||
import { MessageChannelSyncStatus } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
import { MessageChannelSyncStatus } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ export class MigrateMessageChannelSyncStatusEnumCommand extends CommandRunner {
|
|||||||
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
|
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
|
||||||
private readonly typeORMService: TypeORMService,
|
private readonly typeORMService: TypeORMService,
|
||||||
private readonly dataSourceService: DataSourceService,
|
private readonly dataSourceService: DataSourceService,
|
||||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@ -212,7 +212,9 @@ export class MigrateMessageChannelSyncStatusEnumCommand extends CommandRunner {
|
|||||||
options: newOptions,
|
options: newOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
this.logger.log(
|
this.logger.log(
|
||||||
chalk.green(`Running command on workspace ${workspaceId} done`),
|
chalk.green(`Running command on workspace ${workspaceId} done`),
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import {
|
|||||||
Workspace,
|
Workspace,
|
||||||
WorkspaceActivationStatus,
|
WorkspaceActivationStatus,
|
||||||
} from 'src/engine/core-modules/workspace/workspace.entity';
|
} from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
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 { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||||
import { CalendarChannelSyncStatus } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
|
import { CalendarChannelSyncStatus } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
|
||||||
import { AccountsToReconnectService } from 'src/modules/connected-account/services/accounts-to-reconnect.service';
|
import { AccountsToReconnectService } from 'src/modules/connected-account/services/accounts-to-reconnect.service';
|
||||||
@ -34,7 +34,7 @@ export class SetUserVarsAccountsToReconnectCommand extends CommandRunner {
|
|||||||
SetUserVarsAccountsToReconnectCommand.name,
|
SetUserVarsAccountsToReconnectCommand.name,
|
||||||
);
|
);
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||||
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||||
private readonly accountsToReconnectService: AccountsToReconnectService,
|
private readonly accountsToReconnectService: AccountsToReconnectService,
|
||||||
@InjectRepository(KeyValuePair, 'core')
|
@InjectRepository(KeyValuePair, 'core')
|
||||||
@ -149,7 +149,9 @@ export class SetUserVarsAccountsToReconnectCommand extends CommandRunner {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
this.logger.log(
|
this.logger.log(
|
||||||
chalk.green(`Running command on workspace ${workspaceId} done`),
|
chalk.green(`Running command on workspace ${workspaceId} done`),
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import {
|
|||||||
WorkspaceActivationStatus,
|
WorkspaceActivationStatus,
|
||||||
} from 'src/engine/core-modules/workspace/workspace.entity';
|
} from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||||
|
|
||||||
interface SetWorkspaceActivationStatusCommandOptions {
|
interface SetWorkspaceActivationStatusCommandOptions {
|
||||||
workspaceId?: string;
|
workspaceId?: string;
|
||||||
@ -31,7 +31,7 @@ export class SetWorkspaceActivationStatusCommand extends CommandRunner {
|
|||||||
private readonly workspaceRepository: Repository<Workspace>,
|
private readonly workspaceRepository: Repository<Workspace>,
|
||||||
private readonly typeORMService: TypeORMService,
|
private readonly typeORMService: TypeORMService,
|
||||||
private readonly dataSourceService: DataSourceService,
|
private readonly dataSourceService: DataSourceService,
|
||||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||||
private readonly billingSubscriptionService: BillingSubscriptionService,
|
private readonly billingSubscriptionService: BillingSubscriptionService,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
@ -97,7 +97,9 @@ export class SetWorkspaceActivationStatusCommand extends CommandRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
this.logger.log(
|
this.logger.log(
|
||||||
chalk.green(`Running command on workspace ${workspaceId} done`),
|
chalk.green(`Running command on workspace ${workspaceId} done`),
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { TypeORMService } from 'src/database/typeorm/typeorm.service';
|
|||||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
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 { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||||
import { notesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view';
|
import { notesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view';
|
||||||
import { tasksAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-all.view';
|
import { tasksAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-all.view';
|
||||||
@ -44,7 +44,7 @@ export class UpdateActivitiesCommand extends CommandRunner {
|
|||||||
private readonly workspaceStatusService: WorkspaceStatusService,
|
private readonly workspaceStatusService: WorkspaceStatusService,
|
||||||
private readonly typeORMService: TypeORMService,
|
private readonly typeORMService: TypeORMService,
|
||||||
private readonly dataSourceService: DataSourceService,
|
private readonly dataSourceService: DataSourceService,
|
||||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||||
private readonly objectMetadataService: ObjectMetadataService,
|
private readonly objectMetadataService: ObjectMetadataService,
|
||||||
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||||
) {
|
) {
|
||||||
@ -400,7 +400,9 @@ export class UpdateActivitiesCommand extends CommandRunner {
|
|||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/
|
|||||||
import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module';
|
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 { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
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 { 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';
|
import { WorkspaceSyncMetadataCommandsModule } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/workspace-sync-metadata-commands.module';
|
||||||
import { ConnectedAccountModule } from 'src/modules/connected-account/connected-account.module';
|
import { ConnectedAccountModule } from 'src/modules/connected-account/connected-account.module';
|
||||||
@ -35,7 +35,7 @@ import { ViewModule } from 'src/modules/view/view.module';
|
|||||||
OnboardingModule,
|
OnboardingModule,
|
||||||
TypeORMModule,
|
TypeORMModule,
|
||||||
DataSourceModule,
|
DataSourceModule,
|
||||||
WorkspaceCacheVersionModule,
|
WorkspaceMetadataVersionModule,
|
||||||
FieldMetadataModule,
|
FieldMetadataModule,
|
||||||
DataSourceModule,
|
DataSourceModule,
|
||||||
WorkspaceStatusModule,
|
WorkspaceStatusModule,
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/
|
|||||||
import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module';
|
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 { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||||
import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module';
|
import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module';
|
||||||
import { WorkspaceStatusModule } from 'src/engine/workspace-manager/workspace-status/workspace-manager.module';
|
import { WorkspaceStatusModule } from 'src/engine/workspace-manager/workspace-status/workspace-manager.module';
|
||||||
@ -48,7 +48,7 @@ import { ViewModule } from 'src/modules/view/view.module';
|
|||||||
WorkspaceStatusModule,
|
WorkspaceStatusModule,
|
||||||
ObjectMetadataModule,
|
ObjectMetadataModule,
|
||||||
DataSeedDemoWorkspaceModule,
|
DataSeedDemoWorkspaceModule,
|
||||||
WorkspaceCacheVersionModule,
|
WorkspaceMetadataVersionModule,
|
||||||
FieldMetadataModule,
|
FieldMetadataModule,
|
||||||
ViewModule,
|
ViewModule,
|
||||||
BillingModule,
|
BillingModule,
|
||||||
|
|||||||
@ -0,0 +1,31 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class IntroduceMetadataVersionAndDatasourceOnWorkspace1724173430043
|
||||||
|
implements MigrationInterface
|
||||||
|
{
|
||||||
|
name = 'IntroduceMetadataVersionAndDatasourceOnWorkspace1724173430043';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "core"."workspace" ADD "metadataVersion" integer NOT NULL DEFAULT '1'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "core"."workspace" ADD "databaseUrl" character varying NOT NULL DEFAULT ''`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "core"."workspace" ADD "databaseSchema" character varying NOT NULL DEFAULT ''`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "core"."workspace" DROP COLUMN "databaseSchema"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "core"."workspace" DROP COLUMN "databaseUrl"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "core"."workspace" DROP COLUMN "metadataVersion"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class DeprecateCacheVersion1724173061204 implements MigrationInterface {
|
||||||
|
name = 'DeprecateCacheVersion1724173061204';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP TABLE "metadata"."workspaceCacheVersion"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "metadata"."workspaceCacheVersion" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "workspaceId" uuid NOT NULL, "version" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "UQ_1a80ecf2638b477809403cc26ed" UNIQUE ("workspaceId"), CONSTRAINT "PK_5d502f8dbfb5b9a8bf2439320e9" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,11 +1,12 @@
|
|||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
|
||||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
|
||||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
|
||||||
import { ScalarsExplorerService } from 'src/engine/api/graphql/services/scalars-explorer.service';
|
import { ScalarsExplorerService } from 'src/engine/api/graphql/services/scalars-explorer.service';
|
||||||
import { WorkspaceResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/workspace-resolver.factory';
|
import { WorkspaceResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/workspace-resolver.factory';
|
||||||
import { WorkspaceGraphQLSchemaFactory } from 'src/engine/api/graphql/workspace-schema-builder/workspace-graphql-schema.factory';
|
import { WorkspaceGraphQLSchemaFactory } from 'src/engine/api/graphql/workspace-schema-builder/workspace-graphql-schema.factory';
|
||||||
import { WorkspaceSchemaFactory } from 'src/engine/api/graphql/workspace-schema.factory';
|
import { WorkspaceSchemaFactory } from 'src/engine/api/graphql/workspace-schema.factory';
|
||||||
|
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||||
|
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||||
|
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||||
|
|
||||||
describe('WorkspaceSchemaFactory', () => {
|
describe('WorkspaceSchemaFactory', () => {
|
||||||
@ -39,6 +40,10 @@ describe('WorkspaceSchemaFactory', () => {
|
|||||||
provide: WorkspaceCacheStorageService,
|
provide: WorkspaceCacheStorageService,
|
||||||
useValue: {},
|
useValue: {},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: WorkspaceMetadataVersionService,
|
||||||
|
useValue: {},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
|
||||||
import { ScalarsExplorerService } from 'src/engine/api/graphql/services/scalars-explorer.service';
|
import { ScalarsExplorerService } from 'src/engine/api/graphql/services/scalars-explorer.service';
|
||||||
import { WorkspaceSchemaBuilderModule } from 'src/engine/api/graphql/workspace-schema-builder/workspace-schema-builder.module';
|
|
||||||
import { WorkspaceResolverBuilderModule } from 'src/engine/api/graphql/workspace-resolver-builder/workspace-resolver-builder.module';
|
import { WorkspaceResolverBuilderModule } from 'src/engine/api/graphql/workspace-resolver-builder/workspace-resolver-builder.module';
|
||||||
|
import { WorkspaceSchemaBuilderModule } from 'src/engine/api/graphql/workspace-schema-builder/workspace-schema-builder.module';
|
||||||
import { MetadataEngineModule } from 'src/engine/metadata-modules/metadata-engine.module';
|
import { MetadataEngineModule } from 'src/engine/metadata-modules/metadata-engine.module';
|
||||||
|
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||||
|
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||||
|
|
||||||
import { WorkspaceSchemaFactory } from './workspace-schema.factory';
|
import { WorkspaceSchemaFactory } from './workspace-schema.factory';
|
||||||
|
|
||||||
@ -21,6 +22,7 @@ import { WorkspaceSchemaFactory } from './workspace-schema.factory';
|
|||||||
WorkspaceSchemaBuilderModule,
|
WorkspaceSchemaBuilderModule,
|
||||||
WorkspaceResolverBuilderModule,
|
WorkspaceResolverBuilderModule,
|
||||||
WorkspaceCacheStorageModule,
|
WorkspaceCacheStorageModule,
|
||||||
|
WorkspaceMetadataVersionModule,
|
||||||
],
|
],
|
||||||
providers: [WorkspaceSchemaFactory, ScalarsExplorerService],
|
providers: [WorkspaceSchemaFactory, ScalarsExplorerService],
|
||||||
exports: [WorkspaceSchemaFactory],
|
exports: [WorkspaceSchemaFactory],
|
||||||
|
|||||||
@ -9,10 +9,11 @@ export type CacheMetadataPluginConfig = {
|
|||||||
export function useCachedMetadata(config: CacheMetadataPluginConfig): Plugin {
|
export function useCachedMetadata(config: CacheMetadataPluginConfig): Plugin {
|
||||||
const computeCacheKey = (serverContext: any) => {
|
const computeCacheKey = (serverContext: any) => {
|
||||||
const workspaceId = serverContext.req.workspace?.id ?? 'anonymous';
|
const workspaceId = serverContext.req.workspace?.id ?? 'anonymous';
|
||||||
const cacheVersion = serverContext.req.cacheVersion ?? '0';
|
const workspaceMetadataVersion =
|
||||||
|
serverContext.req.workspaceMetadataVersion ?? '0';
|
||||||
const operationName = getOperationName(serverContext);
|
const operationName = getOperationName(serverContext);
|
||||||
|
|
||||||
return `cachedOperations:${operationName}:${workspaceId}:${cacheVersion}`;
|
return `graphql:operations:${operationName}:${workspaceId}:${workspaceMetadataVersion}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getOperationName = (serverContext: any) =>
|
const getOperationName = (serverContext: any) =>
|
||||||
|
|||||||
@ -1,19 +1,18 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { GraphQLModule } from '@nestjs/graphql';
|
import { GraphQLModule } from '@nestjs/graphql';
|
||||||
|
|
||||||
import { YogaDriverConfig, YogaDriver } from '@graphql-yoga/nestjs';
|
import { YogaDriver, YogaDriverConfig } from '@graphql-yoga/nestjs';
|
||||||
|
|
||||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
|
||||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
|
||||||
import { MetadataEngineModule } from 'src/engine/metadata-modules/metadata-engine.module';
|
|
||||||
import { GraphQLConfigModule } from 'src/engine/api/graphql/graphql-config/graphql-config.module';
|
import { GraphQLConfigModule } from 'src/engine/api/graphql/graphql-config/graphql-config.module';
|
||||||
import { metadataModuleFactory } from 'src/engine/api/graphql/metadata.module-factory';
|
import { metadataModuleFactory } from 'src/engine/api/graphql/metadata.module-factory';
|
||||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
|
||||||
import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service';
|
|
||||||
import { DataloaderModule } from 'src/engine/dataloaders/dataloader.module';
|
import { DataloaderModule } from 'src/engine/dataloaders/dataloader.module';
|
||||||
import { DataloaderService } from 'src/engine/dataloaders/dataloader.service';
|
import { DataloaderService } from 'src/engine/dataloaders/dataloader.service';
|
||||||
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
||||||
import { CacheStorageModule } from 'src/engine/integrations/cache-storage/cache-storage.module';
|
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||||
|
import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service';
|
||||||
|
import { MetadataEngineModule } from 'src/engine/metadata-modules/metadata-engine.module';
|
||||||
|
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||||
|
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@ -25,13 +24,12 @@ import { CacheStorageModule } from 'src/engine/integrations/cache-storage/cache-
|
|||||||
EnvironmentService,
|
EnvironmentService,
|
||||||
ExceptionHandlerService,
|
ExceptionHandlerService,
|
||||||
DataloaderService,
|
DataloaderService,
|
||||||
CacheStorageNamespace.WorkspaceSchema,
|
CacheStorageNamespace.EngineWorkspace,
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
MetadataEngineModule,
|
MetadataEngineModule,
|
||||||
WorkspaceMigrationRunnerModule,
|
WorkspaceMigrationRunnerModule,
|
||||||
WorkspaceMigrationModule,
|
WorkspaceMigrationModule,
|
||||||
CacheStorageModule,
|
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class MetadataGraphQLApiModule {}
|
export class MetadataGraphQLApiModule {}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ export const metadataModuleFactory = async (
|
|||||||
environmentService: EnvironmentService,
|
environmentService: EnvironmentService,
|
||||||
exceptionHandlerService: ExceptionHandlerService,
|
exceptionHandlerService: ExceptionHandlerService,
|
||||||
dataloaderService: DataloaderService,
|
dataloaderService: DataloaderService,
|
||||||
workspaceSchemaCacheStorage: CacheStorageService,
|
cacheStorageService: CacheStorageService,
|
||||||
): Promise<YogaDriverConfig> => {
|
): Promise<YogaDriverConfig> => {
|
||||||
const config: YogaDriverConfig = {
|
const config: YogaDriverConfig = {
|
||||||
autoSchemaFile: true,
|
autoSchemaFile: true,
|
||||||
@ -36,12 +36,8 @@ export const metadataModuleFactory = async (
|
|||||||
exceptionHandlerService,
|
exceptionHandlerService,
|
||||||
}),
|
}),
|
||||||
useCachedMetadata({
|
useCachedMetadata({
|
||||||
cacheGetter: workspaceSchemaCacheStorage.get.bind(
|
cacheGetter: cacheStorageService.get.bind(cacheStorageService),
|
||||||
workspaceSchemaCacheStorage,
|
cacheSetter: cacheStorageService.set.bind(cacheStorageService),
|
||||||
),
|
|
||||||
cacheSetter: workspaceSchemaCacheStorage.set.bind(
|
|
||||||
workspaceSchemaCacheStorage,
|
|
||||||
),
|
|
||||||
operationsToCache: ['ObjectMetadataItems'],
|
operationsToCache: ['ObjectMetadataItems'],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,17 +1,18 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
import { GraphQLSchema, printSchema } from 'graphql';
|
|
||||||
import { makeExecutableSchema } from '@graphql-tools/schema';
|
import { makeExecutableSchema } from '@graphql-tools/schema';
|
||||||
|
import { GraphQLSchema, printSchema } from 'graphql';
|
||||||
import { gql } from 'graphql-tag';
|
import { gql } from 'graphql-tag';
|
||||||
|
|
||||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
|
||||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
|
||||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
|
||||||
import { ScalarsExplorerService } from 'src/engine/api/graphql/services/scalars-explorer.service';
|
import { ScalarsExplorerService } from 'src/engine/api/graphql/services/scalars-explorer.service';
|
||||||
import { WorkspaceGraphQLSchemaFactory } from 'src/engine/api/graphql/workspace-schema-builder/workspace-graphql-schema.factory';
|
|
||||||
import { workspaceResolverBuilderMethodNames } from 'src/engine/api/graphql/workspace-resolver-builder/factories/factories';
|
import { workspaceResolverBuilderMethodNames } from 'src/engine/api/graphql/workspace-resolver-builder/factories/factories';
|
||||||
import { WorkspaceResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/workspace-resolver.factory';
|
import { WorkspaceResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/workspace-resolver.factory';
|
||||||
|
import { WorkspaceGraphQLSchemaFactory } from 'src/engine/api/graphql/workspace-schema-builder/workspace-graphql-schema.factory';
|
||||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||||
|
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||||
|
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||||
|
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||||
|
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class WorkspaceSchemaFactory {
|
export class WorkspaceSchemaFactory {
|
||||||
@ -22,6 +23,7 @@ export class WorkspaceSchemaFactory {
|
|||||||
private readonly workspaceGraphQLSchemaFactory: WorkspaceGraphQLSchemaFactory,
|
private readonly workspaceGraphQLSchemaFactory: WorkspaceGraphQLSchemaFactory,
|
||||||
private readonly workspaceResolverFactory: WorkspaceResolverFactory,
|
private readonly workspaceResolverFactory: WorkspaceResolverFactory,
|
||||||
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
||||||
|
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async createGraphQLSchema(authContext: AuthContext): Promise<GraphQLSchema> {
|
async createGraphQLSchema(authContext: AuthContext): Promise<GraphQLSchema> {
|
||||||
@ -40,7 +42,7 @@ export class WorkspaceSchemaFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate cache version
|
// Validate cache version
|
||||||
await this.workspaceCacheStorageService.validateCacheVersion(
|
await this.workspaceMetadataVersionService.flushCacheIfMetadataVersionIsOutdated(
|
||||||
authContext.workspace.id,
|
authContext.workspace.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -64,11 +66,11 @@ export class WorkspaceSchemaFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get typeDefs from cache
|
// Get typeDefs from cache
|
||||||
let typeDefs = await this.workspaceCacheStorageService.getTypeDefs(
|
let typeDefs = await this.workspaceCacheStorageService.getGraphQLTypeDefs(
|
||||||
authContext.workspace.id,
|
authContext.workspace.id,
|
||||||
);
|
);
|
||||||
let usedScalarNames =
|
let usedScalarNames =
|
||||||
await this.workspaceCacheStorageService.getUsedScalarNames(
|
await this.workspaceCacheStorageService.getGraphQLUsedScalarNames(
|
||||||
authContext.workspace.id,
|
authContext.workspace.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -84,11 +86,11 @@ export class WorkspaceSchemaFactory {
|
|||||||
this.scalarsExplorerService.getUsedScalarNames(autoGeneratedSchema);
|
this.scalarsExplorerService.getUsedScalarNames(autoGeneratedSchema);
|
||||||
typeDefs = printSchema(autoGeneratedSchema);
|
typeDefs = printSchema(autoGeneratedSchema);
|
||||||
|
|
||||||
await this.workspaceCacheStorageService.setTypeDefs(
|
await this.workspaceCacheStorageService.setGraphQLTypeDefs(
|
||||||
authContext.workspace.id,
|
authContext.workspace.id,
|
||||||
typeDefs,
|
typeDefs,
|
||||||
);
|
);
|
||||||
await this.workspaceCacheStorageService.setUsedScalarNames(
|
await this.workspaceCacheStorageService.setGraphQLUsedScalarNames(
|
||||||
authContext.workspace.id,
|
authContext.workspace.id,
|
||||||
usedScalarNames,
|
usedScalarNames,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -21,7 +21,6 @@ import { TokenService } from 'src/engine/core-modules/auth/services/token.servic
|
|||||||
import { GoogleAPIsRequest } from 'src/engine/core-modules/auth/types/google-api-request.type';
|
import { GoogleAPIsRequest } from 'src/engine/core-modules/auth/types/google-api-request.type';
|
||||||
import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service';
|
import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service';
|
||||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||||
import { LoadServiceWithWorkspaceContext } from 'src/engine/twenty-orm/context/load-service-with-workspace.context';
|
|
||||||
|
|
||||||
@Controller('auth/google-apis')
|
@Controller('auth/google-apis')
|
||||||
@UseFilters(AuthRestApiExceptionFilter)
|
@UseFilters(AuthRestApiExceptionFilter)
|
||||||
@ -31,7 +30,6 @@ export class GoogleAPIsAuthController {
|
|||||||
private readonly tokenService: TokenService,
|
private readonly tokenService: TokenService,
|
||||||
private readonly environmentService: EnvironmentService,
|
private readonly environmentService: EnvironmentService,
|
||||||
private readonly onboardingService: OnboardingService,
|
private readonly onboardingService: OnboardingService,
|
||||||
private readonly loadServiceWithWorkspaceContext: LoadServiceWithWorkspaceContext,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
@ -80,13 +78,7 @@ export class GoogleAPIsAuthController {
|
|||||||
|
|
||||||
const handle = emails[0].value;
|
const handle = emails[0].value;
|
||||||
|
|
||||||
const googleAPIsServiceInstance =
|
await this.googleAPIsService.refreshGoogleRefreshToken({
|
||||||
await this.loadServiceWithWorkspaceContext.load(
|
|
||||||
this.googleAPIsService,
|
|
||||||
workspaceId,
|
|
||||||
);
|
|
||||||
|
|
||||||
await googleAPIsServiceInstance.refreshGoogleRefreshToken({
|
|
||||||
handle,
|
handle,
|
||||||
workspaceMemberId: workspaceMemberId,
|
workspaceMemberId: workspaceMemberId,
|
||||||
workspaceId: workspaceId,
|
workspaceId: workspaceId,
|
||||||
@ -97,13 +89,7 @@ export class GoogleAPIsAuthController {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (userId) {
|
if (userId) {
|
||||||
const onboardingServiceInstance =
|
await this.onboardingService.setOnboardingConnectAccountPending({
|
||||||
await this.loadServiceWithWorkspaceContext.load(
|
|
||||||
this.onboardingService,
|
|
||||||
workspaceId,
|
|
||||||
);
|
|
||||||
|
|
||||||
await onboardingServiceInstance.setOnboardingConnectAccountPending({
|
|
||||||
userId,
|
userId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
value: false,
|
value: false,
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decora
|
|||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||||
import {
|
import {
|
||||||
CalendarEventListFetchJob,
|
CalendarEventListFetchJob,
|
||||||
CalendarEventsImportJobData,
|
CalendarEventsImportJobData,
|
||||||
@ -39,7 +39,7 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class GoogleAPIsService {
|
export class GoogleAPIsService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly twentyORMManager: TwentyORMManager,
|
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||||
@InjectMessageQueue(MessageQueue.messagingQueue)
|
@InjectMessageQueue(MessageQueue.messagingQueue)
|
||||||
private readonly messageQueueService: MessageQueueService,
|
private readonly messageQueueService: MessageQueueService,
|
||||||
@InjectMessageQueue(MessageQueue.calendarQueue)
|
@InjectMessageQueue(MessageQueue.calendarQueue)
|
||||||
@ -82,16 +82,19 @@ export class GoogleAPIsService {
|
|||||||
const newOrExistingConnectedAccountId = existingAccountId ?? v4();
|
const newOrExistingConnectedAccountId = existingAccountId ?? v4();
|
||||||
|
|
||||||
const calendarChannelRepository =
|
const calendarChannelRepository =
|
||||||
await this.twentyORMManager.getRepository<CalendarChannelWorkspaceEntity>(
|
await this.twentyORMGlobalManager.getRepositoryForWorkspace<CalendarChannelWorkspaceEntity>(
|
||||||
|
workspaceId,
|
||||||
'calendarChannel',
|
'calendarChannel',
|
||||||
);
|
);
|
||||||
|
|
||||||
const messageChannelRepository =
|
const messageChannelRepository =
|
||||||
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
await this.twentyORMGlobalManager.getRepositoryForWorkspace<MessageChannelWorkspaceEntity>(
|
||||||
|
workspaceId,
|
||||||
'messageChannel',
|
'messageChannel',
|
||||||
);
|
);
|
||||||
|
|
||||||
const workspaceDataSource = await this.twentyORMManager.getDatasource();
|
const workspaceDataSource =
|
||||||
|
await this.twentyORMGlobalManager.getDataSourceForWorkspace(workspaceId);
|
||||||
|
|
||||||
await workspaceDataSource.transaction(async (manager: EntityManager) => {
|
await workspaceDataSource.transaction(async (manager: EntityManager) => {
|
||||||
if (!existingAccountId) {
|
if (!existingAccountId) {
|
||||||
@ -146,7 +149,8 @@ export class GoogleAPIsService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const workspaceMemberRepository =
|
const workspaceMemberRepository =
|
||||||
await this.twentyORMManager.getRepository<WorkspaceMemberWorkspaceEntity>(
|
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||||
|
workspaceId,
|
||||||
'workspaceMember',
|
'workspaceMember',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
import { PassportStrategy } from '@nestjs/passport';
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { PassportStrategy } from '@nestjs/passport';
|
||||||
|
|
||||||
import { Strategy, VerifyCallback } from 'passport-google-oauth20';
|
|
||||||
import { Request } from 'express';
|
import { Request } from 'express';
|
||||||
|
import { Strategy, VerifyCallback } from 'passport-google-oauth20';
|
||||||
|
|
||||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||||
|
|
||||||
export type GoogleRequest = Omit<
|
export type GoogleRequest = Omit<
|
||||||
Request,
|
Request,
|
||||||
'user' | 'workspace' | 'cacheVersion'
|
'user' | 'workspace' | 'workspaceMetadataVersion'
|
||||||
> & {
|
> & {
|
||||||
user: {
|
user: {
|
||||||
firstName?: string | null;
|
firstName?: string | null;
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { EnvironmentService } from 'src/engine/integrations/environment/environm
|
|||||||
|
|
||||||
export type MicrosoftRequest = Omit<
|
export type MicrosoftRequest = Omit<
|
||||||
Request,
|
Request,
|
||||||
'user' | 'workspace' | 'cacheVersion'
|
'user' | 'workspace' | 'workspaceMetadataVersion'
|
||||||
> & {
|
> & {
|
||||||
user: {
|
user: {
|
||||||
firstName?: string | null;
|
firstName?: string | null;
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { MessageChannelVisibility } from 'src/modules/messaging/common/standard-
|
|||||||
|
|
||||||
export type GoogleAPIsRequest = Omit<
|
export type GoogleAPIsRequest = Omit<
|
||||||
Request,
|
Request,
|
||||||
'user' | 'workspace' | 'cacheVersion'
|
'user' | 'workspace' | 'workspaceMetadataVersion'
|
||||||
> & {
|
> & {
|
||||||
user: {
|
user: {
|
||||||
firstName?: string | null;
|
firstName?: string | null;
|
||||||
|
|||||||
@ -44,6 +44,10 @@ export class FileController {
|
|||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
fileStream.on('error', () => {
|
||||||
|
res.status(500).send({ error: 'Internal server error' });
|
||||||
|
});
|
||||||
|
|
||||||
fileStream.pipe(res);
|
fileStream.pipe(res);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (
|
if (
|
||||||
|
|||||||
@ -119,13 +119,13 @@ export const useGraphQLErrorHandlerHook = <
|
|||||||
|
|
||||||
if (Array.isArray(errors) && errors.length > 0) {
|
if (Array.isArray(errors) && errors.length > 0) {
|
||||||
const headers = context.req.headers;
|
const headers = context.req.headers;
|
||||||
const currentSchemaVersion = context.req.cacheVersion;
|
const currentMetadataVersion = context.req.workspaceMetadataVersion;
|
||||||
|
|
||||||
const requestSchemaVersion = headers['x-schema-version'];
|
const requestMetadataVersion = headers['x-schema-version'];
|
||||||
|
|
||||||
if (
|
if (
|
||||||
requestSchemaVersion &&
|
requestMetadataVersion &&
|
||||||
requestSchemaVersion !== currentSchemaVersion
|
requestMetadataVersion !== `${currentMetadataVersion}`
|
||||||
) {
|
) {
|
||||||
throw new GraphQLError(
|
throw new GraphQLError(
|
||||||
`Schema version mismatch, please refresh the page.`,
|
`Schema version mismatch, please refresh the page.`,
|
||||||
|
|||||||
@ -33,7 +33,6 @@ import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorat
|
|||||||
import { DemoEnvGuard } from 'src/engine/guards/demo.env.guard';
|
import { DemoEnvGuard } from 'src/engine/guards/demo.env.guard';
|
||||||
import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard';
|
import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard';
|
||||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||||
import { LoadServiceWithWorkspaceContext } from 'src/engine/twenty-orm/context/load-service-with-workspace.context';
|
|
||||||
import { streamToBuffer } from 'src/utils/stream-to-buffer';
|
import { streamToBuffer } from 'src/utils/stream-to-buffer';
|
||||||
|
|
||||||
const getHMACKey = (email?: string, key?: string | null) => {
|
const getHMACKey = (email?: string, key?: string | null) => {
|
||||||
@ -54,7 +53,6 @@ export class UserResolver {
|
|||||||
private readonly environmentService: EnvironmentService,
|
private readonly environmentService: EnvironmentService,
|
||||||
private readonly fileUploadService: FileUploadService,
|
private readonly fileUploadService: FileUploadService,
|
||||||
private readonly onboardingService: OnboardingService,
|
private readonly onboardingService: OnboardingService,
|
||||||
private readonly loadServiceWithWorkspaceContext: LoadServiceWithWorkspaceContext,
|
|
||||||
private readonly userVarService: UserVarsService,
|
private readonly userVarService: UserVarsService,
|
||||||
private readonly fileService: FileService,
|
private readonly fileService: FileService,
|
||||||
) {}
|
) {}
|
||||||
@ -189,11 +187,6 @@ export class UserResolver {
|
|||||||
|
|
||||||
@ResolveField(() => OnboardingStatus)
|
@ResolveField(() => OnboardingStatus)
|
||||||
async onboardingStatus(@Parent() user: User): Promise<OnboardingStatus> {
|
async onboardingStatus(@Parent() user: User): Promise<OnboardingStatus> {
|
||||||
const contextInstance = await this.loadServiceWithWorkspaceContext.load(
|
return this.onboardingService.getOnboardingStatus(user);
|
||||||
this.onboardingService,
|
|
||||||
user.defaultWorkspaceId,
|
|
||||||
);
|
|
||||||
|
|
||||||
return contextInstance.getOnboardingStatus(user);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -117,4 +117,16 @@ export class Workspace {
|
|||||||
(postgresCredentials) => postgresCredentials.workspace,
|
(postgresCredentials) => postgresCredentials.workspace,
|
||||||
)
|
)
|
||||||
allPostgresCredentials: Relation<PostgresCredentials[]>;
|
allPostgresCredentials: Relation<PostgresCredentials[]>;
|
||||||
|
|
||||||
|
@Field()
|
||||||
|
@Column({ default: 1 })
|
||||||
|
metadataVersion: number;
|
||||||
|
|
||||||
|
@Field()
|
||||||
|
@Column({ default: '' })
|
||||||
|
databaseUrl: string;
|
||||||
|
|
||||||
|
@Field()
|
||||||
|
@Column({ default: '' })
|
||||||
|
databaseSchema: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import { User } from 'src/engine/core-modules/user/user.entity';
|
|||||||
import { WorkspaceWorkspaceMemberListener } from 'src/engine/core-modules/workspace/workspace-workspace-member.listener';
|
import { WorkspaceWorkspaceMemberListener } from 'src/engine/core-modules/workspace/workspace-workspace-member.listener';
|
||||||
import { WorkspaceResolver } from 'src/engine/core-modules/workspace/workspace.resolver';
|
import { WorkspaceResolver } from 'src/engine/core-modules/workspace/workspace.resolver';
|
||||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||||
import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module';
|
import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module';
|
||||||
|
|
||||||
import { workspaceAutoResolverOpts } from './workspace.auto-resolver-opts';
|
import { workspaceAutoResolverOpts } from './workspace.auto-resolver-opts';
|
||||||
@ -32,7 +32,7 @@ import { WorkspaceService } from './services/workspace.service';
|
|||||||
BillingModule,
|
BillingModule,
|
||||||
FileModule,
|
FileModule,
|
||||||
FileUploadModule,
|
FileUploadModule,
|
||||||
WorkspaceCacheVersionModule,
|
WorkspaceMetadataVersionModule,
|
||||||
NestjsQueryTypeOrmModule.forFeature(
|
NestjsQueryTypeOrmModule.forFeature(
|
||||||
[User, Workspace, UserWorkspace, FeatureFlagEntity],
|
[User, Workspace, UserWorkspace, FeatureFlagEntity],
|
||||||
'core',
|
'core',
|
||||||
|
|||||||
@ -26,7 +26,7 @@ import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator';
|
|||||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||||
import { DemoEnvGuard } from 'src/engine/guards/demo.env.guard';
|
import { DemoEnvGuard } from 'src/engine/guards/demo.env.guard';
|
||||||
import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard';
|
import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard';
|
||||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||||
import { assert } from 'src/utils/assert';
|
import { assert } from 'src/utils/assert';
|
||||||
import { streamToBuffer } from 'src/utils/stream-to-buffer';
|
import { streamToBuffer } from 'src/utils/stream-to-buffer';
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ import { WorkspaceService } from './services/workspace.service';
|
|||||||
export class WorkspaceResolver {
|
export class WorkspaceResolver {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workspaceService: WorkspaceService,
|
private readonly workspaceService: WorkspaceService,
|
||||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||||
private readonly userWorkspaceService: UserWorkspaceService,
|
private readonly userWorkspaceService: UserWorkspaceService,
|
||||||
private readonly fileUploadService: FileUploadService,
|
private readonly fileUploadService: FileUploadService,
|
||||||
private readonly fileService: FileService,
|
private readonly fileService: FileService,
|
||||||
@ -107,13 +107,6 @@ export class WorkspaceResolver {
|
|||||||
return this.workspaceService.deleteWorkspace(id);
|
return this.workspaceService.deleteWorkspace(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ResolveField(() => String, { nullable: true })
|
|
||||||
async currentCacheVersion(
|
|
||||||
@Parent() workspace: Workspace,
|
|
||||||
): Promise<string | null> {
|
|
||||||
return this.workspaceCacheVersionService.getVersion(workspace.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResolveField(() => BillingSubscription, { nullable: true })
|
@ResolveField(() => BillingSubscription, { nullable: true })
|
||||||
async currentBillingSubscription(
|
async currentBillingSubscription(
|
||||||
@Parent() workspace: Workspace,
|
@Parent() workspace: Workspace,
|
||||||
@ -133,11 +126,15 @@ export class WorkspaceResolver {
|
|||||||
@ResolveField(() => String)
|
@ResolveField(() => String)
|
||||||
async logo(@Parent() workspace: Workspace): Promise<string> {
|
async logo(@Parent() workspace: Workspace): Promise<string> {
|
||||||
if (workspace.logo) {
|
if (workspace.logo) {
|
||||||
const workspaceLogoToken = await this.fileService.encodeFileToken({
|
try {
|
||||||
workspace_id: workspace.id,
|
const workspaceLogoToken = await this.fileService.encodeFileToken({
|
||||||
});
|
workspace_id: workspace.id,
|
||||||
|
});
|
||||||
|
|
||||||
return `${workspace.logo}?token=${workspaceLogoToken}`;
|
return `${workspace.logo}?token=${workspaceLogoToken}`;
|
||||||
|
} catch (e) {
|
||||||
|
return workspace.logo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return workspace.logo ?? '';
|
return workspace.logo ?? '';
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
export enum CacheStorageNamespace {
|
export enum CacheStorageNamespace {
|
||||||
Messaging = 'messaging',
|
ModuleMessaging = 'module:messaging',
|
||||||
Calendar = 'calendar',
|
ModuleCalendar = 'module:calendar',
|
||||||
WorkspaceSchema = 'workspaceSchema',
|
EngineWorkspace = 'engine:workspace',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,15 +13,15 @@ import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-s
|
|||||||
import { FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
|
import { FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
|
||||||
import { FieldMetadataResolver } from 'src/engine/metadata-modules/field-metadata/field-metadata.resolver';
|
import { FieldMetadataResolver } from 'src/engine/metadata-modules/field-metadata/field-metadata.resolver';
|
||||||
import { FieldMetadataGraphqlApiExceptionInterceptor } from 'src/engine/metadata-modules/field-metadata/interceptors/field-metadata-graphql-api-exception.interceptor';
|
import { FieldMetadataGraphqlApiExceptionInterceptor } from 'src/engine/metadata-modules/field-metadata/interceptors/field-metadata-graphql-api-exception.interceptor';
|
||||||
|
import { CreatedByPreQueryHook } from 'src/engine/metadata-modules/field-metadata/query-hooks/created-by.pre-query-hook';
|
||||||
import { IsFieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/validators/is-field-metadata-default-value.validator';
|
import { IsFieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/validators/is-field-metadata-default-value.validator';
|
||||||
import { IsFieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/validators/is-field-metadata-options.validator';
|
import { IsFieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/validators/is-field-metadata-options.validator';
|
||||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||||
import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
|
import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
|
||||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||||
import { WorkspaceStatusModule } from 'src/engine/workspace-manager/workspace-status/workspace-manager.module';
|
import { WorkspaceStatusModule } from 'src/engine/workspace-manager/workspace-status/workspace-manager.module';
|
||||||
import { CreatedByPreQueryHook } from 'src/engine/metadata-modules/field-metadata/query-hooks/created-by.pre-query-hook';
|
|
||||||
|
|
||||||
import { FieldMetadataEntity } from './field-metadata.entity';
|
import { FieldMetadataEntity } from './field-metadata.entity';
|
||||||
import { FieldMetadataService } from './field-metadata.service';
|
import { FieldMetadataService } from './field-metadata.service';
|
||||||
@ -38,7 +38,7 @@ import { UpdateFieldInput } from './dtos/update-field.input';
|
|||||||
WorkspaceStatusModule,
|
WorkspaceStatusModule,
|
||||||
TwentyORMModule,
|
TwentyORMModule,
|
||||||
WorkspaceMigrationRunnerModule,
|
WorkspaceMigrationRunnerModule,
|
||||||
WorkspaceCacheVersionModule,
|
WorkspaceMetadataVersionModule,
|
||||||
ObjectMetadataModule,
|
ObjectMetadataModule,
|
||||||
DataSourceModule,
|
DataSourceModule,
|
||||||
TypeORMModule,
|
TypeORMModule,
|
||||||
|
|||||||
@ -40,7 +40,7 @@ import {
|
|||||||
NameTooLongException,
|
NameTooLongException,
|
||||||
validateMetadataNameOrThrow,
|
validateMetadataNameOrThrow,
|
||||||
} from 'src/engine/metadata-modules/utils/validate-metadata-name.utils';
|
} from 'src/engine/metadata-modules/utils/validate-metadata-name.utils';
|
||||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||||
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
||||||
import {
|
import {
|
||||||
WorkspaceMigrationColumnActionType,
|
WorkspaceMigrationColumnActionType,
|
||||||
@ -76,7 +76,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||||
private readonly dataSourceService: DataSourceService,
|
private readonly dataSourceService: DataSourceService,
|
||||||
private readonly typeORMService: TypeORMService,
|
private readonly typeORMService: TypeORMService,
|
||||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||||
) {
|
) {
|
||||||
super(fieldMetadataRepository);
|
super(fieldMetadataRepository);
|
||||||
}
|
}
|
||||||
@ -274,7 +274,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
await queryRunner.release();
|
await queryRunner.release();
|
||||||
await this.workspaceCacheVersionService.incrementVersion(
|
await this.workspaceMetadataVersionService.getMetadataVersion(
|
||||||
fieldMetadataInput.workspaceId,
|
fieldMetadataInput.workspaceId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -426,7 +426,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
await queryRunner.release();
|
await queryRunner.release();
|
||||||
await this.workspaceCacheVersionService.incrementVersion(
|
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||||
fieldMetadataInput.workspaceId,
|
fieldMetadataInput.workspaceId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -545,7 +545,9 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||||||
throw error;
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
await queryRunner.release();
|
await queryRunner.release();
|
||||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,7 +588,9 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
|||||||
|
|
||||||
public async deleteFieldsMetadata(workspaceId: string) {
|
public async deleteFieldsMetadata(workspaceId: string) {
|
||||||
await this.fieldMetadataRepository.delete({ workspaceId });
|
await this.fieldMetadataRepository.delete({ workspaceId });
|
||||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private buildUpdatableStandardFieldInput(
|
private buildUpdatableStandardFieldInput(
|
||||||
|
|||||||
@ -5,9 +5,9 @@ import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/
|
|||||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||||
import { RelationMetadataModule } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.module';
|
import { RelationMetadataModule } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.module';
|
||||||
import { RemoteServerModule } from 'src/engine/metadata-modules/remote-server/remote-server.module';
|
import { RemoteServerModule } from 'src/engine/metadata-modules/remote-server/remote-server.module';
|
||||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
|
||||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
|
||||||
import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module';
|
import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module';
|
||||||
|
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||||
|
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@ -16,7 +16,7 @@ import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless
|
|||||||
ObjectMetadataModule,
|
ObjectMetadataModule,
|
||||||
RelationMetadataModule,
|
RelationMetadataModule,
|
||||||
ServerlessFunctionModule,
|
ServerlessFunctionModule,
|
||||||
WorkspaceCacheVersionModule,
|
WorkspaceMetadataVersionModule,
|
||||||
WorkspaceMigrationModule,
|
WorkspaceMigrationModule,
|
||||||
RemoteServerModule,
|
RemoteServerModule,
|
||||||
],
|
],
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import { ObjectMetadataGraphqlApiExceptionInterceptor } from 'src/engine/metadat
|
|||||||
import { ObjectMetadataResolver } from 'src/engine/metadata-modules/object-metadata/object-metadata.resolver';
|
import { ObjectMetadataResolver } from 'src/engine/metadata-modules/object-metadata/object-metadata.resolver';
|
||||||
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||||
import { RemoteTableRelationsModule } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table-relations/remote-table-relations.module';
|
import { RemoteTableRelationsModule } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table-relations/remote-table-relations.module';
|
||||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ import { UpdateObjectPayload } from './dtos/update-object.input';
|
|||||||
DataSourceModule,
|
DataSourceModule,
|
||||||
WorkspaceMigrationModule,
|
WorkspaceMigrationModule,
|
||||||
WorkspaceMigrationRunnerModule,
|
WorkspaceMigrationRunnerModule,
|
||||||
WorkspaceCacheVersionModule,
|
WorkspaceMetadataVersionModule,
|
||||||
FeatureFlagModule,
|
FeatureFlagModule,
|
||||||
RemoteTableRelationsModule,
|
RemoteTableRelationsModule,
|
||||||
],
|
],
|
||||||
|
|||||||
@ -32,7 +32,7 @@ import {
|
|||||||
import { RelationToDelete } from 'src/engine/metadata-modules/relation-metadata/types/relation-to-delete';
|
import { RelationToDelete } from 'src/engine/metadata-modules/relation-metadata/types/relation-to-delete';
|
||||||
import { RemoteTableRelationsService } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table-relations/remote-table-relations.service';
|
import { RemoteTableRelationsService } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table-relations/remote-table-relations.service';
|
||||||
import { mapUdtNameToFieldType } from 'src/engine/metadata-modules/remote-server/remote-table/utils/udt-name-mapper.util';
|
import { mapUdtNameToFieldType } from 'src/engine/metadata-modules/remote-server/remote-table/utils/udt-name-mapper.util';
|
||||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||||
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
||||||
import {
|
import {
|
||||||
WorkspaceMigrationColumnActionType,
|
WorkspaceMigrationColumnActionType,
|
||||||
@ -80,7 +80,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
|||||||
private readonly typeORMService: TypeORMService,
|
private readonly typeORMService: TypeORMService,
|
||||||
private readonly workspaceMigrationService: WorkspaceMigrationService,
|
private readonly workspaceMigrationService: WorkspaceMigrationService,
|
||||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||||
) {
|
) {
|
||||||
super(objectMetadataRepository);
|
super(objectMetadataRepository);
|
||||||
}
|
}
|
||||||
@ -144,7 +144,9 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
|||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
return objectMetadata;
|
return objectMetadata;
|
||||||
}
|
}
|
||||||
@ -352,7 +354,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.workspaceCacheVersionService.incrementVersion(
|
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||||
objectMetadataInput.workspaceId,
|
objectMetadataInput.workspaceId,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -367,7 +369,9 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
|||||||
|
|
||||||
const updatedObject = await super.updateOne(input.id, input.update);
|
const updatedObject = await super.updateOne(input.id, input.update);
|
||||||
|
|
||||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
return updatedObject;
|
return updatedObject;
|
||||||
}
|
}
|
||||||
@ -452,7 +456,9 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
|||||||
|
|
||||||
public async deleteObjectsMetadata(workspaceId: string) {
|
public async deleteObjectsMetadata(workspaceId: string) {
|
||||||
await this.objectMetadataRepository.delete({ workspaceId });
|
await this.objectMetadataRepository.delete({ workspaceId });
|
||||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createObjectRelationsMetadataAndMigrations(
|
private async createObjectRelationsMetadataAndMigrations(
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/
|
|||||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||||
import { RelationMetadataGraphqlApiExceptionInterceptor } from 'src/engine/metadata-modules/relation-metadata/interceptors/relation-metadata-graphql-api-exception.interceptor';
|
import { RelationMetadataGraphqlApiExceptionInterceptor } from 'src/engine/metadata-modules/relation-metadata/interceptors/relation-metadata-graphql-api-exception.interceptor';
|
||||||
import { RelationMetadataResolver } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.resolver';
|
import { RelationMetadataResolver } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.resolver';
|
||||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ import { RelationMetadataDTO } from './dtos/relation-metadata.dto';
|
|||||||
FieldMetadataModule,
|
FieldMetadataModule,
|
||||||
WorkspaceMigrationRunnerModule,
|
WorkspaceMigrationRunnerModule,
|
||||||
WorkspaceMigrationModule,
|
WorkspaceMigrationModule,
|
||||||
WorkspaceCacheVersionModule,
|
WorkspaceMetadataVersionModule,
|
||||||
],
|
],
|
||||||
services: [RelationMetadataService],
|
services: [RelationMetadataService],
|
||||||
resolvers: [
|
resolvers: [
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import {
|
|||||||
InvalidStringException,
|
InvalidStringException,
|
||||||
validateMetadataNameOrThrow,
|
validateMetadataNameOrThrow,
|
||||||
} from 'src/engine/metadata-modules/utils/validate-metadata-name.utils';
|
} from 'src/engine/metadata-modules/utils/validate-metadata-name.utils';
|
||||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||||
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
||||||
import {
|
import {
|
||||||
WorkspaceMigrationColumnActionType,
|
WorkspaceMigrationColumnActionType,
|
||||||
@ -50,7 +50,7 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
|
|||||||
private readonly fieldMetadataService: FieldMetadataService,
|
private readonly fieldMetadataService: FieldMetadataService,
|
||||||
private readonly workspaceMigrationService: WorkspaceMigrationService,
|
private readonly workspaceMigrationService: WorkspaceMigrationService,
|
||||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||||
) {
|
) {
|
||||||
super(relationMetadataRepository);
|
super(relationMetadataRepository);
|
||||||
}
|
}
|
||||||
@ -120,7 +120,7 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
|
|||||||
relationMetadataInput.workspaceId,
|
relationMetadataInput.workspaceId,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.workspaceCacheVersionService.incrementVersion(
|
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||||
relationMetadataInput.workspaceId,
|
relationMetadataInput.workspaceId,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -394,7 +394,9 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
|
|||||||
relationMetadata.workspaceId,
|
relationMetadata.workspaceId,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
// TODO: Return id for delete endpoints
|
// TODO: Return id for delete endpoints
|
||||||
return relationMetadata;
|
return relationMetadata;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { ForeignTableService } from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/foreign-table.service';
|
import { ForeignTableService } from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/foreign-table.service';
|
||||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||||
@ -11,7 +11,7 @@ import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/wor
|
|||||||
WorkspaceMigrationModule,
|
WorkspaceMigrationModule,
|
||||||
WorkspaceMigrationRunnerModule,
|
WorkspaceMigrationRunnerModule,
|
||||||
WorkspaceDataSourceModule,
|
WorkspaceDataSourceModule,
|
||||||
WorkspaceCacheVersionModule,
|
WorkspaceMetadataVersionModule,
|
||||||
],
|
],
|
||||||
providers: [ForeignTableService],
|
providers: [ForeignTableService],
|
||||||
exports: [ForeignTableService],
|
exports: [ForeignTableService],
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import {
|
|||||||
} from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/foreign-table.exception';
|
} from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/foreign-table.exception';
|
||||||
import { getForeignTableColumnName } from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/utils/get-foreign-table-column-name.util';
|
import { getForeignTableColumnName } from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/utils/get-foreign-table-column-name.util';
|
||||||
import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/types/postgres-table-schema-column';
|
import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/types/postgres-table-schema-column';
|
||||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||||
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
||||||
import {
|
import {
|
||||||
ReferencedTable,
|
ReferencedTable,
|
||||||
@ -30,7 +30,7 @@ export class ForeignTableService {
|
|||||||
private readonly workspaceMigrationService: WorkspaceMigrationService,
|
private readonly workspaceMigrationService: WorkspaceMigrationService,
|
||||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async fetchForeignTableNamesWithinWorkspace(
|
public async fetchForeignTableNamesWithinWorkspace(
|
||||||
@ -127,7 +127,9 @@ export class ForeignTableService {
|
|||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: foreignTableName,
|
name: foreignTableName,
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { RemoteTableSchemaUpdateModule } from 'src/engine/metadata-modules/remot
|
|||||||
import { RemoteTableEntity } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.entity';
|
import { RemoteTableEntity } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.entity';
|
||||||
import { RemoteTableResolver } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.resolver';
|
import { RemoteTableResolver } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.resolver';
|
||||||
import { RemoteTableService } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.service';
|
import { RemoteTableService } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.service';
|
||||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
@ -24,7 +24,7 @@ import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/works
|
|||||||
DataSourceModule,
|
DataSourceModule,
|
||||||
ObjectMetadataModule,
|
ObjectMetadataModule,
|
||||||
FieldMetadataModule,
|
FieldMetadataModule,
|
||||||
WorkspaceCacheVersionModule,
|
WorkspaceMetadataVersionModule,
|
||||||
WorkspaceDataSourceModule,
|
WorkspaceDataSourceModule,
|
||||||
ForeignTableModule,
|
ForeignTableModule,
|
||||||
RemoteTableSchemaUpdateModule,
|
RemoteTableSchemaUpdateModule,
|
||||||
|
|||||||
@ -1,49 +1,49 @@
|
|||||||
import { Logger } from '@nestjs/common';
|
import { Logger } from '@nestjs/common';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
|
||||||
import { Repository } from 'typeorm';
|
|
||||||
import { plural } from 'pluralize';
|
|
||||||
import isEmpty from 'lodash.isempty';
|
import isEmpty from 'lodash.isempty';
|
||||||
|
import { plural } from 'pluralize';
|
||||||
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
|
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||||
|
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||||
|
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||||
|
import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service';
|
||||||
|
import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input';
|
||||||
|
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||||
import {
|
import {
|
||||||
RemoteServerType,
|
|
||||||
RemoteServerEntity,
|
RemoteServerEntity,
|
||||||
|
RemoteServerType,
|
||||||
} from 'src/engine/metadata-modules/remote-server/remote-server.entity';
|
} from 'src/engine/metadata-modules/remote-server/remote-server.entity';
|
||||||
|
import { DistantTableService } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/distant-table.service';
|
||||||
|
import { sortDistantTables } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/utils/sort-distant-tables.util';
|
||||||
|
import { RemoteTableInput } from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table-input';
|
||||||
import {
|
import {
|
||||||
DistantTableUpdate,
|
DistantTableUpdate,
|
||||||
RemoteTableStatus,
|
RemoteTableStatus,
|
||||||
} from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto';
|
} from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto';
|
||||||
import {
|
|
||||||
mapUdtNameToFieldSettings,
|
|
||||||
mapUdtNameToFieldType,
|
|
||||||
} from 'src/engine/metadata-modules/remote-server/remote-table/utils/udt-name-mapper.util';
|
|
||||||
import { RemoteTableInput } from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table-input';
|
|
||||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
|
||||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
|
||||||
import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input';
|
|
||||||
import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service';
|
|
||||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
|
||||||
import { camelCase } from 'src/utils/camel-case';
|
|
||||||
import { camelToTitleCase } from 'src/utils/camel-to-title-case';
|
|
||||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
|
||||||
import { RemoteTableEntity } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.entity';
|
|
||||||
import { getRemoteTableLocalName } from 'src/engine/metadata-modules/remote-server/remote-table/utils/get-remote-table-local-name.util';
|
|
||||||
import { DistantTableService } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/distant-table.service';
|
|
||||||
import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/types/postgres-table-schema-column';
|
|
||||||
import { fetchTableColumns } from 'src/engine/metadata-modules/remote-server/remote-table/utils/fetch-table-columns.util';
|
|
||||||
import { ForeignTableService } from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/foreign-table.service';
|
import { ForeignTableService } from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/foreign-table.service';
|
||||||
import { RemoteTableSchemaUpdateService } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table-schema-update/remote-table-schema-update.service';
|
import { RemoteTableSchemaUpdateService } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table-schema-update/remote-table-schema-update.service';
|
||||||
import { sortDistantTables } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/utils/sort-distant-tables.util';
|
import { RemoteTableEntity } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.entity';
|
||||||
import {
|
|
||||||
WorkspaceMigrationColumnAction,
|
|
||||||
WorkspaceMigrationColumnActionType,
|
|
||||||
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
|
||||||
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
|
||||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
|
||||||
import {
|
import {
|
||||||
RemoteTableException,
|
RemoteTableException,
|
||||||
RemoteTableExceptionCode,
|
RemoteTableExceptionCode,
|
||||||
} from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.exception';
|
} from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.exception';
|
||||||
|
import { fetchTableColumns } from 'src/engine/metadata-modules/remote-server/remote-table/utils/fetch-table-columns.util';
|
||||||
|
import { getRemoteTableLocalName } from 'src/engine/metadata-modules/remote-server/remote-table/utils/get-remote-table-local-name.util';
|
||||||
|
import {
|
||||||
|
mapUdtNameToFieldSettings,
|
||||||
|
mapUdtNameToFieldType,
|
||||||
|
} from 'src/engine/metadata-modules/remote-server/remote-table/utils/udt-name-mapper.util';
|
||||||
|
import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/types/postgres-table-schema-column';
|
||||||
|
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||||
|
import {
|
||||||
|
WorkspaceMigrationColumnAction,
|
||||||
|
WorkspaceMigrationColumnActionType,
|
||||||
|
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||||
|
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||||
|
import { camelCase } from 'src/utils/camel-case';
|
||||||
|
import { camelToTitleCase } from 'src/utils/camel-to-title-case';
|
||||||
|
|
||||||
export class RemoteTableService {
|
export class RemoteTableService {
|
||||||
private readonly logger = new Logger(RemoteTableService.name);
|
private readonly logger = new Logger(RemoteTableService.name);
|
||||||
@ -55,7 +55,7 @@ export class RemoteTableService {
|
|||||||
private readonly remoteServerRepository: Repository<
|
private readonly remoteServerRepository: Repository<
|
||||||
RemoteServerEntity<RemoteServerType>
|
RemoteServerEntity<RemoteServerType>
|
||||||
>,
|
>,
|
||||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||||
private readonly dataSourceService: DataSourceService,
|
private readonly dataSourceService: DataSourceService,
|
||||||
private readonly objectMetadataService: ObjectMetadataService,
|
private readonly objectMetadataService: ObjectMetadataService,
|
||||||
private readonly fieldMetadataService: FieldMetadataService,
|
private readonly fieldMetadataService: FieldMetadataService,
|
||||||
@ -250,7 +250,9 @@ export class RemoteTableService {
|
|||||||
|
|
||||||
await this.remoteTableRepository.save(remoteTableEntity);
|
await this.remoteTableRepository.save(remoteTableEntity);
|
||||||
|
|
||||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: remoteTableEntity.id,
|
id: remoteTableEntity.id,
|
||||||
@ -435,7 +437,9 @@ export class RemoteTableService {
|
|||||||
|
|
||||||
await this.remoteTableRepository.delete(remoteTable.id);
|
await this.remoteTableRepository.delete(remoteTable.id);
|
||||||
|
|
||||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createRemoteTableMetadata(
|
private async createRemoteTableMetadata(
|
||||||
|
|||||||
@ -1,25 +0,0 @@
|
|||||||
import {
|
|
||||||
Column,
|
|
||||||
CreateDateColumn,
|
|
||||||
Entity,
|
|
||||||
PrimaryGeneratedColumn,
|
|
||||||
UpdateDateColumn,
|
|
||||||
} from 'typeorm';
|
|
||||||
|
|
||||||
@Entity('workspaceCacheVersion')
|
|
||||||
export class WorkspaceCacheVersionEntity {
|
|
||||||
@PrimaryGeneratedColumn('uuid')
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
@Column({ unique: true, nullable: false, type: 'uuid' })
|
|
||||||
workspaceId: string;
|
|
||||||
|
|
||||||
@Column()
|
|
||||||
version: string;
|
|
||||||
|
|
||||||
@CreateDateColumn({ type: 'timestamptz' })
|
|
||||||
createdAt: Date;
|
|
||||||
|
|
||||||
@UpdateDateColumn({ type: 'timestamptz' })
|
|
||||||
updatedAt: Date;
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
||||||
|
|
||||||
import { WorkspaceCacheVersionEntity } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.entity';
|
|
||||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [
|
|
||||||
TypeOrmModule.forFeature([WorkspaceCacheVersionEntity], 'metadata'),
|
|
||||||
],
|
|
||||||
exports: [WorkspaceCacheVersionService],
|
|
||||||
providers: [WorkspaceCacheVersionService],
|
|
||||||
})
|
|
||||||
export class WorkspaceCacheVersionModule {}
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
|
||||||
|
|
||||||
import { Repository } from 'typeorm';
|
|
||||||
|
|
||||||
import { WorkspaceCacheVersionEntity } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.entity';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class WorkspaceCacheVersionService {
|
|
||||||
constructor(
|
|
||||||
@InjectRepository(WorkspaceCacheVersionEntity, 'metadata')
|
|
||||||
private readonly workspaceCacheVersionRepository: Repository<WorkspaceCacheVersionEntity>,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async incrementVersion(workspaceId: string): Promise<string> {
|
|
||||||
const workspaceCacheVersion = (await this.getVersion(workspaceId)) ?? '0';
|
|
||||||
const newVersion = `${+workspaceCacheVersion + 1}`;
|
|
||||||
|
|
||||||
await this.workspaceCacheVersionRepository.upsert(
|
|
||||||
{
|
|
||||||
workspaceId,
|
|
||||||
version: `${+workspaceCacheVersion + 1}`,
|
|
||||||
},
|
|
||||||
['workspaceId'],
|
|
||||||
);
|
|
||||||
|
|
||||||
return newVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getVersion(workspaceId: string): Promise<string | null> {
|
|
||||||
const workspaceCacheVersion =
|
|
||||||
await this.workspaceCacheVersionRepository.findOne({
|
|
||||||
where: { workspaceId },
|
|
||||||
});
|
|
||||||
|
|
||||||
return workspaceCacheVersion?.version ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteVersion(workspaceId: string): Promise<void> {
|
|
||||||
await this.workspaceCacheVersionRepository.delete({ workspaceId });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
|
||||||
|
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
|
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||||
|
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
TypeOrmModule.forFeature([Workspace], 'core'),
|
||||||
|
WorkspaceCacheStorageModule,
|
||||||
|
],
|
||||||
|
exports: [WorkspaceMetadataVersionService],
|
||||||
|
providers: [WorkspaceMetadataVersionService],
|
||||||
|
})
|
||||||
|
export class WorkspaceMetadataVersionModule {}
|
||||||
@ -0,0 +1,79 @@
|
|||||||
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
|
||||||
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
|
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
|
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class WorkspaceMetadataVersionService {
|
||||||
|
logger = new Logger(WorkspaceMetadataVersionService.name);
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(Workspace, 'core')
|
||||||
|
private readonly workspaceRepository: Repository<Workspace>,
|
||||||
|
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async flushCacheIfMetadataVersionIsOutdated(
|
||||||
|
workspaceId: string,
|
||||||
|
): Promise<void> {
|
||||||
|
const currentVersion =
|
||||||
|
(await this.workspaceCacheStorageService.getMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
)) ?? 1;
|
||||||
|
|
||||||
|
let latestVersion = await this.getMetadataVersion(workspaceId);
|
||||||
|
|
||||||
|
if (latestVersion === undefined || currentVersion !== latestVersion) {
|
||||||
|
this.logger.log(
|
||||||
|
`Metadata version mismatch detected for workspace ${workspaceId}. Current version: ${currentVersion}. Latest version: ${latestVersion}. Invalidating cache...`,
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.workspaceCacheStorageService.flush(workspaceId);
|
||||||
|
|
||||||
|
latestVersion = await this.incrementMetadataVersion(workspaceId);
|
||||||
|
|
||||||
|
await this.workspaceCacheStorageService.setMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
latestVersion,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async incrementMetadataVersion(workspaceId: string): Promise<number> {
|
||||||
|
const metadataVersion = (await this.getMetadataVersion(workspaceId)) ?? 0;
|
||||||
|
const newMetadataVersion = metadataVersion + 1;
|
||||||
|
|
||||||
|
await this.workspaceRepository.update(
|
||||||
|
{ id: workspaceId },
|
||||||
|
{ metadataVersion: newMetadataVersion },
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.workspaceCacheStorageService.setMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
newMetadataVersion,
|
||||||
|
);
|
||||||
|
|
||||||
|
return newMetadataVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getMetadataVersion(workspaceId: string): Promise<number | undefined> {
|
||||||
|
const workspace = await this.workspaceRepository.findOne({
|
||||||
|
where: { id: workspaceId },
|
||||||
|
});
|
||||||
|
|
||||||
|
return workspace?.metadataVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
async resetMetadataVersion(workspaceId: string): Promise<void> {
|
||||||
|
await this.workspaceRepository.update(
|
||||||
|
{ id: workspaceId },
|
||||||
|
{ metadataVersion: 1 },
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.workspaceCacheStorageService.flush(workspaceId);
|
||||||
|
await this.workspaceCacheStorageService.setMetadataVersion(workspaceId, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,7 +6,7 @@ import { AuthGraphqlApiExceptionFilter } from 'src/engine/core-modules/auth/filt
|
|||||||
import { TokenService } from 'src/engine/core-modules/auth/services/token.service';
|
import { TokenService } from 'src/engine/core-modules/auth/services/token.service';
|
||||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||||
import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service';
|
import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service';
|
||||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||||
import { handleExceptionAndConvertToGraphQLError } from 'src/engine/utils/global-exception-handler.util';
|
import { handleExceptionAndConvertToGraphQLError } from 'src/engine/utils/global-exception-handler.util';
|
||||||
|
|
||||||
class GraphqlTokenValidationProxy {
|
class GraphqlTokenValidationProxy {
|
||||||
@ -33,7 +33,7 @@ export class GraphQLHydrateRequestFromTokenMiddleware
|
|||||||
{
|
{
|
||||||
constructor(
|
constructor(
|
||||||
private readonly tokenService: TokenService,
|
private readonly tokenService: TokenService,
|
||||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||||
private readonly exceptionHandlerService: ExceptionHandlerService,
|
private readonly exceptionHandlerService: ExceptionHandlerService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@ -72,15 +72,16 @@ export class GraphQLHydrateRequestFromTokenMiddleware
|
|||||||
);
|
);
|
||||||
|
|
||||||
data = await graphqlTokenValidationProxy.validateToken(req);
|
data = await graphqlTokenValidationProxy.validateToken(req);
|
||||||
const cacheVersion = await this.workspaceCacheVersionService.getVersion(
|
const metadataVersion =
|
||||||
data.workspace.id,
|
await this.workspaceMetadataVersionService.getMetadataVersion(
|
||||||
);
|
data.workspace.id,
|
||||||
|
);
|
||||||
|
|
||||||
req.user = data.user;
|
req.user = data.user;
|
||||||
req.apiKey = data.apiKey;
|
req.apiKey = data.apiKey;
|
||||||
req.workspace = data.workspace;
|
req.workspace = data.workspace;
|
||||||
req.workspaceId = data.workspace.id;
|
req.workspaceId = data.workspace.id;
|
||||||
req.cacheVersion = cacheVersion;
|
req.workspaceMetadataVersion = metadataVersion;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||||
res.write(
|
res.write(
|
||||||
|
|||||||
@ -1,44 +0,0 @@
|
|||||||
import { Inject, Type } from '@nestjs/common';
|
|
||||||
import { ModuleRef, createContextId } from '@nestjs/core';
|
|
||||||
import { Injector } from '@nestjs/core/injector/injector';
|
|
||||||
|
|
||||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
|
||||||
|
|
||||||
export class LoadServiceWithWorkspaceContext {
|
|
||||||
private readonly injector = new Injector();
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
@Inject(ModuleRef)
|
|
||||||
private readonly moduleRef: ModuleRef,
|
|
||||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async load<T>(service: T, workspaceId: string): Promise<T> {
|
|
||||||
const modules = this.moduleRef['container'].getModules();
|
|
||||||
const host = [...modules.values()].find((module) =>
|
|
||||||
module.providers.has((service as Type<T>).constructor),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!host) {
|
|
||||||
throw new Error('Host module not found for the service');
|
|
||||||
}
|
|
||||||
|
|
||||||
const contextId = createContextId();
|
|
||||||
const cacheVersion =
|
|
||||||
await this.workspaceCacheVersionService.getVersion(workspaceId);
|
|
||||||
|
|
||||||
if (this.moduleRef.registerRequestByContextId) {
|
|
||||||
this.moduleRef.registerRequestByContextId(
|
|
||||||
{ req: { workspaceId, cacheVersion } },
|
|
||||||
contextId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.injector.loadPerContext(
|
|
||||||
service,
|
|
||||||
host,
|
|
||||||
new Map(host.providers),
|
|
||||||
contextId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -11,16 +11,16 @@ export class ScopedWorkspaceContextFactory {
|
|||||||
|
|
||||||
public create(): {
|
public create(): {
|
||||||
workspaceId: string | null;
|
workspaceId: string | null;
|
||||||
cacheVersion: string | null;
|
workspaceMetadataVersion: string | null;
|
||||||
} {
|
} {
|
||||||
const workspaceId: string | undefined =
|
const workspaceId: string | undefined =
|
||||||
this.request?.['req']?.['workspaceId'];
|
this.request?.['req']?.['workspaceId'];
|
||||||
const cacheVersion: string | undefined =
|
const workspaceMetadataVersion: string | undefined =
|
||||||
this.request?.['req']?.['cacheVersion'];
|
this.request?.['req']?.['workspaceMetadataVersion'];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
workspaceId: workspaceId ?? null,
|
workspaceId: workspaceId ?? null,
|
||||||
cacheVersion: cacheVersion ?? null,
|
workspaceMetadataVersion: workspaceMetadataVersion ?? null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
|
||||||
import { Repository } from 'typeorm';
|
import { EntitySchema, Repository } from 'typeorm';
|
||||||
|
|
||||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||||
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
|
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
|
||||||
import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-schema.factory';
|
import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-schema.factory';
|
||||||
import { workspaceDataSourceCacheInstance } from 'src/engine/twenty-orm/twenty-orm-core.module';
|
import { workspaceDataSourceCacheInstance } from 'src/engine/twenty-orm/twenty-orm-core.module';
|
||||||
@ -18,7 +18,7 @@ export class WorkspaceDatasourceFactory {
|
|||||||
private readonly dataSourceService: DataSourceService,
|
private readonly dataSourceService: DataSourceService,
|
||||||
private readonly environmentService: EnvironmentService,
|
private readonly environmentService: EnvironmentService,
|
||||||
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
||||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||||
@InjectRepository(ObjectMetadataEntity, 'metadata')
|
@InjectRepository(ObjectMetadataEntity, 'metadata')
|
||||||
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
|
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
|
||||||
private readonly entitySchemaFactory: EntitySchemaFactory,
|
private readonly entitySchemaFactory: EntitySchemaFactory,
|
||||||
@ -26,21 +26,29 @@ export class WorkspaceDatasourceFactory {
|
|||||||
|
|
||||||
public async create(
|
public async create(
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
workspaceSchemaVersion: string | null,
|
workspaceMetadataVersion: string | null,
|
||||||
): Promise<WorkspaceDataSource> {
|
): Promise<WorkspaceDataSource> {
|
||||||
const desiredWorkspaceSchemaVersion =
|
const desiredWorkspaceMetadataVersion =
|
||||||
workspaceSchemaVersion ??
|
workspaceMetadataVersion ??
|
||||||
(await this.workspaceCacheVersionService.getVersion(workspaceId));
|
(await this.workspaceMetadataVersionService.getMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
));
|
||||||
|
|
||||||
if (!desiredWorkspaceSchemaVersion) {
|
if (!desiredWorkspaceMetadataVersion) {
|
||||||
throw new Error('Cache version not found');
|
throw new Error(
|
||||||
|
`Desired workspace metadata version not found while creating workspace data source for workspace ${workspaceId}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const latestWorkspaceSchemaVersion =
|
const latestWorkspaceMetadataVersion =
|
||||||
await this.workspaceCacheVersionService.getVersion(workspaceId);
|
await this.workspaceMetadataVersionService.getMetadataVersion(
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
if (latestWorkspaceSchemaVersion !== desiredWorkspaceSchemaVersion) {
|
if (latestWorkspaceMetadataVersion !== desiredWorkspaceMetadataVersion) {
|
||||||
throw new Error('Cache version mismatch');
|
throw new Error(
|
||||||
|
`Workspace metadata version mismatch detected for workspace ${workspaceId}. Current version: ${latestWorkspaceMetadataVersion}. Desired version: ${desiredWorkspaceMetadataVersion}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let cachedObjectMetadataCollection =
|
let cachedObjectMetadataCollection =
|
||||||
@ -70,7 +78,7 @@ export class WorkspaceDatasourceFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const workspaceDataSource = await workspaceDataSourceCacheInstance.execute(
|
const workspaceDataSource = await workspaceDataSourceCacheInstance.execute(
|
||||||
`${workspaceId}-${latestWorkspaceSchemaVersion}`,
|
`${workspaceId}-${latestWorkspaceMetadataVersion}`,
|
||||||
async () => {
|
async () => {
|
||||||
const dataSourceMetadata =
|
const dataSourceMetadata =
|
||||||
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceId(
|
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceId(
|
||||||
@ -78,18 +86,43 @@ export class WorkspaceDatasourceFactory {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!dataSourceMetadata) {
|
if (!dataSourceMetadata) {
|
||||||
throw new Error('Data source metadata not found');
|
throw new Error(
|
||||||
|
`Data source metadata not found for workspace ${workspaceId}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cachedObjectMetadataCollection) {
|
if (!cachedObjectMetadataCollection) {
|
||||||
throw new Error('Object metadata collection not found');
|
throw new Error(
|
||||||
|
`Object metadata collection not found for workspace ${workspaceId}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cachedEntitySchemaOptions =
|
||||||
|
await this.workspaceCacheStorageService.getORMEntitySchema(
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
|
let cachedEntitySchemas: EntitySchema[];
|
||||||
|
|
||||||
|
if (cachedEntitySchemaOptions) {
|
||||||
|
cachedEntitySchemas = cachedEntitySchemaOptions.map(
|
||||||
|
(option) => new EntitySchema(option),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const entitySchemas = await Promise.all(
|
||||||
|
cachedObjectMetadataCollection.map((objectMetadata) =>
|
||||||
|
this.entitySchemaFactory.create(workspaceId, objectMetadata),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.workspaceCacheStorageService.setORMEntitySchema(
|
||||||
|
workspaceId,
|
||||||
|
entitySchemas.map((entitySchema) => entitySchema.options),
|
||||||
|
);
|
||||||
|
|
||||||
|
cachedEntitySchemas = entitySchemas;
|
||||||
}
|
}
|
||||||
|
|
||||||
const entities = await Promise.all(
|
|
||||||
cachedObjectMetadataCollection.map((objectMetadata) =>
|
|
||||||
this.entitySchemaFactory.create(workspaceId, objectMetadata),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
const workspaceDataSource = new WorkspaceDataSource(
|
const workspaceDataSource = new WorkspaceDataSource(
|
||||||
{
|
{
|
||||||
workspaceId,
|
workspaceId,
|
||||||
@ -104,7 +137,7 @@ export class WorkspaceDatasourceFactory {
|
|||||||
? ['query', 'error']
|
? ['query', 'error']
|
||||||
: ['error'],
|
: ['error'],
|
||||||
schema: dataSourceMetadata.schema,
|
schema: dataSourceMetadata.schema,
|
||||||
entities,
|
entities: cachedEntitySchemas,
|
||||||
ssl: this.environmentService.get('PG_SSL_ALLOW_SELF_SIGNED')
|
ssl: this.environmentService.get('PG_SSL_ALLOW_SELF_SIGNED')
|
||||||
? {
|
? {
|
||||||
rejectUnauthorized: false,
|
rejectUnauthorized: false,
|
||||||
|
|||||||
@ -14,8 +14,7 @@ import {
|
|||||||
|
|
||||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||||
import { LoadServiceWithWorkspaceContext } from 'src/engine/twenty-orm/context/load-service-with-workspace.context';
|
|
||||||
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
|
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
|
||||||
import { entitySchemaFactories } from 'src/engine/twenty-orm/factories';
|
import { entitySchemaFactories } from 'src/engine/twenty-orm/factories';
|
||||||
import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-schema.factory';
|
import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-schema.factory';
|
||||||
@ -33,21 +32,15 @@ export const workspaceDataSourceCacheInstance =
|
|||||||
imports: [
|
imports: [
|
||||||
TypeOrmModule.forFeature([ObjectMetadataEntity], 'metadata'),
|
TypeOrmModule.forFeature([ObjectMetadataEntity], 'metadata'),
|
||||||
DataSourceModule,
|
DataSourceModule,
|
||||||
WorkspaceCacheVersionModule,
|
|
||||||
WorkspaceCacheStorageModule,
|
WorkspaceCacheStorageModule,
|
||||||
|
WorkspaceMetadataVersionModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
...entitySchemaFactories,
|
...entitySchemaFactories,
|
||||||
TwentyORMManager,
|
TwentyORMManager,
|
||||||
TwentyORMGlobalManager,
|
TwentyORMGlobalManager,
|
||||||
LoadServiceWithWorkspaceContext,
|
|
||||||
],
|
|
||||||
exports: [
|
|
||||||
EntitySchemaFactory,
|
|
||||||
TwentyORMManager,
|
|
||||||
LoadServiceWithWorkspaceContext,
|
|
||||||
TwentyORMGlobalManager,
|
|
||||||
],
|
],
|
||||||
|
exports: [EntitySchemaFactory, TwentyORMManager, TwentyORMGlobalManager],
|
||||||
})
|
})
|
||||||
export class TwentyORMCoreModule
|
export class TwentyORMCoreModule
|
||||||
extends ConfigurableModuleClass
|
extends ConfigurableModuleClass
|
||||||
|
|||||||
@ -25,7 +25,7 @@ export class TwentyORMManager {
|
|||||||
async getRepository<T extends ObjectLiteral>(
|
async getRepository<T extends ObjectLiteral>(
|
||||||
workspaceEntityOrobjectMetadataName: Type<T> | string,
|
workspaceEntityOrobjectMetadataName: Type<T> | string,
|
||||||
): Promise<WorkspaceRepository<T>> {
|
): Promise<WorkspaceRepository<T>> {
|
||||||
const { workspaceId, cacheVersion } =
|
const { workspaceId, workspaceMetadataVersion } =
|
||||||
this.scopedWorkspaceContextFactory.create();
|
this.scopedWorkspaceContextFactory.create();
|
||||||
|
|
||||||
let objectMetadataName: string;
|
let objectMetadataName: string;
|
||||||
@ -44,20 +44,23 @@ export class TwentyORMManager {
|
|||||||
|
|
||||||
const workspaceDataSource = await this.workspaceDataSourceFactory.create(
|
const workspaceDataSource = await this.workspaceDataSourceFactory.create(
|
||||||
workspaceId,
|
workspaceId,
|
||||||
cacheVersion,
|
workspaceMetadataVersion,
|
||||||
);
|
);
|
||||||
|
|
||||||
return workspaceDataSource.getRepository<T>(objectMetadataName);
|
return workspaceDataSource.getRepository<T>(objectMetadataName);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDatasource() {
|
async getDatasource() {
|
||||||
const { workspaceId, cacheVersion } =
|
const { workspaceId, workspaceMetadataVersion } =
|
||||||
this.scopedWorkspaceContextFactory.create();
|
this.scopedWorkspaceContextFactory.create();
|
||||||
|
|
||||||
if (!workspaceId) {
|
if (!workspaceId) {
|
||||||
throw new Error('Workspace not found');
|
throw new Error('Workspace not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.workspaceDataSourceFactory.create(workspaceId, cacheVersion);
|
return this.workspaceDataSourceFactory.create(
|
||||||
|
workspaceId,
|
||||||
|
workspaceMetadataVersion,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
|
||||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [WorkspaceCacheVersionModule],
|
|
||||||
providers: [WorkspaceCacheStorageService],
|
providers: [WorkspaceCacheStorageService],
|
||||||
exports: [WorkspaceCacheStorageService],
|
exports: [WorkspaceCacheStorageService],
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,56 +1,67 @@
|
|||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { EntitySchemaOptions } from 'typeorm';
|
||||||
|
|
||||||
import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service';
|
import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service';
|
||||||
import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator';
|
import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator';
|
||||||
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
||||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
|
||||||
|
enum WorkspaceCacheKeys {
|
||||||
|
GraphQLTypeDefs = 'graphql:type-defs',
|
||||||
|
GraphQLUsedScalarNames = 'graphql:used-scalar-names',
|
||||||
|
GraphQLOperations = 'graphql:operations',
|
||||||
|
ORMEntitySchemas = 'orm:entity-schemas',
|
||||||
|
MetadataObjectMetadataCollection = 'metadata:object-metadata-collection',
|
||||||
|
MetadataVersion = 'metadata:workspace-metadata-version',
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class WorkspaceCacheStorageService {
|
export class WorkspaceCacheStorageService {
|
||||||
private readonly logger = new Logger(WorkspaceCacheStorageService.name);
|
private readonly logger = new Logger(WorkspaceCacheStorageService.name);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@InjectCacheStorage(CacheStorageNamespace.WorkspaceSchema)
|
@InjectCacheStorage(CacheStorageNamespace.EngineWorkspace)
|
||||||
private readonly workspaceSchemaCache: CacheStorageService,
|
private readonly cacheStorageService: CacheStorageService,
|
||||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async validateCacheVersion(workspaceId: string): Promise<void> {
|
setORMEntitySchema(
|
||||||
const currentVersion =
|
workspaceId: string,
|
||||||
(await this.workspaceSchemaCache.get<string>(
|
entitySchemas: EntitySchemaOptions<any>[],
|
||||||
`cacheVersion:${workspaceId}`,
|
) {
|
||||||
)) ?? '0';
|
return this.cacheStorageService.set<EntitySchemaOptions<any>[]>(
|
||||||
|
`${WorkspaceCacheKeys.ORMEntitySchemas}:${workspaceId}`,
|
||||||
|
entitySchemas,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let latestVersion =
|
getORMEntitySchema(
|
||||||
await this.workspaceCacheVersionService.getVersion(workspaceId);
|
workspaceId: string,
|
||||||
|
): Promise<EntitySchemaOptions<any>[] | undefined> {
|
||||||
|
return this.cacheStorageService.get<EntitySchemaOptions<any>[]>(
|
||||||
|
`${WorkspaceCacheKeys.ORMEntitySchemas}:${workspaceId}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (!latestVersion || currentVersion !== latestVersion) {
|
setMetadataVersion(workspaceId: string, version: number): Promise<void> {
|
||||||
// Invalidate cache if version mismatch is detected"
|
return this.cacheStorageService.set<number>(
|
||||||
this.logger.log(
|
`${WorkspaceCacheKeys.MetadataVersion}:${workspaceId}`,
|
||||||
`Cache version mismatch detected for workspace ${workspaceId}. Current version: ${currentVersion}. Latest version: ${latestVersion}. Invalidating cache...`,
|
version,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
await this.invalidateCache(workspaceId);
|
getMetadataVersion(workspaceId: string): Promise<number | undefined> {
|
||||||
|
return this.cacheStorageService.get<number>(
|
||||||
// If the latest version is not found, increment the version
|
`${WorkspaceCacheKeys.MetadataVersion}:${workspaceId}`,
|
||||||
latestVersion ??=
|
);
|
||||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
|
||||||
|
|
||||||
// Update the cache version after invalidation
|
|
||||||
await this.workspaceSchemaCache.set<string>(
|
|
||||||
`cacheVersion:${workspaceId}`,
|
|
||||||
latestVersion,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setObjectMetadataCollection(
|
setObjectMetadataCollection(
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
objectMetadataCollection: ObjectMetadataEntity[],
|
objectMetadataCollection: ObjectMetadataEntity[],
|
||||||
) {
|
) {
|
||||||
return this.workspaceSchemaCache.set<ObjectMetadataEntity[]>(
|
return this.cacheStorageService.set<ObjectMetadataEntity[]>(
|
||||||
`objectMetadataCollection:${workspaceId}`,
|
`${WorkspaceCacheKeys.MetadataObjectMetadataCollection}:${workspaceId}`,
|
||||||
objectMetadataCollection,
|
objectMetadataCollection,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -58,43 +69,57 @@ export class WorkspaceCacheStorageService {
|
|||||||
getObjectMetadataCollection(
|
getObjectMetadataCollection(
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
): Promise<ObjectMetadataEntity[] | undefined> {
|
): Promise<ObjectMetadataEntity[] | undefined> {
|
||||||
return this.workspaceSchemaCache.get<ObjectMetadataEntity[]>(
|
return this.cacheStorageService.get<ObjectMetadataEntity[]>(
|
||||||
`objectMetadataCollection:${workspaceId}`,
|
`${WorkspaceCacheKeys.MetadataObjectMetadataCollection}:${workspaceId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
setTypeDefs(workspaceId: string, typeDefs: string): Promise<void> {
|
setGraphQLTypeDefs(workspaceId: string, typeDefs: string): Promise<void> {
|
||||||
return this.workspaceSchemaCache.set<string>(
|
return this.cacheStorageService.set<string>(
|
||||||
`typeDefs:${workspaceId}`,
|
`${WorkspaceCacheKeys.GraphQLTypeDefs}:${workspaceId}`,
|
||||||
typeDefs,
|
typeDefs,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTypeDefs(workspaceId: string): Promise<string | undefined> {
|
getGraphQLTypeDefs(workspaceId: string): Promise<string | undefined> {
|
||||||
return this.workspaceSchemaCache.get<string>(`typeDefs:${workspaceId}`);
|
return this.cacheStorageService.get<string>(
|
||||||
|
`${WorkspaceCacheKeys.GraphQLTypeDefs}:${workspaceId}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
setUsedScalarNames(
|
setGraphQLUsedScalarNames(
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
scalarsUsed: string[],
|
usedScalarNames: string[],
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return this.workspaceSchemaCache.set<string[]>(
|
return this.cacheStorageService.set<string[]>(
|
||||||
`usedScalarNames:${workspaceId}`,
|
`${WorkspaceCacheKeys.GraphQLUsedScalarNames}:${workspaceId}`,
|
||||||
scalarsUsed,
|
usedScalarNames,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getUsedScalarNames(workspaceId: string): Promise<string[] | undefined> {
|
getGraphQLUsedScalarNames(
|
||||||
return this.workspaceSchemaCache.get<string[]>(
|
workspaceId: string,
|
||||||
`usedScalarNames:${workspaceId}`,
|
): Promise<string[] | undefined> {
|
||||||
|
return this.cacheStorageService.get<string[]>(
|
||||||
|
`${WorkspaceCacheKeys.GraphQLUsedScalarNames}:${workspaceId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async invalidateCache(workspaceId: string): Promise<void> {
|
async flush(workspaceId: string): Promise<void> {
|
||||||
await this.workspaceSchemaCache.del(
|
await this.cacheStorageService.del(
|
||||||
`objectMetadataCollection:${workspaceId}`,
|
`${WorkspaceCacheKeys.MetadataObjectMetadataCollection}:${workspaceId}`,
|
||||||
|
);
|
||||||
|
await this.cacheStorageService.del(
|
||||||
|
`${WorkspaceCacheKeys.MetadataVersion}:${workspaceId}`,
|
||||||
|
);
|
||||||
|
await this.cacheStorageService.del(
|
||||||
|
`${WorkspaceCacheKeys.GraphQLTypeDefs}:${workspaceId}`,
|
||||||
|
);
|
||||||
|
await this.cacheStorageService.del(
|
||||||
|
`${WorkspaceCacheKeys.GraphQLUsedScalarNames}:${workspaceId}`,
|
||||||
|
);
|
||||||
|
await this.cacheStorageService.del(
|
||||||
|
`${WorkspaceCacheKeys.ORMEntitySchemas}:${workspaceId}`,
|
||||||
);
|
);
|
||||||
await this.workspaceSchemaCache.del(`typeDefs:${workspaceId}`);
|
|
||||||
await this.workspaceSchemaCache.del(`usedScalarNames:${workspaceId}`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,13 @@
|
|||||||
import { InjectRepository } from '@nestjs/typeorm';
|
|
||||||
import { Logger } from '@nestjs/common';
|
import { Logger } from '@nestjs/common';
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
|
||||||
import { Command, CommandRunner, Option } from 'nest-commander';
|
import { Command, CommandRunner, Option } from 'nest-commander';
|
||||||
import { In, Repository } from 'typeorm';
|
import { In, Repository } from 'typeorm';
|
||||||
|
|
||||||
|
import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service';
|
||||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||||
import { getDryRunLogHeader } from 'src/utils/get-dry-run-log-header';
|
import { getDryRunLogHeader } from 'src/utils/get-dry-run-log-header';
|
||||||
import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service';
|
|
||||||
import { LoadServiceWithWorkspaceContext } from 'src/engine/twenty-orm/context/load-service-with-workspace.context';
|
|
||||||
|
|
||||||
type DeleteWorkspacesCommandOptions = {
|
type DeleteWorkspacesCommandOptions = {
|
||||||
dryRun?: boolean;
|
dryRun?: boolean;
|
||||||
@ -24,7 +23,6 @@ export class DeleteWorkspacesCommand extends CommandRunner {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workspaceService: WorkspaceService,
|
private readonly workspaceService: WorkspaceService,
|
||||||
private readonly loadServiceWithWorkspaceContext: LoadServiceWithWorkspaceContext,
|
|
||||||
@InjectRepository(Workspace, 'core')
|
@InjectRepository(Workspace, 'core')
|
||||||
private readonly workspaceRepository: Repository<Workspace>,
|
private readonly workspaceRepository: Repository<Workspace>,
|
||||||
private readonly dataSourceService: DataSourceService,
|
private readonly dataSourceService: DataSourceService,
|
||||||
@ -81,15 +79,15 @@ export class DeleteWorkspacesCommand extends CommandRunner {
|
|||||||
workspace.id
|
workspace.id
|
||||||
} name: '${workspace.displayName}'`,
|
} name: '${workspace.displayName}'`,
|
||||||
);
|
);
|
||||||
const workspaceServiceInstance =
|
// const workspaceServiceInstance =
|
||||||
await this.loadServiceWithWorkspaceContext.load(
|
// await this.loadServiceWithWorkspaceContext.load(
|
||||||
this.workspaceService,
|
// this.workspaceService,
|
||||||
workspace.id,
|
// workspace.id,
|
||||||
);
|
// );
|
||||||
|
|
||||||
if (!options.dryRun) {
|
// if (!options.dryRun) {
|
||||||
await workspaceServiceInstance.softDeleteWorkspace(workspace.id);
|
// await workspaceServiceInstance.softDeleteWorkspace(workspace.id);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import { Module } from '@nestjs/common';
|
|||||||
|
|
||||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
|
||||||
import { WorkspaceMigrationEnumService } from 'src/engine/workspace-manager/workspace-migration-runner/services/workspace-migration-enum.service';
|
import { WorkspaceMigrationEnumService } from 'src/engine/workspace-manager/workspace-migration-runner/services/workspace-migration-enum.service';
|
||||||
|
|
||||||
import { WorkspaceMigrationRunnerService } from './workspace-migration-runner.service';
|
import { WorkspaceMigrationRunnerService } from './workspace-migration-runner.service';
|
||||||
@ -10,11 +9,7 @@ import { WorkspaceMigrationRunnerService } from './workspace-migration-runner.se
|
|||||||
import { WorkspaceMigrationTypeService } from './services/workspace-migration-type.service';
|
import { WorkspaceMigrationTypeService } from './services/workspace-migration-type.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [WorkspaceDataSourceModule, WorkspaceMigrationModule],
|
||||||
WorkspaceDataSourceModule,
|
|
||||||
WorkspaceMigrationModule,
|
|
||||||
WorkspaceCacheVersionModule,
|
|
||||||
],
|
|
||||||
providers: [
|
providers: [
|
||||||
WorkspaceMigrationRunnerService,
|
WorkspaceMigrationRunnerService,
|
||||||
WorkspaceMigrationEnumService,
|
WorkspaceMigrationEnumService,
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-
|
|||||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||||
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||||
import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||||
import { WorkspaceMigrationBuilderModule } from 'src/engine/workspace-manager/workspace-migration-builder/workspace-migration-builder.module';
|
import { WorkspaceMigrationBuilderModule } from 'src/engine/workspace-manager/workspace-migration-builder/workspace-migration-builder.module';
|
||||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||||
@ -35,7 +35,7 @@ import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/works
|
|||||||
'metadata',
|
'metadata',
|
||||||
),
|
),
|
||||||
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
|
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
|
||||||
WorkspaceCacheVersionModule,
|
WorkspaceMetadataVersionModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
...workspaceSyncMetadataFactories,
|
...workspaceSyncMetadataFactories,
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { DataSource, QueryFailedError } from 'typeorm';
|
|||||||
import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface';
|
import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface';
|
||||||
|
|
||||||
import { FeatureFlagFactory } from 'src/engine/core-modules/feature-flag/services/feature-flags.factory';
|
import { FeatureFlagFactory } from 'src/engine/core-modules/feature-flag/services/feature-flags.factory';
|
||||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||||
import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||||
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service';
|
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service';
|
||||||
import { WorkspaceSyncFieldMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-field-metadata.service';
|
import { WorkspaceSyncFieldMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-field-metadata.service';
|
||||||
@ -32,9 +32,9 @@ export class WorkspaceSyncMetadataService {
|
|||||||
private readonly workspaceSyncObjectMetadataService: WorkspaceSyncObjectMetadataService,
|
private readonly workspaceSyncObjectMetadataService: WorkspaceSyncObjectMetadataService,
|
||||||
private readonly workspaceSyncRelationMetadataService: WorkspaceSyncRelationMetadataService,
|
private readonly workspaceSyncRelationMetadataService: WorkspaceSyncRelationMetadataService,
|
||||||
private readonly workspaceSyncFieldMetadataService: WorkspaceSyncFieldMetadataService,
|
private readonly workspaceSyncFieldMetadataService: WorkspaceSyncFieldMetadataService,
|
||||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
|
||||||
private readonly workspaceSyncIndexMetadataService: WorkspaceSyncIndexMetadataService,
|
private readonly workspaceSyncIndexMetadataService: WorkspaceSyncIndexMetadataService,
|
||||||
private readonly workspaceSyncObjectMetadataIdentifiersService: WorkspaceSyncObjectMetadataIdentifiersService,
|
private readonly workspaceSyncObjectMetadataIdentifiersService: WorkspaceSyncObjectMetadataIdentifiersService,
|
||||||
|
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -157,7 +157,7 @@ export class WorkspaceSyncMetadataService {
|
|||||||
await queryRunner.rollbackTransaction();
|
await queryRunner.rollbackTransaction();
|
||||||
} finally {
|
} finally {
|
||||||
await queryRunner.release();
|
await queryRunner.release();
|
||||||
await this.workspaceCacheVersionService.incrementVersion(
|
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||||
context.workspaceId,
|
context.workspaceId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,6 +32,8 @@ export class CalendarEventListFetchCronJob {
|
|||||||
|
|
||||||
@Process(CalendarEventListFetchCronJob.name)
|
@Process(CalendarEventListFetchCronJob.name)
|
||||||
async handle(): Promise<void> {
|
async handle(): Promise<void> {
|
||||||
|
console.time('CalendarEventListFetchCronJob time');
|
||||||
|
|
||||||
const activeWorkspaces = await this.workspaceRepository.find({
|
const activeWorkspaces = await this.workspaceRepository.find({
|
||||||
where: {
|
where: {
|
||||||
activationStatus: WorkspaceActivationStatus.ACTIVE,
|
activationStatus: WorkspaceActivationStatus.ACTIVE,
|
||||||
@ -65,5 +67,7 @@ export class CalendarEventListFetchCronJob {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.timeEnd('CalendarEventListFetchCronJob time');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,6 +33,8 @@ export class CalendarEventListFetchJob {
|
|||||||
|
|
||||||
@Process(CalendarEventListFetchJob.name)
|
@Process(CalendarEventListFetchJob.name)
|
||||||
async handle(data: CalendarEventsImportJobData): Promise<void> {
|
async handle(data: CalendarEventsImportJobData): Promise<void> {
|
||||||
|
console.time('CalendarEventListFetchJob time');
|
||||||
|
|
||||||
const { workspaceId, calendarChannelId } = data;
|
const { workspaceId, calendarChannelId } = data;
|
||||||
|
|
||||||
const calendarChannelRepository =
|
const calendarChannelRepository =
|
||||||
@ -91,5 +93,6 @@ export class CalendarEventListFetchJob {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
console.timeEnd('CalendarEventListFetchJob time');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import { AccountsToReconnectKeys } from 'src/modules/connected-account/types/acc
|
|||||||
export class CalendarChannelSyncStatusService {
|
export class CalendarChannelSyncStatusService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly twentyORMManager: TwentyORMManager,
|
private readonly twentyORMManager: TwentyORMManager,
|
||||||
@InjectCacheStorage(CacheStorageNamespace.Calendar)
|
@InjectCacheStorage(CacheStorageNamespace.ModuleCalendar)
|
||||||
private readonly cacheStorage: CacheStorageService,
|
private readonly cacheStorage: CacheStorageService,
|
||||||
private readonly accountsToReconnectService: AccountsToReconnectService,
|
private readonly accountsToReconnectService: AccountsToReconnectService,
|
||||||
) {}
|
) {}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import {
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class MessagingChannelSyncStatusService {
|
export class MessagingChannelSyncStatusService {
|
||||||
constructor(
|
constructor(
|
||||||
@InjectCacheStorage(CacheStorageNamespace.Messaging)
|
@InjectCacheStorage(CacheStorageNamespace.ModuleMessaging)
|
||||||
private readonly cacheStorage: CacheStorageService,
|
private readonly cacheStorage: CacheStorageService,
|
||||||
private readonly twentyORMManager: TwentyORMManager,
|
private readonly twentyORMManager: TwentyORMManager,
|
||||||
private readonly accountsToReconnectService: AccountsToReconnectService,
|
private readonly accountsToReconnectService: AccountsToReconnectService,
|
||||||
|
|||||||
@ -33,6 +33,8 @@ export class MessagingMessageListFetchCronJob {
|
|||||||
|
|
||||||
@Process(MessagingMessageListFetchCronJob.name)
|
@Process(MessagingMessageListFetchCronJob.name)
|
||||||
async handle(): Promise<void> {
|
async handle(): Promise<void> {
|
||||||
|
console.time('MessagingMessageListFetchCronJob time');
|
||||||
|
|
||||||
const activeWorkspaces = await this.workspaceRepository.find({
|
const activeWorkspaces = await this.workspaceRepository.find({
|
||||||
where: {
|
where: {
|
||||||
activationStatus: WorkspaceActivationStatus.ACTIVE,
|
activationStatus: WorkspaceActivationStatus.ACTIVE,
|
||||||
@ -66,5 +68,7 @@ export class MessagingMessageListFetchCronJob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.timeEnd('MessagingMessageListFetchCronJob time');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,7 @@ export class MessagingMessagesImportCronJob {
|
|||||||
|
|
||||||
@Process(MessagingMessagesImportCronJob.name)
|
@Process(MessagingMessagesImportCronJob.name)
|
||||||
async handle(): Promise<void> {
|
async handle(): Promise<void> {
|
||||||
|
console.time('MessagingMessagesImportCronJob time');
|
||||||
const activeWorkspaces = await this.workspaceRepository.find({
|
const activeWorkspaces = await this.workspaceRepository.find({
|
||||||
where: {
|
where: {
|
||||||
activationStatus: WorkspaceActivationStatus.ACTIVE,
|
activationStatus: WorkspaceActivationStatus.ACTIVE,
|
||||||
@ -69,5 +70,7 @@ export class MessagingMessagesImportCronJob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.timeEnd('MessagingMessagesImportCronJob time');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export type MessagingAddSingleMessageToCacheForImportJobData = {
|
|||||||
@Processor(MessageQueue.messagingQueue)
|
@Processor(MessageQueue.messagingQueue)
|
||||||
export class MessagingAddSingleMessageToCacheForImportJob {
|
export class MessagingAddSingleMessageToCacheForImportJob {
|
||||||
constructor(
|
constructor(
|
||||||
@InjectCacheStorage(CacheStorageNamespace.Messaging)
|
@InjectCacheStorage(CacheStorageNamespace.ModuleMessaging)
|
||||||
private readonly cacheStorage: CacheStorageService,
|
private readonly cacheStorage: CacheStorageService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import { Logger } from '@nestjs/common';
|
import { Logger } from '@nestjs/common';
|
||||||
|
|
||||||
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service';
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
|
||||||
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
|
|
||||||
import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator';
|
import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator';
|
||||||
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
||||||
import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service';
|
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
|
||||||
|
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
||||||
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
|
|
||||||
export type MessagingCleanCacheJobData = {
|
export type MessagingCleanCacheJobData = {
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
@ -17,7 +17,7 @@ export class MessagingCleanCacheJob {
|
|||||||
private readonly logger = new Logger(MessagingCleanCacheJob.name);
|
private readonly logger = new Logger(MessagingCleanCacheJob.name);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@InjectCacheStorage(CacheStorageNamespace.Messaging)
|
@InjectCacheStorage(CacheStorageNamespace.ModuleMessaging)
|
||||||
private readonly cacheStorage: CacheStorageService,
|
private readonly cacheStorage: CacheStorageService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@ -39,6 +39,8 @@ export class MessagingMessageListFetchJob {
|
|||||||
|
|
||||||
@Process(MessagingMessageListFetchJob.name)
|
@Process(MessagingMessageListFetchJob.name)
|
||||||
async handle(data: MessagingMessageListFetchJobData): Promise<void> {
|
async handle(data: MessagingMessageListFetchJobData): Promise<void> {
|
||||||
|
console.time('MessagingMessageListFetchJob time');
|
||||||
|
|
||||||
const { messageChannelId, workspaceId } = data;
|
const { messageChannelId, workspaceId } = data;
|
||||||
|
|
||||||
await this.messagingTelemetryService.track({
|
await this.messagingTelemetryService.track({
|
||||||
@ -145,5 +147,7 @@ export class MessagingMessageListFetchJob {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.timeEnd('MessagingMessageListFetchJob time');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,6 +35,8 @@ export class MessagingMessagesImportJob {
|
|||||||
|
|
||||||
@Process(MessagingMessagesImportJob.name)
|
@Process(MessagingMessagesImportJob.name)
|
||||||
async handle(data: MessagingMessagesImportJobData): Promise<void> {
|
async handle(data: MessagingMessagesImportJobData): Promise<void> {
|
||||||
|
console.time('MessagingMessagesImportJob time');
|
||||||
|
|
||||||
const { messageChannelId, workspaceId } = data;
|
const { messageChannelId, workspaceId } = data;
|
||||||
|
|
||||||
await this.messagingTelemetryService.track({
|
await this.messagingTelemetryService.track({
|
||||||
@ -95,5 +97,7 @@ export class MessagingMessagesImportJob {
|
|||||||
connectedAccount,
|
connectedAccount,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.timeEnd('MessagingMessagesImportJob time');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,7 +29,7 @@ export class MessagingFullMessageListFetchService {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly gmailClientProvider: MessagingGmailClientProvider,
|
private readonly gmailClientProvider: MessagingGmailClientProvider,
|
||||||
@InjectCacheStorage(CacheStorageNamespace.Messaging)
|
@InjectCacheStorage(CacheStorageNamespace.ModuleMessaging)
|
||||||
private readonly cacheStorage: CacheStorageService,
|
private readonly cacheStorage: CacheStorageService,
|
||||||
private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService,
|
private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService,
|
||||||
private readonly gmailErrorHandlingService: MessagingErrorHandlingService,
|
private readonly gmailErrorHandlingService: MessagingErrorHandlingService,
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export class MessagingMessagesImportService {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly fetchMessagesByBatchesService: MessagingGmailFetchMessagesByBatchesService,
|
private readonly fetchMessagesByBatchesService: MessagingGmailFetchMessagesByBatchesService,
|
||||||
@InjectCacheStorage(CacheStorageNamespace.Messaging)
|
@InjectCacheStorage(CacheStorageNamespace.ModuleMessaging)
|
||||||
private readonly cacheStorage: CacheStorageService,
|
private readonly cacheStorage: CacheStorageService,
|
||||||
private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService,
|
private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService,
|
||||||
private readonly saveMessagesAndEnqueueContactCreationService: MessagingSaveMessagesAndEnqueueContactCreationService,
|
private readonly saveMessagesAndEnqueueContactCreationService: MessagingSaveMessagesAndEnqueueContactCreationService,
|
||||||
|
|||||||
@ -24,7 +24,7 @@ export class MessagingPartialMessageListFetchService {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly gmailClientProvider: MessagingGmailClientProvider,
|
private readonly gmailClientProvider: MessagingGmailClientProvider,
|
||||||
@InjectCacheStorage(CacheStorageNamespace.Messaging)
|
@InjectCacheStorage(CacheStorageNamespace.ModuleMessaging)
|
||||||
private readonly cacheStorage: CacheStorageService,
|
private readonly cacheStorage: CacheStorageService,
|
||||||
private readonly gmailErrorHandlingService: MessagingErrorHandlingService,
|
private readonly gmailErrorHandlingService: MessagingErrorHandlingService,
|
||||||
private readonly gmailGetHistoryService: MessagingGmailHistoryService,
|
private readonly gmailGetHistoryService: MessagingGmailHistoryService,
|
||||||
|
|||||||
@ -32,6 +32,8 @@ export class MessagingMessageChannelSyncStatusMonitoringCronJob {
|
|||||||
async handle(): Promise<void> {
|
async handle(): Promise<void> {
|
||||||
this.logger.log('Starting message channel sync status monitoring...');
|
this.logger.log('Starting message channel sync status monitoring...');
|
||||||
|
|
||||||
|
console.time('MessagingMessageChannelSyncStatusMonitoringCronJob time');
|
||||||
|
|
||||||
await this.messagingTelemetryService.track({
|
await this.messagingTelemetryService.track({
|
||||||
eventName: 'message_channel.monitoring.sync_status.start',
|
eventName: 'message_channel.monitoring.sync_status.start',
|
||||||
message: 'Starting message channel sync status monitoring',
|
message: 'Starting message channel sync status monitoring',
|
||||||
@ -68,5 +70,7 @@ export class MessagingMessageChannelSyncStatusMonitoringCronJob {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.timeEnd('MessagingMessageChannelSyncStatusMonitoringCronJob time');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user