Qfix: mongo status collection (#7990)

Signed-off-by: Alexey Zinoviev <alexey.zinoviev@xored.com>
This commit is contained in:
Alexey Zinoviev
2025-02-12 17:22:19 +07:00
committed by GitHub
parent 7716ff8590
commit 69dbd06863
2 changed files with 235 additions and 7 deletions
+226
View File
@@ -0,0 +1,226 @@
//
// Copyright © 2025 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
/* eslint-disable @typescript-eslint/unbound-method */
import { type WorkspaceUuid } from '@hcengineering/core'
import { MongoDbCollection, WorkspaceStatusMongoDbCollection } from '../collections/mongo'
import { WorkspaceInfoWithStatus, WorkspaceStatus } from '../types'
describe('WorkspaceStatusMongoDbCollection', () => {
let mockWsCollection: MongoDbCollection<WorkspaceInfoWithStatus, 'uuid'>
let wsStatusCollection: WorkspaceStatusMongoDbCollection
beforeEach(() => {
mockWsCollection = {
find: jest.fn(),
findOne: jest.fn(),
insertOne: jest.fn(),
updateOne: jest.fn(),
deleteMany: jest.fn()
} as any
wsStatusCollection = new WorkspaceStatusMongoDbCollection(mockWsCollection)
})
describe('find', () => {
it('should transform query and return status results', async () => {
const mockWorkspaces = [
{
uuid: 'ws1',
status: {
mode: 'active',
versionMajor: 1,
versionMinor: 0,
versionPatch: 0,
isDisabled: false
}
}
]
;(mockWsCollection.find as jest.Mock).mockResolvedValue(mockWorkspaces)
const query: Partial<WorkspaceStatus> = {
workspaceUuid: 'ws1' as WorkspaceUuid,
mode: 'active'
}
const result = await wsStatusCollection.find(query)
expect(mockWsCollection.find).toHaveBeenCalledWith(
{
uuid: 'ws1',
status: {
mode: 'active'
}
},
undefined,
undefined
)
expect(result).toEqual([
{
workspaceUuid: 'ws1' as WorkspaceUuid,
mode: 'active',
versionMajor: 1,
versionMinor: 0,
versionPatch: 0,
isDisabled: false
}
])
})
})
describe('updateOne', () => {
it('should transform operations correctly', async () => {
const query = { workspaceUuid: 'ws1' as WorkspaceUuid }
const ops = {
$inc: { processingAttempts: 1 },
$set: { mode: 'active' as const }
}
await wsStatusCollection.updateOne(query, ops)
expect(mockWsCollection.updateOne).toHaveBeenCalledWith(
{ uuid: 'ws1' },
{
$inc: { 'status.processingAttempts': 1 },
'status.mode': 'active'
}
)
})
it('should handle direct field updates', async () => {
const query = { workspaceUuid: 'ws1' as WorkspaceUuid }
const ops = {
mode: 'active' as const,
isDisabled: true,
processingProgress: 75
}
await wsStatusCollection.updateOne(query, ops)
expect(mockWsCollection.updateOne).toHaveBeenCalledWith(
{ uuid: 'ws1' },
{
'status.mode': 'active',
'status.isDisabled': true,
'status.processingProgress': 75
}
)
})
it('should handle complex query operators', async () => {
const query = {
workspaceUuid: 'ws1' as WorkspaceUuid,
mode: { $in: ['active' as const, 'creating' as const] },
processingProgress: { $lt: 50 },
processingAttempts: { $gte: 3 }
}
const ops = {
mode: 'active' as const
}
await wsStatusCollection.updateOne(query, ops)
expect(mockWsCollection.updateOne).toHaveBeenCalledWith(
{
uuid: 'ws1',
status: {
mode: { $in: ['active', 'creating'] },
processingProgress: { $lt: 50 },
processingAttempts: { $gte: 3 }
}
},
{
'status.mode': 'active'
}
)
})
it('should handle mixed operations and complex queries', async () => {
const query = {
workspaceUuid: 'ws1' as WorkspaceUuid,
mode: { $in: ['active' as const, 'creating' as const] }
}
const ops = {
$inc: {
processingAttempts: 1,
processingProgress: 10
},
$set: {
mode: 'active' as const,
lastProcessingTime: 123456
},
isDisabled: true
}
await wsStatusCollection.updateOne(query, ops)
expect(mockWsCollection.updateOne).toHaveBeenCalledWith(
{
uuid: 'ws1',
status: {
mode: { $in: ['active', 'creating'] }
}
},
{
$inc: {
'status.processingAttempts': 1,
'status.processingProgress': 10
},
'status.mode': 'active',
'status.lastProcessingTime': 123456,
'status.isDisabled': true
}
)
})
})
describe('updateOne', () => {
it('should transform operations correctly', async () => {
const query = { workspaceUuid: 'ws1' as WorkspaceUuid }
const ops = {
$inc: { processingAttempts: 1 },
$set: { mode: 'active' as const }
}
await wsStatusCollection.updateOne(query, ops)
expect(mockWsCollection.updateOne).toHaveBeenCalledWith(
{ uuid: 'ws1' },
{
$inc: { 'status.processingAttempts': 1 },
'status.mode': 'active'
}
)
})
})
describe('deleteMany', () => {
it('should transform query for deletion', async () => {
const query = { workspaceUuid: 'ws1' as WorkspaceUuid, mode: 'active' as const }
await wsStatusCollection.deleteMany(query)
expect(mockWsCollection.deleteMany).toHaveBeenCalledWith({
uuid: 'ws1',
status: {
mode: 'active'
}
})
})
})
})
+9 -7
View File
@@ -235,17 +235,15 @@ export class WorkspaceStatusMongoDbCollection implements DbCollection<WorkspaceS
for (const key of Object.keys(query)) {
const qVal = (query as any)[key]
const operator = typeof qVal === 'object' ? Object.keys(qVal)[0] : ''
const targetVal = operator !== '' ? { [operator]: qVal } : qVal
if (key === 'workspaceUuid') {
res.uuid = targetVal
res.uuid = qVal
} else {
if (res.status === undefined) {
res.status = {}
}
;(res.status as any)[key] = targetVal
;(res.status as any)[key] = qVal
}
}
@@ -274,10 +272,14 @@ export class WorkspaceStatusMongoDbCollection implements DbCollection<WorkspaceS
for (const key of Object.keys(ops)) {
const op = (ops as any)[key]
if (['$inc', '$set'].includes(key)) {
if (key === '$inc') {
res[key] = {}
for (const incKey of Object.keys(op)) {
res[key][`status.${incKey}`] = op[incKey]
for (const opKey of Object.keys(op)) {
res[key][`status.${opKey}`] = op[opKey]
}
} else if (key === '$set') {
for (const opKey of Object.keys(op)) {
res[`status.${opKey}`] = op[opKey]
}
} else {
res[`status.${key}`] = op