Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(regions): move project comments and webhooks #3957

Draft
wants to merge 39 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
4d5f96b
feat(regions): repo functions for copying project branches and commits
cdriesler Jan 12, 2025
e5d04e5
chore(regions): wire up move to resolver
cdriesler Jan 13, 2025
f64a8bb
chore(regions): successful basic test of project region change
cdriesler Jan 14, 2025
f1a82e6
fix(regions): sabrina carpenter please please please
cdriesler Jan 16, 2025
ec0df3c
Merge remote-tracking branch 'origin' into chuck/web-2433-move-projec…
cdriesler Jan 16, 2025
88bafb2
fix(regions): repair multiregion test setup
cdriesler Jan 22, 2025
34a68a8
Merge remote-tracking branch 'origin' into chuck/web-2433-move-projec…
cdriesler Jan 22, 2025
1fb3b43
chore(regions): appease ts
cdriesler Jan 22, 2025
54b61bf
chore(multiregion): update test multiregion config
cdriesler Jan 22, 2025
de8d78a
chore(multiregion): fix test docker config and test
cdriesler Jan 22, 2025
ca85039
chore(multiregion): use transaction
cdriesler Jan 23, 2025
201fe2e
chore(multiregion): maybe this will work
cdriesler Jan 23, 2025
08b53cc
fix(multiregion): drop subs synchronously
cdriesler Jan 24, 2025
8edde64
chore(multiregion): desperate test logs
cdriesler Jan 24, 2025
afc06d7
chore(multiregion): somehow that worked?
cdriesler Jan 24, 2025
6d6f800
chore(multiregion): add load-bearing log statement
cdriesler Jan 24, 2025
a27b97a
chore(multiregion): move services
cdriesler Jan 24, 2025
6a0fadc
fix(multiregion): test drop waits
cdriesler Jan 24, 2025
969f8b6
Merge branch 'main' into chuck/web-2433-move-project-branches-and-com…
cdriesler Jan 27, 2025
361960c
Merge branch 'main' into chuck/web-2433-move-project-branches-and-com…
cdriesler Feb 2, 2025
0811916
chore(regions): fix import
cdriesler Feb 3, 2025
b48721e
chore(regions): make test a bit more thorough for good measure
cdriesler Feb 3, 2025
2b8f6af
fix(regions): move project objects
cdriesler Feb 3, 2025
62466f5
chore(regions): add tests for object move
cdriesler Feb 3, 2025
51ba709
feat(regions): move project automations
cdriesler Feb 3, 2025
de3173e
chore(regions): add tests for moving automations
cdriesler Feb 4, 2025
e371633
chore(regions): more tests for moving automate data
cdriesler Feb 6, 2025
04edd9c
fix(regions): speed up inserts
cdriesler Feb 6, 2025
28abd12
Merge branch 'chuck/web-2433-move-project-branches-and-commits' into …
cdriesler Feb 7, 2025
72167e6
fix(regions): simplify postgres usage
cdriesler Feb 7, 2025
f830056
Merge branch 'main' into chuck/web-2433-move-project-branches-and-com…
cdriesler Feb 7, 2025
d2212b0
Merge branch 'chuck/web-2433-move-project-branches-and-commits' into …
cdriesler Feb 7, 2025
2b00b47
Merge branch 'chuck/web-2451-move-commit-objects' into chuck/web-2436…
cdriesler Feb 7, 2025
25eacc3
chore(regions): repair build
cdriesler Feb 7, 2025
78e8ff8
fix(regions): improve queries
cdriesler Feb 7, 2025
613eb3c
chore(regions): failing test for moving comments
cdriesler Feb 7, 2025
c416484
feat(regions): move project comments
cdriesler Feb 7, 2025
21bf57f
fix(regions): move webhooks because they deserve love too
cdriesler Feb 11, 2025
f18a457
Merge remote-tracking branch 'origin' into chuck/web-2435-move-commen…
cdriesler Feb 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/server/modules/comments/domain/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,3 +319,8 @@ export type GetPaginatedProjectComments = (
items: CommentRecord[]
cursor: string | null
}>

export type GetStreamCommentCount = (
streamId: string,
options?: Partial<{ threadsOnly: boolean; includeArchived: boolean }>
) => Promise<number>
2 changes: 1 addition & 1 deletion packages/server/modules/core/services/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const createNewProjectFactory =
const replicatedProject = await getProject({ projectId })
if (!replicatedProject) throw new StreamNotFoundError()
},
{ maxAttempts: 10 }
{ maxAttempts: 100 }
)
} catch (err) {
if (err instanceof StreamNotFoundError) {
Expand Down
6 changes: 6 additions & 0 deletions packages/server/modules/workspaces/domain/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,3 +369,9 @@ export type CopyProjectObjects = (params: {
export type CopyProjectAutomations = (params: {
projectIds: string[]
}) => Promise<Record<string, number>>
export type CopyProjectComments = (params: {
projectIds: string[]
}) => Promise<Record<string, number>>
export type CopyProjectWebhooks = (params: {
projectIds: string[]
}) => Promise<Record<string, number>>
10 changes: 9 additions & 1 deletion packages/server/modules/workspaces/graph/resolvers/regions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import {
} from '@/modules/workspaces/repositories/regions'
import {
copyProjectAutomationsFactory,
copyProjectCommentsFactory,
copyProjectModelsFactory,
copyProjectObjectsFactory,
copyProjectsFactory,
copyProjectVersionsFactory,
copyProjectWebhooksFactory,
copyWorkspaceFactory
} from '@/modules/workspaces/repositories/projectRegions'
import {
Expand All @@ -35,6 +37,8 @@ import { getStreamObjectCountFactory } from '@/modules/core/repositories/objects
import { getProjectAutomationsTotalCountFactory } from '@/modules/automate/repositories/automations'
import { getFeatureFlags, isTestEnv } from '@/modules/shared/helpers/envHelper'
import { WorkspacesNotYetImplementedError } from '@/modules/workspaces/errors/workspace'
import { getStreamCommentCountFactory } from '@/modules/comments/repositories/comments'
import { getStreamWebhooksFactory } from '@/modules/webhooks/repositories/webhooks'

const { FF_MOVE_PROJECT_REGION_ENABLED } = getFeatureFlags()

Expand Down Expand Up @@ -97,6 +101,8 @@ export default {
countProjectAutomations: getProjectAutomationsTotalCountFactory({
db: sourceDb
}),
countProjectComments: getStreamCommentCountFactory({ db: sourceDb }),
getProjectWebhooks: getStreamWebhooksFactory({ db: sourceDb }),
getAvailableRegions: getAvailableRegionsFactory({
getRegions: getRegionsFactory({ db }),
canWorkspaceUseRegions: canWorkspaceUseRegionsFactory({
Expand All @@ -108,7 +114,9 @@ export default {
copyProjectModels: copyProjectModelsFactory({ sourceDb, targetDb }),
copyProjectVersions: copyProjectVersionsFactory({ sourceDb, targetDb }),
copyProjectObjects: copyProjectObjectsFactory({ sourceDb, targetDb }),
copyProjectAutomations: copyProjectAutomationsFactory({ sourceDb, targetDb })
copyProjectAutomations: copyProjectAutomationsFactory({ sourceDb, targetDb }),
copyProjectComments: copyProjectCommentsFactory({ sourceDb, targetDb }),
copyProjectWebhooks: copyProjectWebhooksFactory({ sourceDb, targetDb })
})

return await withTransaction(updateProjectRegion(args), targetDb)
Expand Down
120 changes: 119 additions & 1 deletion packages/server/modules/workspaces/repositories/projectRegions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import {
AutomationTriggers,
BranchCommits,
Branches,
CommentLinks,
Comments,
CommentViews,
Commits,
Objects,
StreamCommits,
Expand All @@ -30,10 +33,12 @@ import {
import { executeBatchedSelect } from '@/modules/shared/helpers/dbHelper'
import {
CopyProjectAutomations,
CopyProjectComments,
CopyProjectModels,
CopyProjectObjects,
CopyProjects,
CopyProjectVersions,
CopyProjectWebhooks,
CopyWorkspace
} from '@/modules/workspaces/domain/operations'
import { WorkspaceNotFoundError } from '@/modules/workspaces/errors/workspace'
Expand All @@ -51,6 +56,12 @@ import {
AutomationTokenRecord,
AutomationTriggerDefinitionRecord
} from '@/modules/automate/helpers/types'
import {
CommentLinkRecord,
CommentRecord,
CommentViewRecord
} from '@/modules/comments/helpers/types'
import { Webhook, WebhookEvent } from '@/modules/webhooks/domain/types'

const tables = {
workspaces: (db: Knex) => db<Workspace>(Workspaces.name),
Expand All @@ -75,7 +86,12 @@ const tables = {
automationRunTriggers: (db: Knex) =>
db<AutomationRunTriggerRecord>(AutomationRunTriggers.name),
automationFunctionRuns: (db: Knex) =>
db<AutomationFunctionRunRecord>(AutomationFunctionRuns.name)
db<AutomationFunctionRunRecord>(AutomationFunctionRuns.name),
comments: (db: Knex) => db.table<CommentRecord>(Comments.name),
commentViews: (db: Knex) => db.table<CommentViewRecord>(CommentViews.name),
commentLinks: (db: Knex) => db.table<CommentLinkRecord>(CommentLinks.name),
webhooks: (db: Knex) => db.table<Webhook>('webhooks_config'),
webhookEvents: (db: Knex) => db.table<WebhookEvent>('webhooks_events')
}

/**
Expand Down Expand Up @@ -459,3 +475,105 @@ export const copyProjectAutomationsFactory =

return copiedAutomationCountByProjectId
}

/**
* Copies rows from the following tables:
* - comments
* - comment_views
* - comment_links
*/
export const copyProjectCommentsFactory =
(deps: { sourceDb: Knex; targetDb: Knex }): CopyProjectComments =>
async ({ projectIds }) => {
const copiedCommentCountByProjectId: Record<string, number> = {}

// Copy `comments` table rows in batches
const selectComments = tables
.comments(deps.sourceDb)
.select('*')
.whereIn(Comments.col.streamId, projectIds)

for await (const comments of executeBatchedSelect(selectComments)) {
const commentIds = comments.map((comment) => comment.id)

// Write `comments` rows to target db
await tables.comments(deps.targetDb).insert(comments).onConflict().ignore()

for (const comment of comments) {
copiedCommentCountByProjectId[comment.streamId] ??= 0
copiedCommentCountByProjectId[comment.streamId]++
}

// Copy `comment_views` table rows
const commentViews = await tables
.commentViews(deps.sourceDb)
.select('*')
.whereIn(CommentViews.col.commentId, commentIds)

await tables
.commentViews(deps.targetDb)
.insert(commentViews)
.onConflict()
.ignore()

// Copy `comment_links` table rows
const commentLinks = await tables
.commentLinks(deps.sourceDb)
.select('*')
.whereIn(CommentLinks.col.commentId, commentIds)

await tables
.commentLinks(deps.targetDb)
.insert(commentLinks)
.onConflict()
.ignore()
}

return copiedCommentCountByProjectId
}

/**
* Copies rows from the following tables:
* - webhooks_config
* - webhooks_events
*/
export const copyProjectWebhooksFactory =
(deps: { sourceDb: Knex; targetDb: Knex }): CopyProjectWebhooks =>
async ({ projectIds }) => {
const copiedWebhookCountByProjectId: Record<string, number> = {}

// Copy `webhooks_config` table rows in batches
const selectWebhooks = tables
.webhooks(deps.sourceDb)
.select('*')
.whereIn('streamId', projectIds)

for await (const webhooks of executeBatchedSelect(selectWebhooks)) {
const webhookIds = webhooks.map((webhook) => webhook.id)

// Write `webhooks_config` rows to target db
await tables.webhooks(deps.targetDb).insert(webhooks).onConflict().ignore()

for (const webhook of webhooks) {
copiedWebhookCountByProjectId[webhook.streamId] ??= 0
copiedWebhookCountByProjectId[webhook.streamId]++
}

// Copy `webhooks_events` table rows in batches
const selectWebhookEvents = tables
.webhookEvents(deps.sourceDb)
.select('*')
.whereIn('webhookId', webhookIds)

for await (const webhookEvents of executeBatchedSelect(selectWebhookEvents)) {
// Write `webhooks_events` rows to target db
await tables
.webhookEvents(deps.targetDb)
.insert(webhookEvents)
.onConflict()
.ignore()
}
}

return copiedWebhookCountByProjectId
}
22 changes: 19 additions & 3 deletions packages/server/modules/workspaces/services/projectRegions.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
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,
CopyProjectComments,
CopyProjectModels,
CopyProjectObjects,
CopyProjects,
CopyProjectVersions,
CopyProjectWebhooks,
CopyWorkspace,
GetAvailableRegions,
UpdateProjectRegion
Expand All @@ -22,13 +26,17 @@ export const updateProjectRegionFactory =
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
}): UpdateProjectRegion =>
async (params) => {
const { projectId, regionKey } = params
Expand Down Expand Up @@ -74,9 +82,13 @@ export const updateProjectRegionFactory =
// Move automations
const copiedAutomationCount = await deps.copyProjectAutomations({ projectIds })

// TODO: Move comments
// Move comments
const copiedCommentCount = await deps.copyProjectComments({ projectIds })

// Move webhooks
const copiedWebhookCount = await deps.copyProjectWebhooks({ projectIds })

// TODO: Move file blobs
// TODO: Move webhooks

// TODO: Validate state after move captures latest state of project
const sourceProjectModelCount = await deps.countProjectModels(projectId)
Expand All @@ -87,12 +99,16 @@ export const updateProjectRegionFactory =
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
copiedAutomationCount[projectId] === sourceProjectAutomationCount,
copiedCommentCount[projectId] === sourceProjectCommentCount,
copiedWebhookCount[projectId] === sourceProjectWebhooks.length
]

if (!tests.every((test) => !!test)) {
Expand Down
Loading