Skip to content

Commit 86ecf29

Browse files
authored
Merge pull request #138 from devsapp/fileManager-remove
feat: add upgrade model support in fileManager remove operation
2 parents 0cb5e83 + fce20c5 commit 86ecf29

7 files changed

Lines changed: 520 additions & 133 deletions

File tree

__tests__/ut/commands/artModelService_test.ts

Lines changed: 92 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { ArtModelService } from '../../../src/subCommands/model/fileManager';
22
import { IInputs } from '../../../src/interface';
33
import DevClient from '@alicloud/devs20230714';
44
import { sleep } from '../../../src/utils';
5-
import { initClient, checkModelStatus } from '../../../src/subCommands/model/utils';
5+
import { initClient } from '../../../src/subCommands/model/utils';
66

77
// Mock dependencies
88
jest.mock('../../../src/logger', () => {
@@ -33,11 +33,13 @@ jest.mock('../../../src/utils');
3333
jest.mock('../../../src/subCommands/model/utils', () => {
3434
const originalModule = jest.requireActual('../../../src/subCommands/model/utils');
3535
const mockRetryFileManagerRsyncAndCheckStatus = jest.fn();
36+
const mockRetryFileManagerRm = jest.fn();
3637
return {
3738
__esModule: true,
3839
...originalModule,
3940
retryWithFileManager: jest.fn((command, fn) => fn()),
4041
retryFileManagerRsyncAndCheckStatus: mockRetryFileManagerRsyncAndCheckStatus,
42+
retryFileManagerRm: mockRetryFileManagerRm,
4143
initClient: jest.fn(),
4244
checkModelStatus: jest.fn(),
4345
extractOssMountDir: jest.fn(),
@@ -81,6 +83,13 @@ describe('ArtModelService', () => {
8183
};
8284

8385
artModelService = new ArtModelService(mockInputs);
86+
// 添加 createResource 属性以防止错误
87+
Object.defineProperty(artModelService, 'createResource', {
88+
value: { history: [], oss: {}, nas: {}, vpc: {}, sls: {} },
89+
writable: true,
90+
enumerable: true,
91+
configurable: true,
92+
});
8493
});
8594

8695
afterEach(() => {
@@ -203,8 +212,8 @@ describe('ArtModelService', () => {
203212
},
204213
],
205214
},
206-
storage: 'nas',
207215
nasMountPoints: [{ mountDir: '/mnt/test' }],
216+
ossMountPoints: [{ mountDir: '/mnt/oss' }],
208217
role: 'acs:ram::123456789:role/aliyundevsdefaultrole',
209218
region: 'cn-hangzhou',
210219
vpcConfig: {},
@@ -218,21 +227,19 @@ describe('ArtModelService', () => {
218227
},
219228
} as any);
220229

221-
mockDevClient.fileManagerRsync.mockResolvedValue({
222-
body: {
223-
success: true,
224-
data: {
225-
taskID: 'task-123',
226-
},
227-
requestId: 'req-123',
228-
},
229-
} as any);
230-
231-
// ArtModelService内部会调用checkModelStatus,所以我们需要模拟它
232-
(checkModelStatus as jest.Mock).mockResolvedValue(undefined);
230+
// 现在使用重试函数,我们需要模拟重试函数成功执行
231+
(
232+
require('../../../src/subCommands/model/utils')
233+
.retryFileManagerRsyncAndCheckStatus as jest.Mock
234+
).mockResolvedValue(undefined);
233235

234236
// 成功下载应该正常完成而不抛出异常
235237
await expect(artModelService.downloadModel(name, params)).resolves.toBeUndefined();
238+
239+
// 验证重试函数被调用
240+
expect(
241+
require('../../../src/subCommands/model/utils').retryFileManagerRsyncAndCheckStatus,
242+
).toHaveBeenCalled();
236243
});
237244

238245
it('should handle download error from fileManagerRsync', async () => {
@@ -253,8 +260,8 @@ describe('ArtModelService', () => {
253260
},
254261
],
255262
},
256-
storage: 'nas',
257263
nasMountPoints: [{ mountDir: '/mnt/test' }],
264+
ossMountPoints: [{ mountDir: '/mnt/oss' }],
258265
role: 'acs:ram::123456789:role/aliyundevsdefaultrole',
259266
region: 'cn-hangzhou',
260267
vpcConfig: {},
@@ -297,8 +304,8 @@ describe('ArtModelService', () => {
297304
],
298305
timeout: 10, // 设置较小的超时值以便测试
299306
},
300-
storage: 'nas',
301307
nasMountPoints: [{ mountDir: '/mnt/test' }],
308+
ossMountPoints: [{ mountDir: '/mnt/oss' }],
302309
role: 'acs:ram::123456789:role/aliyundevsdefaultrole',
303310
region: 'cn-hangzhou',
304311
vpcConfig: {},
@@ -312,30 +319,6 @@ describe('ArtModelService', () => {
312319
},
313320
} as any);
314321

315-
mockDevClient.fileManagerRsync.mockResolvedValue({
316-
body: {
317-
success: true,
318-
data: {
319-
taskID: 'task-123',
320-
},
321-
requestId: 'req-123',
322-
},
323-
} as any);
324-
325-
// 模拟超时情况 - 任务永远不会完成
326-
mockDevClient.getFileManagerTask.mockResolvedValue({
327-
body: {
328-
data: {
329-
finished: false,
330-
startTime: Date.now() - 50 * 60 * 1000, // 50分钟前开始
331-
progress: {
332-
currentBytes: 512,
333-
totalBytes: 1024,
334-
},
335-
},
336-
},
337-
} as any);
338-
339322
// 现在使用重试函数,我们需要模拟重试函数抛出超时错误
340323
(
341324
require('../../../src/subCommands/model/utils')
@@ -364,8 +347,8 @@ describe('ArtModelService', () => {
364347
},
365348
],
366349
},
367-
storage: 'nas',
368350
nasMountPoints: [{ mountDir: '/mnt/test' }],
351+
ossMountPoints: [{ mountDir: '/mnt/oss' }],
369352
role: 'acs:ram::123456789:role/aliyundevsdefaultrole',
370353
region: 'cn-hangzhou',
371354
vpcConfig: {},
@@ -379,16 +362,6 @@ describe('ArtModelService', () => {
379362
},
380363
} as any);
381364

382-
mockDevClient.fileManagerRsync.mockResolvedValue({
383-
body: {
384-
success: true,
385-
data: {
386-
taskID: 'task-123',
387-
},
388-
requestId: 'req-123',
389-
},
390-
} as any);
391-
392365
// 现在使用重试函数,我们需要模拟重试函数抛出错误
393366
(
394367
require('../../../src/subCommands/model/utils')
@@ -442,8 +415,8 @@ describe('ArtModelService', () => {
442415
],
443416
conflictResolution: 'overwrite', // 这个值应该被环境变量覆盖
444417
},
445-
storage: 'nas',
446418
nasMountPoints: [{ mountDir: '/mnt/test' }],
419+
ossMountPoints: [{ mountDir: '/mnt/oss' }],
447420
role: 'acs:ram::123456789:role/aliyundevsdefaultrole',
448421
region: 'cn-hangzhou',
449422
vpcConfig: {},
@@ -461,16 +434,6 @@ describe('ArtModelService', () => {
461434
},
462435
} as any);
463436

464-
mockDevClient.fileManagerRsync.mockResolvedValue({
465-
body: {
466-
success: true,
467-
data: {
468-
taskID: 'task-123',
469-
},
470-
requestId: 'req-123',
471-
},
472-
} as any);
473-
474437
// 现在使用重试函数,我们需要模拟重试函数成功执行
475438
(
476439
require('../../../src/subCommands/model/utils')
@@ -518,31 +481,16 @@ describe('ArtModelService', () => {
518481
],
519482
},
520483
nasMountPoints: [{ mountDir: '/mnt/test' }],
484+
ossMountPoints: [{ mountDir: '/mnt/oss' }],
521485
role: 'acs:ram::123456789:role/aliyundevsdefaultrole',
522486
region: 'cn-hangzhou',
523487
vpcConfig: {},
524488
};
525489

526-
mockDevClient.fileManagerRm.mockResolvedValue({
527-
body: {
528-
success: true,
529-
data: {
530-
taskID: 'task-123',
531-
},
532-
requestId: 'req-123',
533-
},
534-
} as any);
535-
536-
// 模拟 getFileManagerTask 返回成功状态
537-
mockDevClient.getFileManagerTask.mockResolvedValue({
538-
body: {
539-
data: {
540-
finished: true,
541-
success: true,
542-
},
543-
requestId: 'req-456',
544-
},
545-
} as any);
490+
// 现在使用重试函数,我们需要模拟重试函数成功执行
491+
(
492+
require('../../../src/subCommands/model/utils').retryFileManagerRm as jest.Mock
493+
).mockResolvedValue({ success: true, fileName: 'file1.txt' });
546494

547495
// 添加 removeFileManagerTasks 的模拟
548496
mockDevClient.removeFileManagerTasks.mockResolvedValue({
@@ -555,6 +503,9 @@ describe('ArtModelService', () => {
555503

556504
// 成功移除应该正常完成
557505
await expect(artModelService.removeModel(name, params)).resolves.toBeUndefined();
506+
507+
// 验证重试函数被调用
508+
expect(require('../../../src/subCommands/model/utils').retryFileManagerRm).toHaveBeenCalled();
558509
});
559510

560511
it('should handle remove failure', async () => {
@@ -572,35 +523,66 @@ describe('ArtModelService', () => {
572523
],
573524
},
574525
nasMountPoints: [{ mountDir: '/mnt/test' }],
526+
ossMountPoints: [{ mountDir: '/mnt/oss' }],
575527
role: 'acs:ram::123456789:role/aliyundevsdefaultrole',
576528
region: 'cn-hangzhou',
577529
vpcConfig: {},
578530
};
579531

580-
mockDevClient.fileManagerRm.mockResolvedValue({
581-
body: {
582-
success: true,
583-
data: {
584-
taskID: 'task-123',
532+
// 现在使用重试函数,我们需要模拟重试函数返回失败
533+
(
534+
require('../../../src/subCommands/model/utils').retryFileManagerRm as jest.Mock
535+
).mockResolvedValue({ success: false, fileName: 'file1.txt', error: 'Remove failed' });
536+
537+
// 移除失败应该抛出异常
538+
await expect(artModelService.removeModel(name, params)).rejects.toThrow();
539+
});
540+
541+
it('should handle remove with upgrade files', async () => {
542+
const name = 'test-project$test-env$test-function';
543+
const params = {
544+
modelConfig: {
545+
target: {
546+
uri: 'nas://auto',
547+
},
548+
files: [
549+
{
550+
source: { path: 'file1.txt' },
551+
target: { path: 'file1.txt' },
552+
},
553+
],
554+
upgrade: {
555+
history: {
556+
'v1.0': '/mnt/test/v1.0/file1.txt',
557+
},
585558
},
586-
requestId: 'req-123',
587559
},
588-
} as any);
560+
nasMountPoints: [{ mountDir: '/mnt/test' }],
561+
ossMountPoints: [{ mountDir: '/mnt/oss' }],
562+
role: 'acs:ram::123456789:role/aliyundevsdefaultrole',
563+
region: 'cn-hangzhou',
564+
vpcConfig: {},
565+
};
589566

590-
// 模拟 getFileManagerTask 返回错误状态
591-
mockDevClient.getFileManagerTask.mockResolvedValue({
567+
// 现在使用重试函数,我们需要模拟重试函数成功执行
568+
(
569+
require('../../../src/subCommands/model/utils').retryFileManagerRm as jest.Mock
570+
).mockResolvedValue({ success: true, fileName: 'file1.txt' });
571+
572+
// 添加 removeFileManagerTasks 的模拟
573+
mockDevClient.removeFileManagerTasks.mockResolvedValue({
592574
body: {
593-
data: {
594-
finished: true,
595-
success: false,
596-
errorMessage: 'Remove failed',
597-
},
598-
requestId: 'req-456',
575+
success: true,
576+
data: {},
577+
requestId: 'req-999',
599578
},
600579
} as any);
601580

602-
// 移除失败应该抛出异常
603-
await expect(artModelService.removeModel(name, params)).rejects.toThrow();
581+
// 成功移除应该正常完成
582+
await expect(artModelService.removeModel(name, params)).resolves.toBeUndefined();
583+
584+
// 验证重试函数被调用
585+
expect(require('../../../src/subCommands/model/utils').retryFileManagerRm).toHaveBeenCalled();
604586
});
605587
});
606588

@@ -743,5 +725,16 @@ describe('ArtModelService', () => {
743725

744726
expect(result).toBe('file://mnt/custom/file1.txt'); // Should remove leading slash
745727
});
728+
729+
it('should handle mountDir starting with slash', () => {
730+
const result = (artModelService as any)._getDestinationPath(
731+
'nas://auto',
732+
{ target: { path: 'file1.txt' } },
733+
[{ mountDir: '/mnt/nas' }], // mountDir starts with slash
734+
[{ mountDir: '/mnt/oss' }],
735+
);
736+
737+
expect(result).toBe('file://mnt/nas/file1.txt');
738+
});
746739
});
747740
});

__tests__/ut/commands/model_test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@ describe('Model', () => {
411411
conflictResolution: 'overwrite',
412412
mode: 'once',
413413
timeout: 30 * 1000,
414+
upgrade: {},
414415
},
415416
region: 'cn-hangzhou',
416417
functionName: 'test-function',
@@ -502,6 +503,7 @@ describe('Model', () => {
502503
conflictResolution: 'skip',
503504
mode: 'always',
504505
timeout: 60 * 1000,
506+
upgrade: {},
505507
},
506508
region: 'cn-hangzhou',
507509
functionName: 'test-function',

0 commit comments

Comments
 (0)