2c122a138d
* feat(multiregion): replace user replication * chore(multiregion): optimise replication * maybe it's this * postgres is fun * once more * chore(multiregion): only replicate test user creation during multiregion tests * feat: improved replicate_query logic * fix: minor * fix: starting issue * feat: included user create and delete specs to multiregion * feat: removed console logs * fix: user defaults * fix: multiregion test helper * fix: update scenarios for users * refactor(multiregion): swap replicateQuery concept to asMultiregionOperation (#5301) feat(multiregion): introduced asMultregionOperator, refactor test to user builder classes * chore: renamings * fix: remove comments * feat: remove user replication * refactor: simplified spec usages * chore: comments * chore: branches and favs * chore: more tests * chore: more tests * fix linting * fix tests * feat: dropping replication * refactor: moved project delete to service * fix: comment * feat: updateStreamFactory and updateProjectFacotry * deleteProjectFactory + replicateFactory * deleteWorkspaceFactory * fix: selector * fix: tests * fix tests, finished createStreamFactory * feat: simplify changes * fix: remove comment * fix: minor strucutres * fix: moveProjectToRegion * fix: moved branch creation outside of multiregion scope * fix: branch creation * fix: tests * fix: ci tests * fix: removed log form test * fix: on specs, no random regionKeys * review fixes * feat: workspace replciation * fix: mr comments * feat: removed test * fix: worksapce test creation * fix: mr issues * updated mutations * feat: drop workspace random defaults --------- Co-authored-by: Charles Driesler <chuck@speckle.systems>
136 lines
4.3 KiB
TypeScript
136 lines
4.3 KiB
TypeScript
import { db } from '@/db/knex'
|
|
import type { Resolvers } from '@/modules/core/graph/generated/graphql'
|
|
import { getWorkspacePlanFactory } from '@/modules/gatekeeper/repositories/billing'
|
|
import { canWorkspaceUseRegionsFactory } from '@/modules/gatekeeper/services/featureAuthorization'
|
|
import { getRegionsFactory } from '@/modules/multiregion/repositories'
|
|
import { authorizeResolver } from '@/modules/shared'
|
|
import {
|
|
getDefaultRegionFactory,
|
|
upsertRegionAssignmentFactory
|
|
} from '@/modules/workspaces/repositories/regions'
|
|
import { getWorkspaceFactory } from '@/modules/workspaces/repositories/workspaces'
|
|
import {
|
|
assignWorkspaceRegionFactory,
|
|
getAvailableRegionsFactory
|
|
} from '@/modules/workspaces/services/regions'
|
|
import { Roles } from '@speckle/shared'
|
|
import { WorkspacesNotYetImplementedError } from '@/modules/workspaces/errors/workspace'
|
|
import { scheduleJob } from '@/modules/multiregion/services/queue'
|
|
import { getExplicitProjects } from '@/modules/core/repositories/streams'
|
|
import { getFeatureFlags } from '@/modules/shared/helpers/envHelper'
|
|
import { withOperationLogging } from '@/observability/domain/businessLogging'
|
|
import { queryAllProjectsFactory } from '@/modules/core/services/projects'
|
|
|
|
const { FF_MOVE_PROJECT_REGION_ENABLED } = getFeatureFlags()
|
|
|
|
export default {
|
|
Workspace: {
|
|
defaultRegion: async (parent) => {
|
|
const getDefaultRegion = getDefaultRegionFactory({ db })
|
|
return await getDefaultRegion({ workspaceId: parent.id })
|
|
}
|
|
},
|
|
WorkspaceMutations: {
|
|
setDefaultRegion: async (_parent, args, ctx) => {
|
|
const workspaceId = args.workspaceId
|
|
const regionKey = args.regionKey
|
|
|
|
await authorizeResolver(
|
|
ctx.userId,
|
|
workspaceId,
|
|
Roles.Workspace.Admin,
|
|
ctx.resourceAccessRules
|
|
)
|
|
|
|
const logger = ctx.log.child({
|
|
workspaceId,
|
|
regionKey
|
|
})
|
|
|
|
const assignRegion = assignWorkspaceRegionFactory({
|
|
getAvailableRegions: getAvailableRegionsFactory({
|
|
getRegions: getRegionsFactory({ db }),
|
|
canWorkspaceUseRegions: canWorkspaceUseRegionsFactory({
|
|
getWorkspacePlan: getWorkspacePlanFactory({ db })
|
|
})
|
|
}),
|
|
upsertRegionAssignment: upsertRegionAssignmentFactory({ db }),
|
|
getDefaultRegion: getDefaultRegionFactory({ db }),
|
|
getWorkspace: getWorkspaceFactory({ db })
|
|
})
|
|
await withOperationLogging(
|
|
async () => await assignRegion({ workspaceId, regionKey }),
|
|
{
|
|
logger,
|
|
operationName: 'assignWorkspaceRegion',
|
|
operationDescription: 'Assign a region to a workspace'
|
|
}
|
|
)
|
|
|
|
// Move existing workspace projects to new target region
|
|
if (FF_MOVE_PROJECT_REGION_ENABLED) {
|
|
const queryAllProjects = queryAllProjectsFactory({
|
|
getExplicitProjects: getExplicitProjects({ db })
|
|
})
|
|
for await (const projects of queryAllProjects({
|
|
workspaceId
|
|
})) {
|
|
await Promise.all(
|
|
projects.map(async (project) => {
|
|
await scheduleJob({
|
|
type: 'move-project-region',
|
|
payload: {
|
|
projectId: project.id,
|
|
regionKey
|
|
}
|
|
})
|
|
})
|
|
)
|
|
}
|
|
}
|
|
|
|
return await ctx.loaders.workspaces!.getWorkspace.load(args.workspaceId)
|
|
}
|
|
},
|
|
WorkspaceProjectMutations: {
|
|
moveToRegion: async (_parent, args, context) => {
|
|
if (!FF_MOVE_PROJECT_REGION_ENABLED) {
|
|
throw new WorkspacesNotYetImplementedError()
|
|
}
|
|
|
|
const projectId = args.projectId
|
|
const regionKey = args.regionKey
|
|
|
|
await authorizeResolver(
|
|
context.userId,
|
|
projectId,
|
|
Roles.Stream.Owner,
|
|
context.resourceAccessRules
|
|
)
|
|
|
|
const logger = context.log.child({
|
|
projectId,
|
|
streamId: projectId, //legacy
|
|
regionKey
|
|
})
|
|
|
|
return await withOperationLogging(
|
|
async () => {
|
|
return await scheduleJob({
|
|
type: 'move-project-region',
|
|
payload: {
|
|
projectId,
|
|
regionKey
|
|
}
|
|
})
|
|
},
|
|
{
|
|
logger,
|
|
operationName: 'workspaceProjectMoveToRegion',
|
|
operationDescription: 'Move a workspace project to a different region'
|
|
}
|
|
)
|
|
}
|
|
}
|
|
} as Resolvers
|