Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ import {
OrcadSourceExportPersistence,
installOrcadSourceExportPersistenceContext
} from '../migrating-orcad-catalog/orcad-source-export'
import {
OrcadSourceRetirementPersistence,
installOrcadSourceRetirementPersistenceContext
} from '../migrating-orcad-catalog/orcad-source-retirement'
import {
OrcadCatalogImportPersistence,
installOrcadCatalogImportPersistenceContext
Expand All @@ -88,6 +92,7 @@ export type StoreDomainOperations = WriteSchedulingOperations &
RetiredWorktreeNamePersistence &
SshLeaseRecoveryOperations &
OrcadSourceExportPersistence &
OrcadSourceRetirementPersistence &
OrcadCatalogImportPersistence &
WriteFlushBarrierOperations

Expand All @@ -114,6 +119,7 @@ export type StoreDomains = {
retiredWorktreeNames: RetiredWorktreeNamePersistence
sshLeases: SshLeaseRecoveryOperations
orcadSourceExport: OrcadSourceExportPersistence
orcadSourceRetirement: OrcadSourceRetirementPersistence
orcadCatalogImports: OrcadCatalogImportPersistence
}

Expand All @@ -134,6 +140,7 @@ export const STORE_DOMAIN_OPERATION_CLASSES = [
RetiredWorktreeNamePersistence,
SshLeaseRecoveryOperations,
OrcadSourceExportPersistence,
OrcadSourceRetirementPersistence,
OrcadCatalogImportPersistence,
WriteFlushBarrierOperations
] as const
Expand All @@ -155,6 +162,7 @@ export function installStoreDomainContexts(target: Store, domains: StoreDomains)
installRetiredWorktreeNamePersistenceContext(target, domains.retiredWorktreeNames)
installSshLeaseRecoveryOperationsContext(target, domains.sshLeases)
installOrcadSourceExportPersistenceContext(target, domains.orcadSourceExport)
installOrcadSourceRetirementPersistenceContext(target, domains.orcadSourceRetirement)
installOrcadCatalogImportPersistenceContext(target, domains.orcadCatalogImports)
installWriteFlushBarrierOperationsContext(target, domains.flushBarriers)
}
Expand Down Expand Up @@ -216,6 +224,7 @@ export function createStoreDomains(runtime: StoreRuntimeState): StoreDomains {
sshLeases,
// Read-only: holds the runtime state and nothing that writes.
orcadSourceExport: new OrcadSourceExportPersistence(runtime),
orcadSourceRetirement: new OrcadSourceRetirementPersistence(runtime, repos, scheduling),
orcadCatalogImports
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { OrcadMigrationManifest } from '../../../shared/orcad-migration-manifest'
import type { PersistedState } from '../../../shared/persisted-state-types'

export function retireOrcadMigrationSourceAutomationState(
state: PersistedState,
manifest: OrcadMigrationManifest
): void {
const automations = manifest.payload.dormantState?.automations ?? []
const automationRuns = manifest.payload.dormantState?.automationRuns ?? []
if (automations.length === 0 && automationRuns.length === 0) {
return
}
const automationIds = new Set(automations.map((entry) => entry.id))
const runIds = new Set(automationRuns.map((entry) => entry.id))
state.automations = state.automations.filter((entry) => !automationIds.has(entry.id))
state.automationRuns = state.automationRuns.filter((entry) => !runIds.has(entry.id))
}

export function assertOrcadMigrationSourceAutomationStateRetired(
state: PersistedState,
manifest: OrcadMigrationManifest
): void {
const automationIds = new Set(
(manifest.payload.dormantState?.automations ?? []).map((entry) => entry.id)
)
const runIds = new Set(
(manifest.payload.dormantState?.automationRuns ?? []).map((entry) => entry.id)
)
if (
state.automations.some((entry) => automationIds.has(entry.id)) ||
state.automationRuns.some((entry) => runIds.has(entry.id))
) {
throw new Error('orcad_migration_source_automation_state_reappeared')
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Removes a migrated target's catalog rows from the source profile. Only rows the manifest names
* and the target still owns go; a group stays while anything outside the migration references it.
*/
import type { StoreRuntimeState } from '../loading-store/store-runtime-state'
import type { OrcadMigrationManifest } from '../../../shared/orcad-migration-manifest'

export function retireOrcadSourceCatalogState(
state: StoreRuntimeState['state'],
manifest: OrcadMigrationManifest
): void {
const repoIds = new Set(manifest.payload.repositories.map((repo) => repo.id))
const folderIds = new Set(manifest.payload.folderWorkspaces.map((workspace) => workspace.id))
const groupIds = new Set(manifest.payload.projectGroups.map((group) => group.id))
const groupConnectionById = new Map(
state.projectGroups.map((group) => [group.id, group.connectionId])
)
state.repos = state.repos.filter(
(repo) => !(repoIds.has(repo.id) && repo.connectionId === manifest.source.sshTargetId)
)
state.folderWorkspaces = state.folderWorkspaces.filter(
(workspace) =>
!(
folderIds.has(workspace.id) &&
(workspace.connectionId ?? groupConnectionById.get(workspace.projectGroupId) ?? null) ===
manifest.source.sshTargetId
)
)
removeUnreferencedSourceGroups(state, groupIds, manifest.source.sshTargetId)
}

function removeUnreferencedSourceGroups(
state: StoreRuntimeState['state'],
candidateIds: ReadonlySet<string>,
targetId: string
): void {
let removed = true
while (removed) {
removed = false
const referencedIds = new Set([
...state.repos.flatMap((repo) => (repo.projectGroupId ? [repo.projectGroupId] : [])),
...state.folderWorkspaces.map((workspace) => workspace.projectGroupId),
...state.projectGroups.flatMap((group) => (group.parentGroupId ? [group.parentGroupId] : []))
])
const next = state.projectGroups.filter((group) => {
const shouldRemove =
candidateIds.has(group.id) &&
group.connectionId === targetId &&
!referencedIds.has(group.id)
removed ||= shouldRemove
return !shouldRemove
})
state.projectGroups = next
}
}
Loading
Loading