From 533152d37d6e86ff071f3b9b78cab02c80fa37b3 Mon Sep 17 00:00:00 2001 From: SeijaHuang Date: Tue, 8 Oct 2024 20:53:35 +1100 Subject: [PATCH] feat add subscription - added graphql subscription setting - added market overview subscription --- package.json | 8 +- src/app.module.ts | 5 ++ .../market-overview.resolver.ts | 20 ++++- yarn.lock | 78 ++++++++++++++----- 4 files changed, 89 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index d850c13..d9f6e6e 100644 --- a/package.json +++ b/package.json @@ -30,22 +30,24 @@ "@nestjs/jwt": "^10.2.0", "@nestjs/passport": "^10.0.2", "@nestjs/platform-express": "^10.0.0", - "@nestjs/schedule": "^4.0.0", + "@nestjs/schedule": "^4.1.1", "@nestjs/typeorm": "^10.0.0", "@types/bcryptjs": "^2.4.6", - "axios": "^1.7.7", "apollo-server-express": "^3.13.0", + "axios": "^1.7.7", "bcryptjs": "^2.4.3", "ccxt": "^4.1.48", "class-validator": "^0.14.0", "dotenv": "^16.3.1", "graphql": "^16.8.1", + "graphql-subscriptions": "^2.0.0", + "graphql-ws": "^5.16.0", "joi": "^17.12.2", "nodemailer": "^6.9.13", "passport": "^0.6.0", - "passport-jwt": "^4.0.1", "passport-facebook": "^3.0.0", "passport-google-oauth20": "^2.0.0", + "passport-jwt": "^4.0.1", "pg": "^8.11.3", "reflect-metadata": "^0.1.13", "rxjs": "^7.8.1", diff --git a/src/app.module.ts b/src/app.module.ts index 43826c3..cd30cb4 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -35,6 +35,10 @@ import { MarketOverviewModule } from './modules/market-overview/market-overview. ScheduleModule.forRoot(), GraphQLModule.forRoot({ driver: ApolloDriver, + subscriptions: { + 'graphql-ws': true, + }, + installSubscriptionHandlers: true, autoSchemaFile: 'schema.gql', formatError: (error) => { const errorMessage = { @@ -47,6 +51,7 @@ import { MarketOverviewModule } from './modules/market-overview/market-overview. context: ({ req, res }) => ({ req, res }), includeStacktraceInErrorResponses: false, }), + ScheduleModule.forRoot(), UserModule, AuthModule, ExchangeKeyModule, diff --git a/src/modules/market-overview/market-overview.resolver.ts b/src/modules/market-overview/market-overview.resolver.ts index a609a17..0e043a4 100644 --- a/src/modules/market-overview/market-overview.resolver.ts +++ b/src/modules/market-overview/market-overview.resolver.ts @@ -1,4 +1,4 @@ -import { Resolver, Query, Args, Directive } from '@nestjs/graphql'; +import { Resolver, Query, Args, Directive, Subscription } from '@nestjs/graphql'; import { MarketOverviewService } from './market-overview.service'; import { MarketOverviewResult, @@ -9,6 +9,10 @@ import { CoinDetailsResponse, } from './dto/market-overview.types'; import { SymbolValidationPipe, ValidSymbol } from './pipe/market-overview-validation.pipe'; +import { PubSub } from 'graphql-subscriptions'; +import { Interval } from '@nestjs/schedule'; + +const subPub = new PubSub(); @Resolver() export class MarketOverviewResolver { @@ -49,4 +53,18 @@ export class MarketOverviewResolver { async getTop20Cryptocurrencies(): Promise { return this.marketOverviewService.getTop20Cryptocurrencies(); } + + @Subscription(() => MarketOverviewResult, { + resolve: (value) => value.updateMarketOverview, + }) + updateMarketOverview() { + return subPub.asyncIterator('updateMarketOverview'); + } + + @Interval(15000) + async publishUpdateMarketOverview(): Promise { + const updateMarketOverview = await this.marketOverviewService.getMarketOverview(); + subPub.publish('updateMarketOverview', { updateMarketOverview }); + return updateMarketOverview; + } } diff --git a/yarn.lock b/yarn.lock index 20f6a2f..c0673ee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1169,13 +1169,13 @@ multer "1.4.4-lts.1" tslib "2.6.2" -"@nestjs/schedule@^4.0.0": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@nestjs/schedule/-/schedule-4.0.1.tgz#beb69f974e7adc96fd799f555ba0121c10d2d61b" - integrity sha512-cz2FNjsuoma+aGsG0cMmG6Dqg/BezbBWet1UTHtAuu6d2mXNTVcmoEQM2DIVG5Lfwb2hfSE2yZt8Moww+7y+mA== +"@nestjs/schedule@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@nestjs/schedule/-/schedule-4.1.1.tgz#a730cff250ad5db78fe6a1bfc7f12a30856e48df" + integrity sha512-VxAnCiU4HP0wWw8IdWAVfsGC/FGjyToNjjUtXDEQL6oj+w/N5QDd2VT9k6d7Jbr8PlZuBZNdWtDKSkH5bZ+RXQ== dependencies: - cron "3.1.6" - uuid "9.0.1" + cron "3.1.7" + uuid "10.0.0" "@nestjs/schematics@^10.0.0", "@nestjs/schematics@^10.0.1": version "10.1.1" @@ -1582,10 +1582,10 @@ resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== -"@types/luxon@~3.3.0": - version "3.3.8" - resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-3.3.8.tgz#84dbf2d020a9209a272058725e168f21d331a67e" - integrity sha512-jYvz8UMLDgy3a5SkGJne8H7VA7zPV2Lwohjx0V8V31+SqAjNmurWMkk9cQhfvlcnXWudBpK9xPM1n4rljOcHYQ== +"@types/luxon@~3.4.0": + version "3.4.2" + resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-3.4.2.tgz#e4fc7214a420173cea47739c33cdf10874694db7" + integrity sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA== "@types/methods@^1.1.4": version "1.1.4" @@ -2837,12 +2837,12 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cron@3.1.6: - version "3.1.6" - resolved "https://registry.yarnpkg.com/cron/-/cron-3.1.6.tgz#e7e1798a468e017c8d31459ecd7c2d088f97346c" - integrity sha512-cvFiQCeVzsA+QPM6fhjBtlKGij7tLLISnTSvFxVdnFGLdz+ZdXN37kNe0i2gefmdD17XuZA6n2uPVwzl4FxW/w== +cron@3.1.7: + version "3.1.7" + resolved "https://registry.yarnpkg.com/cron/-/cron-3.1.7.tgz#3423d618ba625e78458fff8cb67001672d49ba0d" + integrity sha512-tlBg7ARsAMQLzgwqVxy8AZl/qlTc5nibqYwtNGoCrd+cV+ugI+tvZC1oT/8dFH8W455YrywGykx/KMmAqOr7Jw== dependencies: - "@types/luxon" "~3.3.0" + "@types/luxon" "~3.4.0" luxon "~3.4.0" cross-inspect@1.0.0: @@ -3697,6 +3697,13 @@ graphql-subscriptions@^1.1.0: dependencies: iterall "^1.3.0" +graphql-subscriptions@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/graphql-subscriptions/-/graphql-subscriptions-2.0.0.tgz#11ec181d475852d8aec879183e8e1eb94f2eb79a" + integrity sha512-s6k2b8mmt9gF9pEfkxsaO1lTxaySfKoEJzEfmwguBbQ//Oq23hIXCfR1hm4kdh5hnR20RdwB+s3BCb+0duHSZA== + dependencies: + iterall "^1.3.0" + graphql-tag@2.12.6, graphql-tag@^2.11.0: version "2.12.6" resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1" @@ -3709,6 +3716,11 @@ graphql-ws@5.14.3: resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.14.3.tgz#fb1fba011a0ae9c4e86d831cae2ec27955168b9a" integrity sha512-F/i2xNIVbaEF2xWggID0X/UZQa2V8kqKDPO8hwmu53bVOcTL7uNkxnexeEgSCVxYBQUTUNEI8+e4LO1FOhKPKQ== +graphql-ws@^5.16.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.16.0.tgz#849efe02f384b4332109329be01d74c345842729" + integrity sha512-Ju2RCU2dQMgSKtArPbEtsK5gNLnsQyTNIo/T7cZNp96niC1x0KdJNZV0TIoilceBPQwfb5itrGl8pkFeOUMl4A== + graphql@^16.8.1: version "16.8.1" resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07" @@ -5903,7 +5915,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -5944,7 +5965,14 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -6364,6 +6392,11 @@ utils-merge@1.0.1, utils-merge@1.x.x, utils-merge@^1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== +uuid@10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294" + integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ== + uuid@9.0.1, uuid@^9.0.0: version "9.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" @@ -6490,7 +6523,7 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -6508,6 +6541,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"