From a0006f73acc2364ac5528f96cb2cff329eb700f3 Mon Sep 17 00:00:00 2001 From: ankitsridhar16 Date: Fri, 20 Jan 2023 14:55:26 +0530 Subject: [PATCH 1/8] chore: added message types to PubSub Service --- .../src/pubsub/pubsub.service.ts | 6 +++++- .../src/pubsub/subscriptionTopicsDefs.ts | 14 ++++++++++++++ .../{primitive-types.ts => primitiveTypes.ts} | 0 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 packages/hoppscotch-backend/src/pubsub/subscriptionTopicsDefs.ts rename packages/hoppscotch-backend/src/types/{primitive-types.ts => primitiveTypes.ts} (100%) diff --git a/packages/hoppscotch-backend/src/pubsub/pubsub.service.ts b/packages/hoppscotch-backend/src/pubsub/pubsub.service.ts index 475768712..854ef2e92 100644 --- a/packages/hoppscotch-backend/src/pubsub/pubsub.service.ts +++ b/packages/hoppscotch-backend/src/pubsub/pubsub.service.ts @@ -4,6 +4,7 @@ import { default as Redis, RedisOptions } from 'ioredis'; import { RedisPubSub } from 'graphql-redis-subscriptions'; import { PubSub as LocalPubSub } from 'graphql-subscriptions'; +import { MessageType } from './subscriptionTopicsDefs'; /** * RedisPubSub uses JSON parsing for back and forth conversion, which loses Date objects, hence this reviver brings them back @@ -70,7 +71,10 @@ export class PubSubService implements OnModuleInit { return this.pubsub.asyncIterator(topic, options); } - async publish(topic: string, payload: any) { + async publish( + topic: T, + payload: MessageType[T], + ) { await this.pubsub.publish(topic, payload); } } diff --git a/packages/hoppscotch-backend/src/pubsub/subscriptionTopicsDefs.ts b/packages/hoppscotch-backend/src/pubsub/subscriptionTopicsDefs.ts new file mode 100644 index 000000000..c860d55a4 --- /dev/null +++ b/packages/hoppscotch-backend/src/pubsub/subscriptionTopicsDefs.ts @@ -0,0 +1,14 @@ +import { UserEnvironment } from '../user-environment/user-environments.model'; +import { PrimitiveTypes } from '../types/primitiveTypes'; + +// A custom message type that defines the topic and the corresponding payload. +// For every module that publishes a subscription add its type def and the possible subscription type. +export type MessageType = { + [ + topic: `user_environment/${string}/${ + | 'created' + | 'updated' + | 'deleted' + | 'deleted_many'}` + ]: UserEnvironment | PrimitiveTypes; // Returning a number hence having a union with `PrimitiveTypes`. +}; diff --git a/packages/hoppscotch-backend/src/types/primitive-types.ts b/packages/hoppscotch-backend/src/types/primitiveTypes.ts similarity index 100% rename from packages/hoppscotch-backend/src/types/primitive-types.ts rename to packages/hoppscotch-backend/src/types/primitiveTypes.ts From bc55af27a725f08aab75dc643420eeb033f8e3ff Mon Sep 17 00:00:00 2001 From: ankitsridhar16 Date: Fri, 20 Jan 2023 14:56:28 +0530 Subject: [PATCH 2/8] chore: updated user environment to use PubSub instead of SubscriptionHandler --- .../user-environments.module.ts | 2 - .../user-environments.service.spec.ts | 39 +++++++------------ .../user-environments.service.ts | 33 +++++++--------- 3 files changed, 29 insertions(+), 45 deletions(-) diff --git a/packages/hoppscotch-backend/src/user-environment/user-environments.module.ts b/packages/hoppscotch-backend/src/user-environment/user-environments.module.ts index d82a1e899..04f391682 100644 --- a/packages/hoppscotch-backend/src/user-environment/user-environments.module.ts +++ b/packages/hoppscotch-backend/src/user-environment/user-environments.module.ts @@ -5,7 +5,6 @@ import { UserModule } from '../user/user.module'; import { UserEnvsUserResolver } from './user.resolver'; import { UserEnvironmentsResolver } from './user-environments.resolver'; import { UserEnvironmentsService } from './user-environments.service'; -import { SubscriptionHandler } from '../subscription-handler'; @Module({ imports: [PrismaModule, PubSubModule, UserModule], @@ -13,7 +12,6 @@ import { SubscriptionHandler } from '../subscription-handler'; UserEnvironmentsResolver, UserEnvironmentsService, UserEnvsUserResolver, - SubscriptionHandler, ], exports: [UserEnvironmentsService], }) diff --git a/packages/hoppscotch-backend/src/user-environment/user-environments.service.spec.ts b/packages/hoppscotch-backend/src/user-environment/user-environments.service.spec.ts index 894872cde..849b589e1 100644 --- a/packages/hoppscotch-backend/src/user-environment/user-environments.service.spec.ts +++ b/packages/hoppscotch-backend/src/user-environment/user-environments.service.spec.ts @@ -9,19 +9,15 @@ import { USER_ENVIRONMENT_INVALID_ENVIRONMENT_NAME, } from '../errors'; import { PubSubService } from '../pubsub/pubsub.service'; -import { SubscriptionHandler } from '../subscription-handler'; -import { SubscriptionType } from '../types/subscription-types'; const mockPrisma = mockDeep(); const mockPubSub = mockDeep(); -const mockSubscriptionHandler = mockDeep(); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const userEnvironmentsService = new UserEnvironmentsService( mockPrisma, mockPubSub as any, - mockSubscriptionHandler, ); const userPersonalEnvironments = [ @@ -245,9 +241,8 @@ describe('UserEnvironmentsService', () => { false, ); - return expect(mockSubscriptionHandler.publish).toHaveBeenCalledWith( - `user_environment/${result.userUid}`, - SubscriptionType.Created, + return expect(mockPubSub.publish).toHaveBeenCalledWith( + `user_environment/${result.userUid}/created`, result, ); }); @@ -276,9 +271,8 @@ describe('UserEnvironmentsService', () => { true, ); - return expect(mockSubscriptionHandler.publish).toHaveBeenCalledWith( - `user_environment/${result.userUid}`, - SubscriptionType.Created, + return expect(mockPubSub.publish).toHaveBeenCalledWith( + `user_environment/${result.userUid}/created`, result, ); }); @@ -374,9 +368,8 @@ describe('UserEnvironmentsService', () => { '[{}]', ); - return expect(mockSubscriptionHandler.publish).toHaveBeenCalledWith( - `user_environment/${result.id}`, - SubscriptionType.Updated, + return expect(mockPubSub.publish).toHaveBeenCalledWith( + `user_environment/${result.id}/updated`, result, ); }); @@ -404,9 +397,8 @@ describe('UserEnvironmentsService', () => { '[{}]', ); - return expect(mockSubscriptionHandler.publish).toHaveBeenCalledWith( - `user_environment/${result.id}`, - SubscriptionType.Updated, + return expect(mockPubSub.publish).toHaveBeenCalledWith( + `user_environment/${result.id}/updated`, result, ); }); @@ -470,9 +462,8 @@ describe('UserEnvironmentsService', () => { await userEnvironmentsService.deleteUserEnvironment('abc123', 'env1'); - return expect(mockSubscriptionHandler.publish).toHaveBeenCalledWith( - `user_environment/${result.id}`, - SubscriptionType.Deleted, + return expect(mockPubSub.publish).toHaveBeenCalledWith( + `user_environment/${result.id}/deleted`, result, ); }); @@ -486,9 +477,8 @@ describe('UserEnvironmentsService', () => { await userEnvironmentsService.deleteUserEnvironments('abc123'); - return expect(mockSubscriptionHandler.publish).toHaveBeenCalledWith( - `user_environment/abc123`, - SubscriptionType.DeleteMany, + return expect(mockPubSub.publish).toHaveBeenCalledWith( + `user_environment/${'abc123'}/deleted_many`, 1, ); }); @@ -566,9 +556,8 @@ describe('UserEnvironmentsService', () => { await userEnvironmentsService.clearGlobalEnvironments('abc123', 'env1'); - return expect(mockSubscriptionHandler.publish).toHaveBeenCalledWith( - `user_environment/${result.id}`, - SubscriptionType.Updated, + return expect(mockPubSub.publish).toHaveBeenCalledWith( + `user_environment/${result.id}/updated`, result, ); }); diff --git a/packages/hoppscotch-backend/src/user-environment/user-environments.service.ts b/packages/hoppscotch-backend/src/user-environment/user-environments.service.ts index a08549e0c..872395351 100644 --- a/packages/hoppscotch-backend/src/user-environment/user-environments.service.ts +++ b/packages/hoppscotch-backend/src/user-environment/user-environments.service.ts @@ -13,8 +13,6 @@ import { USER_ENVIRONMENT_UPDATE_FAILED, USER_ENVIRONMENT_INVALID_ENVIRONMENT_NAME, } from '../errors'; -import { SubscriptionHandler } from '../subscription-handler'; -import { SubscriptionType } from '../types/subscription-types'; import { stringToJson } from '../utils'; @Injectable() @@ -22,7 +20,6 @@ export class UserEnvironmentsService { constructor( private readonly prisma: PrismaService, private readonly pubsub: PubSubService, - private readonly subscriptionHandler: SubscriptionHandler, ) {} /** @@ -119,9 +116,8 @@ export class UserEnvironmentsService { isGlobal: createdEnvironment.isGlobal, }; // Publish subscription for environment creation - await this.subscriptionHandler.publish( - `user_environment/${userEnvironment.userUid}`, - SubscriptionType.Created, + await this.pubsub.publish( + `user_environment/${userEnvironment.userUid}/created`, userEnvironment, ); return E.right(userEnvironment); @@ -154,9 +150,8 @@ export class UserEnvironmentsService { isGlobal: updatedEnvironment.isGlobal, }; // Publish subscription for environment update - await this.subscriptionHandler.publish( - `user_environment/${updatedUserEnvironment.id}`, - SubscriptionType.Updated, + await this.pubsub.publish( + `user_environment/${updatedUserEnvironment.id}/updated`, updatedUserEnvironment, ); return E.right(updatedUserEnvironment); @@ -196,9 +191,8 @@ export class UserEnvironmentsService { }; // Publish subscription for environment deletion - await this.subscriptionHandler.publish( - `user_environment/${deletedUserEnvironment.id}`, - SubscriptionType.Deleted, + await this.pubsub.publish( + `user_environment/${deletedUserEnvironment.id}/deleted`, deletedUserEnvironment, ); return E.right(true); @@ -220,9 +214,13 @@ export class UserEnvironmentsService { }, }); - await this.subscriptionHandler.publish( - `user_environment/${uid}`, - SubscriptionType.DeleteMany, + // await this.subscriptionHandler.publish( + // `user_environment/${uid}`, + // SubscriptionType.DeleteMany, + // deletedEnvironments.count, + // ); + await this.pubsub.publish( + `user_environment/${uid}/deleted_many`, deletedEnvironments.count, ); @@ -258,9 +256,8 @@ export class UserEnvironmentsService { }; // Publish subscription for environment update - await this.subscriptionHandler.publish( - `user_environment/${updatedUserEnvironment.id}`, - SubscriptionType.Updated, + await this.pubsub.publish( + `user_environment/${updatedUserEnvironment.id}/updated`, updatedUserEnvironment, ); return E.right(updatedUserEnvironment); From 0bed5cd99a519ba39a7d08a8e15680c8291f5189 Mon Sep 17 00:00:00 2001 From: ankitsridhar16 Date: Fri, 20 Jan 2023 14:57:47 +0530 Subject: [PATCH 3/8] chore: removed subscription handler related files --- .../src/subscription-handler.ts | 43 ------------------- .../src/types/custom-module-types.ts | 4 -- .../src/types/subscription-types.ts | 7 --- 3 files changed, 54 deletions(-) delete mode 100644 packages/hoppscotch-backend/src/subscription-handler.ts delete mode 100644 packages/hoppscotch-backend/src/types/custom-module-types.ts delete mode 100644 packages/hoppscotch-backend/src/types/subscription-types.ts diff --git a/packages/hoppscotch-backend/src/subscription-handler.ts b/packages/hoppscotch-backend/src/subscription-handler.ts deleted file mode 100644 index a47730c3b..000000000 --- a/packages/hoppscotch-backend/src/subscription-handler.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { PubSubService } from './pubsub/pubsub.service'; -import { PrimitiveTypes } from './types/primitive-types'; -import { CustomModuleTypes } from './types/custom-module-types'; -import { SubscriptionType } from './types/subscription-types'; - -// Custom generic type to indicate the type of module -type ModuleType = PrimitiveTypes | CustomModuleTypes; - -@Injectable() -export class SubscriptionHandler { - constructor(private readonly pubsub: PubSubService) {} - - /** - * Publishes a subscription using the pubsub module - * @param topic a string containing the "module_name/identifier" - * @param subscriptionType type of subscription being published - * @param moduleType type of the module model being called - * @returns a promise of type void - */ - async publish( - topic: string, - subscriptionType: SubscriptionType, - moduleType: ModuleType, - ) { - switch (subscriptionType) { - case SubscriptionType.Created: - await this.pubsub.publish(`${topic}/created`, moduleType); - break; - case SubscriptionType.Updated: - await this.pubsub.publish(`${topic}/updated`, moduleType); - break; - case SubscriptionType.Deleted: - await this.pubsub.publish(`${topic}/deleted`, moduleType); - break; - case SubscriptionType.DeleteMany: - await this.pubsub.publish(`${topic}/delete_many`, moduleType); - break; - default: - break; - } - } -} diff --git a/packages/hoppscotch-backend/src/types/custom-module-types.ts b/packages/hoppscotch-backend/src/types/custom-module-types.ts deleted file mode 100644 index 5d669e075..000000000 --- a/packages/hoppscotch-backend/src/types/custom-module-types.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { UserEnvironment } from '../user-environment/user-environments.model'; -import { User } from '../user/user.model'; - -export type CustomModuleTypes = UserEnvironment | User; diff --git a/packages/hoppscotch-backend/src/types/subscription-types.ts b/packages/hoppscotch-backend/src/types/subscription-types.ts deleted file mode 100644 index ee7ab75f2..000000000 --- a/packages/hoppscotch-backend/src/types/subscription-types.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Contains constants for the subscription types we use in Subscription Handler -export enum SubscriptionType { - Created = 'created', - Updated = 'updated', - Deleted = 'deleted', - DeleteMany = 'delete_many', -} From 298b960ef75054cd13c83a6cac13edbc46919364 Mon Sep 17 00:00:00 2001 From: ankitsridhar16 Date: Fri, 20 Jan 2023 15:18:04 +0530 Subject: [PATCH 4/8] chore: removed comment --- .../src/user-environment/user-environments.service.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/hoppscotch-backend/src/user-environment/user-environments.service.ts b/packages/hoppscotch-backend/src/user-environment/user-environments.service.ts index 872395351..9daa9cb46 100644 --- a/packages/hoppscotch-backend/src/user-environment/user-environments.service.ts +++ b/packages/hoppscotch-backend/src/user-environment/user-environments.service.ts @@ -214,11 +214,7 @@ export class UserEnvironmentsService { }, }); - // await this.subscriptionHandler.publish( - // `user_environment/${uid}`, - // SubscriptionType.DeleteMany, - // deletedEnvironments.count, - // ); + // Publish subscription for multiple environment deletions await this.pubsub.publish( `user_environment/${uid}/deleted_many`, deletedEnvironments.count, From 6da85fd286b9aa06d6ce4ccc716d8b5104dbe0ce Mon Sep 17 00:00:00 2001 From: ankitsridhar16 Date: Fri, 20 Jan 2023 16:12:45 +0530 Subject: [PATCH 5/8] chore: updated types to def and changed deleted many as a new indexed type --- .../hoppscotch-backend/src/pubsub/pubsub.service.ts | 7 ++----- .../src/pubsub/subscriptionTopicsDefs.ts | 12 ++++-------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/packages/hoppscotch-backend/src/pubsub/pubsub.service.ts b/packages/hoppscotch-backend/src/pubsub/pubsub.service.ts index 854ef2e92..ba86342e1 100644 --- a/packages/hoppscotch-backend/src/pubsub/pubsub.service.ts +++ b/packages/hoppscotch-backend/src/pubsub/pubsub.service.ts @@ -4,7 +4,7 @@ import { default as Redis, RedisOptions } from 'ioredis'; import { RedisPubSub } from 'graphql-redis-subscriptions'; import { PubSub as LocalPubSub } from 'graphql-subscriptions'; -import { MessageType } from './subscriptionTopicsDefs'; +import { TopicDef } from './subscriptionTopicsDefs'; /** * RedisPubSub uses JSON parsing for back and forth conversion, which loses Date objects, hence this reviver brings them back @@ -71,10 +71,7 @@ export class PubSubService implements OnModuleInit { return this.pubsub.asyncIterator(topic, options); } - async publish( - topic: T, - payload: MessageType[T], - ) { + async publish(topic: T, payload: TopicDef[T]) { await this.pubsub.publish(topic, payload); } } diff --git a/packages/hoppscotch-backend/src/pubsub/subscriptionTopicsDefs.ts b/packages/hoppscotch-backend/src/pubsub/subscriptionTopicsDefs.ts index c860d55a4..4a1fbcb27 100644 --- a/packages/hoppscotch-backend/src/pubsub/subscriptionTopicsDefs.ts +++ b/packages/hoppscotch-backend/src/pubsub/subscriptionTopicsDefs.ts @@ -1,14 +1,10 @@ import { UserEnvironment } from '../user-environment/user-environments.model'; -import { PrimitiveTypes } from '../types/primitiveTypes'; // A custom message type that defines the topic and the corresponding payload. // For every module that publishes a subscription add its type def and the possible subscription type. -export type MessageType = { +export type TopicDef = { [ - topic: `user_environment/${string}/${ - | 'created' - | 'updated' - | 'deleted' - | 'deleted_many'}` - ]: UserEnvironment | PrimitiveTypes; // Returning a number hence having a union with `PrimitiveTypes`. + topic: `user_environment/${string}/${'created' | 'updated' | 'deleted'}` + ]: UserEnvironment; + [topic: `user_environment/${string}/deleted_many`]: number; }; From 606e0120ee3f9d9677eb0e80ade2a0dfba467fdd Mon Sep 17 00:00:00 2001 From: ankitsridhar16 Date: Fri, 20 Jan 2023 16:13:35 +0530 Subject: [PATCH 6/8] chore: removed the logic for primitiveTypes as it is unused --- packages/hoppscotch-backend/src/types/primitiveTypes.ts | 1 - 1 file changed, 1 deletion(-) delete mode 100644 packages/hoppscotch-backend/src/types/primitiveTypes.ts diff --git a/packages/hoppscotch-backend/src/types/primitiveTypes.ts b/packages/hoppscotch-backend/src/types/primitiveTypes.ts deleted file mode 100644 index 11918cf33..000000000 --- a/packages/hoppscotch-backend/src/types/primitiveTypes.ts +++ /dev/null @@ -1 +0,0 @@ -export type PrimitiveTypes = number | string | boolean; From 480a34c0f76d8c806a99d152b9d494f3fab1e941 Mon Sep 17 00:00:00 2001 From: ankitsridhar16 Date: Mon, 23 Jan 2023 09:54:20 +0530 Subject: [PATCH 7/8] fix: updated resolver pubsub topic name --- .../src/user-environment/user-environments.resolver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/hoppscotch-backend/src/user-environment/user-environments.resolver.ts b/packages/hoppscotch-backend/src/user-environment/user-environments.resolver.ts index f053905bb..cccdf11cd 100644 --- a/packages/hoppscotch-backend/src/user-environment/user-environments.resolver.ts +++ b/packages/hoppscotch-backend/src/user-environment/user-environments.resolver.ts @@ -201,7 +201,7 @@ export class UserEnvironmentsResolver { @UseGuards(GqlAuthGuard) userEnvironmentDeleteMany(@GqlUser() user: User) { return this.pubsub.asyncIterator( - `user_environment/${user.uid}/delete_many`, + `user_environment/${user.uid}/deleted_many`, ); } } From cb1b13bdb47689a90a7394b371a9e55cf9e512fe Mon Sep 17 00:00:00 2001 From: ankitsridhar16 Date: Mon, 23 Jan 2023 11:49:41 +0530 Subject: [PATCH 8/8] chore: updated filename to topicDefs --- packages/hoppscotch-backend/src/pubsub/pubsub.service.ts | 2 +- .../src/pubsub/{subscriptionTopicsDefs.ts => topicsDefs.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/hoppscotch-backend/src/pubsub/{subscriptionTopicsDefs.ts => topicsDefs.ts} (100%) diff --git a/packages/hoppscotch-backend/src/pubsub/pubsub.service.ts b/packages/hoppscotch-backend/src/pubsub/pubsub.service.ts index ba86342e1..bec396028 100644 --- a/packages/hoppscotch-backend/src/pubsub/pubsub.service.ts +++ b/packages/hoppscotch-backend/src/pubsub/pubsub.service.ts @@ -4,7 +4,7 @@ import { default as Redis, RedisOptions } from 'ioredis'; import { RedisPubSub } from 'graphql-redis-subscriptions'; import { PubSub as LocalPubSub } from 'graphql-subscriptions'; -import { TopicDef } from './subscriptionTopicsDefs'; +import { TopicDef } from './topicsDefs'; /** * RedisPubSub uses JSON parsing for back and forth conversion, which loses Date objects, hence this reviver brings them back diff --git a/packages/hoppscotch-backend/src/pubsub/subscriptionTopicsDefs.ts b/packages/hoppscotch-backend/src/pubsub/topicsDefs.ts similarity index 100% rename from packages/hoppscotch-backend/src/pubsub/subscriptionTopicsDefs.ts rename to packages/hoppscotch-backend/src/pubsub/topicsDefs.ts