feat: add rate limit configuration
Signed-off-by: Kai Dubauskas <kai.dubauskas@doordash.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-notifications-backend-module-slack': patch
|
||||
---
|
||||
|
||||
The rate limit is now a config variable
|
||||
@@ -953,4 +953,65 @@ describe('SlackNotificationProcessor', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when rate limit is not configured', () => {
|
||||
it('should use default rate limit of 10 messages per minute', async () => {
|
||||
const slack = new WebClient();
|
||||
|
||||
const processor = SlackNotificationProcessor.fromConfig(config, {
|
||||
auth,
|
||||
logger,
|
||||
catalog: catalogServiceMock({
|
||||
entities: DEFAULT_ENTITIES_RESPONSE.items,
|
||||
}),
|
||||
slack,
|
||||
})[0];
|
||||
|
||||
await processor.processOptions({
|
||||
recipients: { type: 'entity', entityRef: 'group:default/mock' },
|
||||
payload: { title: 'notification' },
|
||||
});
|
||||
|
||||
expect(slack.chat.postMessage).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when rate limit is configured', () => {
|
||||
it('should use custom rate limit value', async () => {
|
||||
const slack = new WebClient();
|
||||
const rateLimitConfig = mockServices.rootConfig({
|
||||
data: {
|
||||
app: {
|
||||
baseUrl: 'https://example.org',
|
||||
},
|
||||
notifications: {
|
||||
processors: {
|
||||
slack: [
|
||||
{
|
||||
token: 'mock-token',
|
||||
rateLimit: 5,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const processor = SlackNotificationProcessor.fromConfig(rateLimitConfig, {
|
||||
auth,
|
||||
logger,
|
||||
catalog: catalogServiceMock({
|
||||
entities: DEFAULT_ENTITIES_RESPONSE.items,
|
||||
}),
|
||||
slack,
|
||||
})[0];
|
||||
|
||||
await processor.processOptions({
|
||||
recipients: { type: 'entity', entityRef: 'group:default/mock' },
|
||||
payload: { title: 'notification' },
|
||||
});
|
||||
|
||||
expect(slack.chat.postMessage).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -68,10 +68,12 @@ export class SlackNotificationProcessor implements NotificationProcessor {
|
||||
const slack = options.slack ?? new WebClient(token);
|
||||
const broadcastChannels = c.getOptionalStringArray('broadcastChannels');
|
||||
const username = c.getOptionalString('username');
|
||||
const rateLimit = c.getOptionalNumber('rateLimit');
|
||||
return new SlackNotificationProcessor({
|
||||
slack,
|
||||
broadcastChannels,
|
||||
username,
|
||||
rateLimit,
|
||||
...options,
|
||||
});
|
||||
});
|
||||
@@ -84,9 +86,17 @@ export class SlackNotificationProcessor implements NotificationProcessor {
|
||||
catalog: CatalogService;
|
||||
broadcastChannels?: string[];
|
||||
username?: string;
|
||||
rateLimit?: number;
|
||||
}) {
|
||||
const { auth, catalog, logger, slack, broadcastChannels, username } =
|
||||
options;
|
||||
const {
|
||||
auth,
|
||||
catalog,
|
||||
logger,
|
||||
slack,
|
||||
broadcastChannels,
|
||||
username,
|
||||
rateLimit,
|
||||
} = options;
|
||||
this.logger = logger;
|
||||
this.catalog = catalog;
|
||||
this.auth = auth;
|
||||
@@ -134,7 +144,7 @@ export class SlackNotificationProcessor implements NotificationProcessor {
|
||||
);
|
||||
|
||||
const throttle = pThrottle({
|
||||
limit: 10,
|
||||
limit: rateLimit ?? 10,
|
||||
interval: durationToMilliseconds({ minutes: 1 }),
|
||||
});
|
||||
const throttled = throttle((opts: ChatPostMessageArguments) =>
|
||||
|
||||
Reference in New Issue
Block a user