feat: ignore dupe subscriptions

This commit is contained in:
Ricardo Arturo Cabral Mejía
2022-12-19 10:01:04 -05:00
parent f561e6270f
commit 433b7f8707
2 changed files with 20 additions and 12 deletions

View File

@ -39,7 +39,7 @@ export class SubscribeMessageHandler implements IMessageHandler, IAbortable {
const reason = this.canSubscribe(subscriptionId, filters) const reason = this.canSubscribe(subscriptionId, filters)
if (reason) { if (reason) {
debug('subscription %s with %o rejected: %s', subscriptionId, filters, reason) debug('subscription %s with %o rejected: %s', subscriptionId, filters, reason)
this.webSocket.emit(WebSocketAdapterEvent.Message, createNoticeMessage(`Subscription request rejected: ${reason}`)) this.webSocket.emit(WebSocketAdapterEvent.Message, createNoticeMessage(`Subscription rejected: ${reason}`))
return return
} }
@ -85,12 +85,18 @@ export class SubscribeMessageHandler implements IMessageHandler, IAbortable {
} }
private canSubscribe(subscriptionId: SubscriptionId, filters: SubscriptionFilter[]): string | undefined { private canSubscribe(subscriptionId: SubscriptionId, filters: SubscriptionFilter[]): string | undefined {
const subscriptions = this.webSocket.getSubscriptions()
const existingSubscription = subscriptions.get(subscriptionId)
if (existingSubscription?.length && equals(filters, existingSubscription)) {
return `Duplicate subscription ${subscriptionId}: Ignorning`
}
const maxSubscriptions = this.settings().limits.client.subscription.maxSubscriptions const maxSubscriptions = this.settings().limits.client.subscription.maxSubscriptions
if (maxSubscriptions > 0) { if (maxSubscriptions > 0
const subscriptions = this.webSocket.getSubscriptions() && !existingSubscription?.length && subscriptions.size + 1 > maxSubscriptions
if (!subscriptions.has(subscriptionId) && subscriptions.size + 1 > maxSubscriptions) { ) {
return `Too many subscriptions: Number of subscriptions must be less than or equal to ${maxSubscriptions}` return `Too many subscriptions: Number of subscriptions must be less than or equal to ${maxSubscriptions}`
}
} }
const maxFilters = this.settings().limits.client.subscription.maxFilters const maxFilters = this.settings().limits.client.subscription.maxFilters

View File

@ -30,7 +30,7 @@ const toDbEvent = (event: Event) => ({
describe('SubscribeMessageHandler', () => { describe('SubscribeMessageHandler', () => {
const subscriptionId: SubscriptionId = 'subscriptionId' const subscriptionId: SubscriptionId = 'subscriptionId'
let filters: SubscriptionFilter[] let filters: SubscriptionFilter[]
let subscriptions: Map<SubscriptionId, Set<SubscriptionFilter>> let subscriptions: Map<SubscriptionId, SubscriptionFilter[]>
let handler: IMessageHandler & IAbortable let handler: IMessageHandler & IAbortable
let webSocket: IWebSocketAdapter let webSocket: IWebSocketAdapter
let eventRepository: IEventRepository let eventRepository: IEventRepository
@ -94,7 +94,7 @@ describe('SubscribeMessageHandler', () => {
await handler.handleMessage(message) await handler.handleMessage(message)
expect(webSocketOnMessageStub).to.have.been.calledOnceWithExactly( expect(webSocketOnMessageStub).to.have.been.calledOnceWithExactly(
['NOTICE', 'Subscription request rejected: reason'] ['NOTICE', 'Subscription rejected: reason']
) )
}) })
@ -273,7 +273,7 @@ describe('SubscribeMessageHandler', () => {
expect((handler as any).canSubscribe(subscriptionId, filters)).to.be.undefined expect((handler as any).canSubscribe(subscriptionId, filters)).to.be.undefined
}) })
it('returns undefined if client is resubscribing', () => { it('returns reason if client is sending a duplicate subscription', () => {
settingsFactory.returns({ settingsFactory.returns({
limits: { limits: {
client: { client: {
@ -283,9 +283,11 @@ describe('SubscribeMessageHandler', () => {
}, },
}, },
}) })
subscriptions.set(subscriptionId, new Set([{}])) filters = [{ authors: ['aa'] }]
subscriptions.set(subscriptionId, filters)
expect((handler as any).canSubscribe(subscriptionId, filters)).to.be.undefined expect((handler as any).canSubscribe(subscriptionId, filters))
.to.equal('Duplicate subscription subscriptionId: Ignorning')
}) })
it('returns reason if client subscriptions exceed limits', () => { it('returns reason if client subscriptions exceed limits', () => {
@ -298,7 +300,7 @@ describe('SubscribeMessageHandler', () => {
}, },
}, },
}) })
subscriptions.set('other-sub', new Set()) subscriptions.set('other-sub', [])
expect((handler as any).canSubscribe(subscriptionId, filters)).to.equal('Too many subscriptions: Number of subscriptions must be less than or equal to 1') expect((handler as any).canSubscribe(subscriptionId, filters)).to.equal('Too many subscriptions: Number of subscriptions must be less than or equal to 1')
}) })