Files
speckle-server/packages/server/modules/workspaces/services/projectRegions.ts
T
Chuck Driesler 025ae104db feat(regions): move file uploads and blobs (#3977)
* chore(regions): failing test for moving blobs

* fix(blobs): use blob storage table

* chore(regions): include file_uploads table for thoroughness

* fix(regions): extract repeated string to utils
2025-02-26 19:34:50 +00:00

127 lines
4.7 KiB
TypeScript

import { GetProjectAutomationCount } from '@/modules/automate/domain/operations'
import { GetStreamCommentCount } from '@/modules/comments/domain/operations'
import { GetStreamBranchCount } from '@/modules/core/domain/branches/operations'
import { GetStreamCommitCount } from '@/modules/core/domain/commits/operations'
import { GetStreamObjectCount } from '@/modules/core/domain/objects/operations'
import { GetProject } from '@/modules/core/domain/projects/operations'
import { GetStreamWebhooks } from '@/modules/webhooks/domain/operations'
import {
CopyProjectAutomations,
CopyProjectBlobs,
CopyProjectComments,
CopyProjectModels,
CopyProjectObjects,
CopyProjects,
CopyProjectVersions,
CopyProjectWebhooks,
CopyWorkspace,
GetAvailableRegions,
UpdateProjectRegion
} from '@/modules/workspaces/domain/operations'
import { ProjectRegionAssignmentError } from '@/modules/workspaces/errors/regions'
export const updateProjectRegionFactory =
(deps: {
getProject: GetProject
countProjectModels: GetStreamBranchCount
countProjectVersions: GetStreamCommitCount
countProjectObjects: GetStreamObjectCount
countProjectAutomations: GetProjectAutomationCount
countProjectComments: GetStreamCommentCount
getProjectWebhooks: GetStreamWebhooks
getAvailableRegions: GetAvailableRegions
copyWorkspace: CopyWorkspace
copyProjects: CopyProjects
copyProjectModels: CopyProjectModels
copyProjectVersions: CopyProjectVersions
copyProjectObjects: CopyProjectObjects
copyProjectAutomations: CopyProjectAutomations
copyProjectComments: CopyProjectComments
copyProjectWebhooks: CopyProjectWebhooks
copyProjectBlobs: CopyProjectBlobs
}): UpdateProjectRegion =>
async (params) => {
const { projectId, regionKey } = params
const project = await deps.getProject({ projectId })
if (!project) {
throw new ProjectRegionAssignmentError('Project not found', {
info: { params }
})
}
if (!project.workspaceId) {
throw new ProjectRegionAssignmentError('Project not a part of a workspace', {
info: { params }
})
}
const availableRegions = await deps.getAvailableRegions({
workspaceId: project.workspaceId
})
if (!availableRegions.find((region) => region.key === regionKey)) {
throw new ProjectRegionAssignmentError(
'Specified region not available for workspace',
{
info: {
params,
workspaceId: project.workspaceId
}
}
)
}
// Move workspace
await deps.copyWorkspace({ workspaceId: project.workspaceId })
// Move commits
const projectIds = await deps.copyProjects({ projectIds: [projectId] })
const copiedModelCount = await deps.copyProjectModels({ projectIds })
const copiedVersionCount = await deps.copyProjectVersions({ projectIds })
// Move objects
const copiedObjectCount = await deps.copyProjectObjects({ projectIds })
// Move automations
const copiedAutomationCount = await deps.copyProjectAutomations({ projectIds })
// Move comments
const copiedCommentCount = await deps.copyProjectComments({ projectIds })
// Move webhooks
const copiedWebhookCount = await deps.copyProjectWebhooks({ projectIds })
// TODO: Move file blobs
await deps.copyProjectBlobs({ projectIds })
// TODO: Validate state after move captures latest state of project
const sourceProjectModelCount = await deps.countProjectModels(projectId)
const sourceProjectVersionCount = await deps.countProjectVersions(projectId)
const sourceProjectObjectCount = await deps.countProjectObjects({
streamId: projectId
})
const sourceProjectAutomationCount = await deps.countProjectAutomations({
projectId
})
const sourceProjectCommentCount = await deps.countProjectComments(projectId)
const sourceProjectWebhooks = await deps.getProjectWebhooks({ streamId: projectId })
const tests = [
copiedModelCount[projectId] === sourceProjectModelCount,
copiedVersionCount[projectId] === sourceProjectVersionCount,
copiedObjectCount[projectId] === sourceProjectObjectCount,
copiedAutomationCount[projectId] === sourceProjectAutomationCount,
copiedCommentCount[projectId] === sourceProjectCommentCount,
copiedWebhookCount[projectId] === sourceProjectWebhooks.length
]
if (!tests.every((test) => !!test)) {
// TODO: Move failed or source project added data while changing regions. Retry move.
throw new ProjectRegionAssignmentError(
'Missing data from source project in target region copy after move.'
)
}
// TODO: Update project region in db
return { ...project, regionKey }
}