UBERF-13433: Migrate channels to threads (#9761)

* UBERF-13433: Migrate from channels to threads

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* UBERF-13433: Migrate parent info

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* UBERF-13433: Use client traverse

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* UBERF-13433: Add tests

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* UBERF-13433: Support Jest in model packages

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* Revert "UBERF-13433: Support Jest in model packages"

This reverts commit 415f5916c9.

Signed-off-by: Artem Savchenko <armisav@gmail.com>

* Revert "UBERF-13433: Add tests"

This reverts commit 38d7fcd794.

Signed-off-by: Artem Savchenko <armisav@gmail.com>

---------

Signed-off-by: Artem Savchenko <armisav@gmail.com>
This commit is contained in:
Artyom Savchenko
2025-09-03 12:44:45 +07:00
committed by GitHub
parent f0dd63e8a0
commit 34ef726724
14 changed files with 103 additions and 58 deletions
-16
View File
@@ -60,22 +60,6 @@ export function createModel (builder: Builder): void {
},
PaletteColorIndexes.Houseplant
)
createSystemType(
builder,
chat.masterTag.Channel,
chat.icon.Channel,
chat.string.Channel,
chat.string.Channels,
{
defaultSection: communication.ids.CardMessagesSection,
defaultNavigation: MessagesNavigationAnchors.LatestMessages
},
PaletteColorIndexes.Blueberry
)
builder.mixin(chat.masterTag.Channel, core.class.Class, core.mixin.TxAccessLevel, {
updateAccessLevel: AccountRole.Guest
})
builder.mixin(chat.masterTag.Thread, core.class.Class, core.mixin.TxAccessLevel, {
updateAccessLevel: AccountRole.Guest
+84 -2
View File
@@ -13,9 +13,91 @@
// limitations under the License.
//
import { type MigrateOperation, type MigrationClient, type MigrationUpgradeClient } from '@hcengineering/model'
import card, { type Card, cardId, DOMAIN_CARD, type MasterTag } from '@hcengineering/card'
import type { Doc, Ref } from '@hcengineering/core'
import {
type MigrateOperation,
type MigrationClient,
type MigrationUpgradeClient,
type MigrateUpdate,
type MigrationDocumentQuery,
tryMigrate
} from '@hcengineering/model'
import chat from './plugin'
const channelMasterTag = 'chat:masterTag:Channel' as Ref<MasterTag>
export const chatOperation: MigrateOperation = {
async migrate (client: MigrationClient, mode): Promise<void> {},
async migrate (client: MigrationClient, mode): Promise<void> {
await tryMigrate(mode, client, cardId, [
{
state: 'migrate-channels',
mode: 'upgrade',
func: migrateChannelsToThreads
},
{
state: 'migrate-parent-info',
mode: 'upgrade',
func: migrateParentInfo
}
])
},
async upgrade (state: Map<string, Set<string>>, client: () => Promise<MigrationUpgradeClient>, mode): Promise<void> {}
}
async function migrateChannelsToThreads (client: MigrationClient): Promise<void> {
await client.update(
DOMAIN_CARD,
{
_class: channelMasterTag
},
{
_class: chat.masterTag.Thread
}
)
}
async function migrateParentInfo (client: MigrationClient): Promise<void> {
let processedCards = 0
const iterator = await client.traverse<Card>(DOMAIN_CARD, { _class: card.class.Card })
try {
while (true) {
const cards = await iterator.next(1000)
if (cards === null || cards.length === 0) {
break
}
const operations: { filter: MigrationDocumentQuery<Doc>, update: MigrateUpdate<Doc> }[] = []
for (const card of cards) {
if (card.parentInfo == null || card.parentInfo.length === 0) {
continue
}
const needUpdate = card.parentInfo.some((info) => info._class === channelMasterTag)
if (!needUpdate) {
continue
}
const parents = card.parentInfo.map((info) => {
if (info._class !== channelMasterTag) {
return info
}
return {
...info,
_class: chat.masterTag.Thread
}
})
operations.push({
filter: { _id: card._id },
update: {
parentInfo: parents
}
})
}
if (operations.length > 0) {
await client.bulk(DOMAIN_CARD, operations)
}
processedCards += cards.length
client.logger.log('Migrated cards', { count: processedCards })
}
} finally {
await iterator.close()
}
}