Skip to content

Commit cce91bc

Browse files
committed
fix(triggers): manager filter trigger bug
1 parent 53efda7 commit cce91bc

File tree

2 files changed

+159
-35
lines changed

2 files changed

+159
-35
lines changed

__tests__/trigger.manager.test.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,17 @@ describe('Trigger Manager', () => {
7979
path: '/',
8080
method: 'GET',
8181
},
82+
{
83+
function: {
84+
...functionConfig,
85+
86+
functionNamespace: functionConfig.namespace,
87+
functionName: functionConfig.name,
88+
functionQualifier: functionConfig.qualifier,
89+
},
90+
path: '/test',
91+
method: 'GET',
92+
},
8293
],
8394
},
8495
},
@@ -161,6 +172,83 @@ describe('Trigger Manager', () => {
161172
]);
162173
});
163174

175+
test('bulk update triggers', async () => {
176+
const { triggerList } = await client.bulkCreateTriggers(triggers);
177+
178+
expect(triggerList).toEqual([
179+
{
180+
name: functionConfig.name,
181+
triggers: [
182+
{
183+
AddTime: expect.any(String),
184+
AvailableStatus: 'Available',
185+
BindStatus: expect.any(String),
186+
CustomArgument: 'argument',
187+
Enable: 1,
188+
ModTime: expect.any(String),
189+
Qualifier: '$DEFAULT',
190+
ResourceId: expect.any(String),
191+
TriggerAttribute: expect.any(String),
192+
TriggerDesc: '{"cron":"* * */4 * * * *"}',
193+
TriggerName: 'timer1',
194+
Type: 'timer',
195+
triggerType: 'timer',
196+
},
197+
{
198+
AddTime: expect.any(String),
199+
AvailableStatus: expect.any(String),
200+
BindStatus: expect.any(String),
201+
CustomArgument: '',
202+
Enable: 1,
203+
ModTime: expect.any(String),
204+
Qualifier: '$DEFAULT',
205+
ResourceId: expect.any(String),
206+
TriggerAttribute: expect.any(String),
207+
TriggerDesc: expect.stringContaining('"event":"cos:ObjectCreated:*"'),
208+
TriggerName: expect.stringContaining('cos'),
209+
Type: 'cos',
210+
triggerType: 'cos',
211+
},
212+
{
213+
namespace: functionConfig.namespace,
214+
functionName: functionConfig.name,
215+
qualifier: functionConfig.qualifier,
216+
topicId: '6e60b6c7-a98e-4fc8-8ba8-bdfe4ab9c245',
217+
maxWait: 60,
218+
maxSize: 100,
219+
enable: true,
220+
triggerType: 'cls',
221+
},
222+
{
223+
namespace: functionConfig.namespace,
224+
functionName: functionConfig.name,
225+
qualifier: functionConfig.qualifier,
226+
loadBalanceId: expect.stringContaining('lb-'),
227+
listenerId: expect.stringContaining('lbl-'),
228+
locationId: expect.stringContaining('loc-'),
229+
domain: expect.any(String),
230+
protocol: 'HTTP',
231+
port: 80,
232+
url: '/',
233+
weight: 20,
234+
triggerType: 'clb',
235+
},
236+
{
237+
created: expect.any(Boolean),
238+
serviceId: expect.stringContaining('service-'),
239+
serviceName: 'serverless',
240+
subDomain: expect.stringContaining('.apigw.tencentcs.com'),
241+
url: expect.stringContaining('.apigw.tencentcs.com'),
242+
protocols: 'http',
243+
environment: 'release',
244+
apiList: expect.any(Array),
245+
triggerType: 'apigw',
246+
},
247+
],
248+
},
249+
]);
250+
});
251+
164252
test('bulk remove triggers', async () => {
165253
const res = await client.clearScfTriggers({
166254
name: functionConfig.name,

src/modules/triggers/manager.ts

Lines changed: 71 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -103,37 +103,23 @@ export class TriggerManager {
103103
oldList: TriggerDetail[];
104104
}) {
105105
const deleteList: (TriggerDetail | null)[] = deepClone(oldList);
106-
const createList: (NewTriggerInputs | null)[] = deepClone(events);
107106
const deployList: (TriggerDetail | null)[] = [];
108-
const updateList: (NewTriggerInputs | null)[] = [];
109107

110-
for (let index = 0; index < events.length; index++) {
111-
const event = events[index];
112-
const { type } = event;
113-
const TriggerClass = TRIGGERS[type];
114-
const triggerInstance: BaseTrigger = new TriggerClass({
115-
credentials: this.credentials,
116-
region: this.region,
117-
});
118-
const { triggerKey } = await triggerInstance.formatInputs({
119-
region: this.region,
120-
inputs: {
121-
namespace: namespace,
122-
functionName: name,
123-
...event,
124-
},
125-
});
126-
deployList[index] = {
127-
NeedCreate: true,
128-
Type: type,
129-
triggerType: type,
130-
...event,
131-
};
132-
133-
for (let i = 0; i < oldList.length; i++) {
134-
const oldTrigger = oldList[i];
108+
const compareTriggerKey = async ({
109+
triggerType,
110+
newIndex,
111+
newKey,
112+
oldTriggerList,
113+
}: {
114+
triggerType: string;
115+
newIndex: number;
116+
newKey: string;
117+
oldTriggerList: TriggerDetail[];
118+
}) => {
119+
for (let i = 0; i < oldTriggerList.length; i++) {
120+
const oldTrigger = oldTriggerList[i];
135121
// 如果类型不一致或者已经比较过(key值一致),则继续下一次循环
136-
if (oldTrigger.Type !== type || oldTrigger.compared === true) {
122+
if (oldTrigger.Type !== triggerType || oldTrigger.compared === true) {
137123
continue;
138124
}
139125
const OldTriggerClass = TRIGGERS[oldTrigger.Type];
@@ -144,29 +130,79 @@ export class TriggerManager {
144130
const oldKey = await oldTriggerInstance.getKey(oldTrigger);
145131

146132
// 如果 key 不一致则继续下一次循环
147-
if (oldKey !== triggerKey) {
133+
if (oldKey !== newKey) {
148134
continue;
149135
}
150136

151137
oldList[i].compared = true;
152138

153139
deleteList[i] = null;
154-
updateList.push(createList[index]);
155-
if (CAN_UPDATE_TRIGGER.indexOf(type) === -1) {
156-
createList[index] = null;
157-
deployList[index] = {
140+
141+
if (CAN_UPDATE_TRIGGER.indexOf(triggerType) === -1) {
142+
deployList[newIndex] = {
158143
NeedCreate: false,
159144
...oldTrigger,
160145
};
161146
}
162147
// 如果找到 key 值一样的,直接跳出循环
163148
break;
164149
}
150+
};
151+
152+
for (let index = 0; index < events.length; index++) {
153+
const event = events[index];
154+
const { type } = event;
155+
const TriggerClass = TRIGGERS[type];
156+
const triggerInstance: BaseTrigger = new TriggerClass({
157+
credentials: this.credentials,
158+
region: this.region,
159+
});
160+
161+
deployList[index] = {
162+
NeedCreate: true,
163+
Type: type,
164+
triggerType: type,
165+
...event,
166+
};
167+
168+
// 需要特殊比较 API 网关触发器,因为一个触发器配置中,可能包含多个 API 触发器
169+
if (type === 'apigw') {
170+
const { parameters = {} } = event;
171+
const { endpoints = [{ path: '/', method: 'ANY' }] } = parameters;
172+
for (const item of endpoints) {
173+
const newKey = await triggerInstance.getKey({
174+
TriggerDesc: {
175+
serviceId: parameters.serviceId,
176+
path: item.path,
177+
method: item.method,
178+
},
179+
});
180+
await compareTriggerKey({
181+
triggerType: type,
182+
newIndex: index,
183+
newKey: newKey,
184+
oldTriggerList: oldList,
185+
});
186+
}
187+
} else {
188+
const { triggerKey } = await triggerInstance.formatInputs({
189+
region: this.region,
190+
inputs: {
191+
namespace: namespace,
192+
functionName: name,
193+
...event,
194+
},
195+
});
196+
await compareTriggerKey({
197+
triggerType: type,
198+
newIndex: index,
199+
newKey: triggerKey,
200+
oldTriggerList: oldList,
201+
});
202+
}
165203
}
166204
return {
167-
updateList,
168205
deleteList: deleteList.filter((item) => item) as TriggerDetail[],
169-
createList: createList.filter((item) => item) as NewTriggerInputs[],
170206
deployList: deployList.map((item) => {
171207
delete item?.compared;
172208
return item as TriggerDetail;

0 commit comments

Comments
 (0)