Skip to content

Commit 4dc0c81

Browse files
author
高魏洪
committed
fix: deploy updateFunction error
1 parent 221811f commit 4dc0c81

6 files changed

Lines changed: 80 additions & 44 deletions

File tree

__tests__/ut/commands/deploy/impl/function_test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ describe('Service', () => {
237237
{
238238
slsAuto: false,
239239
type: 'config',
240+
removeScalingConfig: expect.any(Function)
240241
},
241242
);
242243
});
@@ -308,6 +309,7 @@ describe('Service', () => {
308309
{
309310
slsAuto: false,
310311
type: 'code',
312+
removeScalingConfig: expect.any(Function)
311313
},
312314
);
313315
});

__tests__/ut/resources/fc/index_test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ describe('FC', () => {
171171
mockFc20230330Client.untagResources.mockResolvedValue({});
172172
mockFc20230330Client.tagResources.mockResolvedValue({});
173173

174-
await fc.deployFunction(mockConfig, { slsAuto: false, type: undefined });
174+
await fc.deployFunction(mockConfig, { slsAuto: false, type: undefined, removeScalingConfig: null });
175175

176176
expect(mockFc20230330Client.untagResources).toHaveBeenCalled();
177177
expect(mockFc20230330Client.tagResources).toHaveBeenCalled();
@@ -181,7 +181,7 @@ describe('FC', () => {
181181
mockConfig.tags = Array(21).fill({ key: 'tag', value: 'value' });
182182

183183
await expect(
184-
fc.deployFunction(mockConfig, { slsAuto: false, type: undefined }),
184+
fc.deployFunction(mockConfig, { slsAuto: false, type: undefined, removeScalingConfig: null }),
185185
).rejects.toThrow('The number of tags cannot exceed 20');
186186
});
187187

@@ -192,7 +192,7 @@ describe('FC', () => {
192192
];
193193

194194
await expect(
195-
fc.deployFunction(mockConfig, { slsAuto: false, type: undefined }),
195+
fc.deployFunction(mockConfig, { slsAuto: false, type: undefined, removeScalingConfig: null }),
196196
).rejects.toThrow('The tag keys must be unique');
197197
});
198198
});

src/resources/fc/error-code.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,15 @@ export const isFunctionStateWaitTimedOut = (ex) => {
5151
}
5252
return false;
5353
};
54+
55+
export const isFunctionScalingConfigError = (ex, localGPUType, remoteGPUType) => {
56+
if (
57+
ex.message.includes('GPU type should not be changed with resident scaling config') ||
58+
ex.message.includes(
59+
`function gpu type '${localGPUType}' doesn't match resident pool gpu type '${remoteGPUType}'`,
60+
)
61+
) {
62+
return true;
63+
}
64+
return false;
65+
};

src/resources/fc/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import {
5353
isInvalidArgument,
5454
isFailedState,
5555
isFunctionStateWaitTimedOut,
56+
isFunctionScalingConfigError,
5657
} from './error-code';
5758
import { isCustomContainerRuntime, isCustomRuntime, computeLocalAuto } from './impl/utils';
5859
import replaceFunctionConfig from './impl/replace-function-config';
@@ -175,7 +176,7 @@ export default class FC extends FC_Client {
175176
/**
176177
* 创建或者修改函数
177178
*/
178-
async deployFunction(config: IFunction, { slsAuto, type }): Promise<void> {
179+
async deployFunction(config: IFunction, { slsAuto, type, removeScalingConfig }): Promise<void> {
179180
logger.debug(`Deploy function use config:\n${JSON.stringify(config, null, 2)}`);
180181
let needUpdate = false;
181182
let remoteConfig = null;
@@ -302,11 +303,18 @@ export default class FC extends FC_Client {
302303
*/
303304
const { project, logstore } = (config.logConfig || {}) as ILogConfig;
304305
const retrySls = slsAuto && isSlsNotExistException(project, logstore, ex);
306+
const localGPUType = config.gpuConfig?.gpuType;
307+
const remoteGPUType = remoteConfig.gpuConfig?.gpuType;
305308
if (retrySls) {
306309
if (calculateRetryTime(3)) {
307310
throw ex;
308311
}
309312
retryInterval = 5;
313+
} else if (
314+
isInvalidArgument(ex) &&
315+
isFunctionScalingConfigError(ex, localGPUType, remoteGPUType)
316+
) {
317+
removeScalingConfig();
310318
} else if (
311319
isAccessDenied(ex) ||
312320
isInvalidArgument(ex) ||

src/subCommands/deploy/impl/function.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { ICredentials } from '@serverless-devs/component-interface';
2121
import { calculateCRC64, getFileSize } from '../../../utils';
2222
import OSS from '../../../resources/oss';
2323
import { setNodeModulesBinPermissions } from '../../../resources/fc/impl/utils';
24+
import ScalingConfig from './scaling_config';
2425

2526
type IType = 'code' | 'config' | boolean;
2627
interface IOpts {
@@ -38,6 +39,8 @@ export default class Service extends Base {
3839
createResource: Record<string, any> = {};
3940
acr: Acr;
4041
codeChecksum: string;
42+
scalingConfig: ScalingConfig;
43+
qualifier: string;
4144

4245
constructor(inputs: IInputs, opts: IOpts) {
4346
super(inputs, opts.yes);
@@ -49,6 +52,13 @@ export default class Service extends Base {
4952
this.type = opts.type;
5053
this.skipPush = opts.skipPush;
5154
logger.debug(`deploy function type: ${this.type}`);
55+
this.scalingConfig = new ScalingConfig(inputs, {
56+
yes: opts.yes,
57+
});
58+
this.qualifier =
59+
_.get(inputs.props, 'provisionConfig.qualifier') ||
60+
_.get(inputs.props, 'scalingConfig.qualifier') ||
61+
'LATEST';
5262

5363
this.local = _.cloneDeep(inputs.props);
5464
_.unset(this.local, 'region');
@@ -84,6 +94,7 @@ export default class Service extends Base {
8494
const { local, remote } = await FC.replaceFunctionConfig(this.local, this.remote);
8595
this.local = local;
8696
this.remote = remote;
97+
this.scalingConfig.before();
8798

8899
await this._plan();
89100
}
@@ -122,9 +133,12 @@ export default class Service extends Base {
122133
logger.debug('sessionAffinityConfig', config.sessionAffinityConfig);
123134
config.sessionAffinityConfig = JSON.stringify(config.sessionAffinityConfig);
124135
}
136+
const removeScalingConfig = async () =>
137+
await this.scalingConfig.removeScalingConfig(this.qualifier);
125138
await this.fcSdk.deployFunction(config, {
126139
slsAuto: !_.isEmpty(this.createResource.sls),
127140
type: this.type,
141+
removeScalingConfig,
128142
});
129143
return this.needDeploy;
130144
}

src/subCommands/deploy/impl/scaling_config.ts

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,46 @@ export default class ScalingConfig extends Base {
123123
}
124124
}
125125

126+
/**
127+
* 删除弹性配置
128+
*/
129+
async removeScalingConfig(qualifier: string) {
130+
try {
131+
if (!_.isEmpty(this.remote)) {
132+
logger.info(`Remove remote scalingConfig of ${this.functionName}/${qualifier}`);
133+
await this.fcSdk.removeFunctionScalingConfig(this.functionName, qualifier);
134+
135+
// 等待弹性配置实例数降至0
136+
const maxRetries = 12;
137+
for (let index = 0; index < maxRetries; index++) {
138+
// eslint-disable-next-line no-await-in-loop
139+
const result = await this.fcSdk.getFunctionScalingConfig(this.functionName, qualifier);
140+
const { currentInstances } = result || {};
141+
142+
if (!currentInstances || currentInstances === 0) {
143+
logger.info(`ScalingConfig of ${this.functionName}/${qualifier} removed successfully`);
144+
return;
145+
}
146+
147+
logger.info(
148+
`waiting ${this.functionName}/${qualifier} scaling currentInstances to 0 ...`,
149+
);
150+
// eslint-disable-next-line no-await-in-loop
151+
await sleep(5);
152+
}
153+
154+
logger.warn(
155+
`Timeout waiting for scalingConfig of ${this.functionName}/${qualifier} to be removed`,
156+
);
157+
}
158+
} catch (ex) {
159+
logger.error(
160+
`Remove remote scalingConfig of ${this.functionName}/${qualifier} error: ${ex.message}`,
161+
);
162+
throw ex;
163+
}
164+
}
165+
126166
/**
127167
* 等待弹性配置实例就绪
128168
*/
@@ -175,46 +215,6 @@ export default class ScalingConfig extends Base {
175215
);
176216
}
177217

178-
/**
179-
* 删除弹性配置
180-
*/
181-
private async removeScalingConfig(qualifier: string) {
182-
try {
183-
if (!_.isEmpty(this.remote)) {
184-
logger.info(`Remove remote scalingConfig of ${this.functionName}/${qualifier}`);
185-
await this.fcSdk.removeFunctionScalingConfig(this.functionName, qualifier);
186-
187-
// 等待弹性配置实例数降至0
188-
const maxRetries = 12;
189-
for (let index = 0; index < maxRetries; index++) {
190-
// eslint-disable-next-line no-await-in-loop
191-
const result = await this.fcSdk.getFunctionScalingConfig(this.functionName, qualifier);
192-
const { currentInstances } = result || {};
193-
194-
if (!currentInstances || currentInstances === 0) {
195-
logger.info(`ScalingConfig of ${this.functionName}/${qualifier} removed successfully`);
196-
return;
197-
}
198-
199-
logger.info(
200-
`waiting ${this.functionName}/${qualifier} scaling currentInstances to 0 ...`,
201-
);
202-
// eslint-disable-next-line no-await-in-loop
203-
await sleep(5);
204-
}
205-
206-
logger.warn(
207-
`Timeout waiting for scalingConfig of ${this.functionName}/${qualifier} to be removed`,
208-
);
209-
}
210-
} catch (ex) {
211-
logger.error(
212-
`Remove remote scalingConfig of ${this.functionName}/${qualifier} error: ${ex.message}`,
213-
);
214-
throw ex;
215-
}
216-
}
217-
218218
/**
219219
* 清理弹性配置对象
220220
*/

0 commit comments

Comments
 (0)