diff --git a/backend/package.json b/backend/package.json index b7d74c102..a4b8eb032 100644 --- a/backend/package.json +++ b/backend/package.json @@ -60,9 +60,11 @@ "graphql-iso-date": "~3.6.1", "graphql-middleware": "~4.0.2", "graphql-middleware-sentry": "^3.2.1", + "graphql-redis-subscriptions": "^2.1.2", "graphql-shield": "~7.0.9", "graphql-tag": "~2.10.2", "helmet": "~3.21.2", + "ioredis": "^4.14.1", "jsonwebtoken": "~8.5.1", "linkifyjs": "~2.1.8", "lodash": "~4.17.14", diff --git a/backend/src/config/index.js b/backend/src/config/index.js index 2f8d0ed22..8bbff8817 100644 --- a/backend/src/config/index.js +++ b/backend/src/config/index.js @@ -20,6 +20,9 @@ const { NEO4J_PASSWORD = 'neo4j', CLIENT_URI = 'http://localhost:3000', GRAPHQL_URI = 'http://localhost:4000', + REDIS_DOMAIN, + REDIS_PORT, + REDIS_PASSWORD, } = process.env export const requiredConfigs = { @@ -58,7 +61,7 @@ export const developmentConfigs = { } export const sentryConfigs = { SENTRY_DSN_BACKEND, COMMIT } - +export const redisConfiig = { REDIS_DOMAIN, REDIS_PORT, REDIS_PASSWORD } export default { ...requiredConfigs, ...smtpConfigs, @@ -66,4 +69,5 @@ export default { ...serverConfigs, ...developmentConfigs, ...sentryConfigs, + ...redisConfiig, } diff --git a/backend/src/middleware/notifications/notificationsMiddleware.js b/backend/src/middleware/notifications/notificationsMiddleware.js index 11337468c..4636b8e9f 100644 --- a/backend/src/middleware/notifications/notificationsMiddleware.js +++ b/backend/src/middleware/notifications/notificationsMiddleware.js @@ -1,6 +1,6 @@ import extractMentionedUsers from './mentions/extractMentionedUsers' import { validateNotifyUsers } from '../validation/validationMiddleware' -import { pubsub, NOTIFICATION_ADDED } from '../../schema/resolvers/notifications' +import { pubsub, NOTIFICATION_ADDED } from '../../server' const handleContentDataOfPost = async (resolve, root, args, context, resolveInfo) => { const idsOfUsers = extractMentionedUsers(args.content) diff --git a/backend/src/schema/resolvers/notifications.js b/backend/src/schema/resolvers/notifications.js index 116ac3e0e..cf35fa8a1 100644 --- a/backend/src/schema/resolvers/notifications.js +++ b/backend/src/schema/resolvers/notifications.js @@ -1,9 +1,6 @@ import log from './helpers/databaseLogger' -import { PubSub } from 'apollo-server' import { withFilter } from 'graphql-subscriptions' - -export const pubsub = new PubSub() -export const NOTIFICATION_ADDED = 'NOTIFICATION_ADDED' +import { pubsub, NOTIFICATION_ADDED } from '../../server' export default { Subscription: { diff --git a/backend/src/server.js b/backend/src/server.js index b7e751bae..4c02b8ddb 100644 --- a/backend/src/server.js +++ b/backend/src/server.js @@ -9,7 +9,30 @@ import { getNeode, getDriver } from './db/neo4j' import decode from './jwt/decode' import schema from './schema' import webfinger from './activitypub/routes/webfinger' +import { RedisPubSub } from 'graphql-redis-subscriptions' +import Redis from 'ioredis' +export const NOTIFICATION_ADDED = 'NOTIFICATION_ADDED' +const { REDIS_DOMAIN, REDIS_PORT, REDIS_PASSWORD } = CONFIG +let prodPubsub, devPubsub +const options = { + host: REDIS_DOMAIN, + port: REDIS_PORT, + password: REDIS_PASSWORD, + retryStrategy: times => { + return Math.min(times * 50, 2000) + }, +} + +if (options.host && options.port && options.password) { + prodPubsub = new RedisPubSub({ + publisher: new Redis(options), + subscriber: new Redis(options), + }) +} else { + devPubsub = new RedisPubSub() +} +export const pubsub = prodPubsub || devPubsub const driver = getDriver() const neode = getNeode() diff --git a/backend/yarn.lock b/backend/yarn.lock index 68e70fea6..eebe5c73b 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -2774,6 +2774,11 @@ clone-response@^1.0.2: dependencies: mimic-response "^1.0.0" +cluster-key-slot@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d" + integrity sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw== + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -3254,6 +3259,11 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= +denque@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/denque/-/denque-1.4.1.tgz#6744ff7641c148c3f8a69c307e51235c1f4a37cf" + integrity sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ== + depd@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" @@ -4476,6 +4486,15 @@ graphql-middleware@~4.0.2: dependencies: graphql-tools "^4.0.5" +graphql-redis-subscriptions@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/graphql-redis-subscriptions/-/graphql-redis-subscriptions-2.1.2.tgz#9c1b744bace0c6ba99dd0ebafe0148cad1df3301" + integrity sha512-l69KbGxyYfVHxvE+Dzv9/hXg/q+Xnjfx1JsrJD6ikePuSsNaCSNxr+MubSTNF3Gt3C/+JZs4FaWImFeK/+X2og== + dependencies: + iterall "^1.2.2" + optionalDependencies: + ioredis "^4.6.3" + graphql-shield@~7.0.9: version "7.0.9" resolved "https://registry.yarnpkg.com/graphql-shield/-/graphql-shield-7.0.9.tgz#8248916e9636a7e3c05719a52fd13f2d37ccaeb2" @@ -4920,6 +4939,21 @@ invariant@^2.2.2, invariant@^2.2.4: dependencies: loose-envify "^1.0.0" +ioredis@^4.14.1, ioredis@^4.6.3: + version "4.14.1" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.14.1.tgz#b73ded95fcf220f106d33125a92ef6213aa31318" + integrity sha512-94W+X//GHM+1GJvDk6JPc+8qlM7Dul+9K+lg3/aHixPN7ZGkW6qlvX0DG6At9hWtH2v3B32myfZqWoANUJYGJA== + dependencies: + cluster-key-slot "^1.1.0" + debug "^4.1.1" + denque "^1.1.0" + lodash.defaults "^4.2.0" + lodash.flatten "^4.4.0" + redis-commands "1.5.0" + redis-errors "^1.2.0" + redis-parser "^3.0.0" + standard-as-callback "^2.0.1" + ip-regex@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-1.0.3.tgz#dc589076f659f419c222039a33316f1c7387effd" @@ -5960,11 +5994,21 @@ lodash.clonedeep@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= +lodash.defaults@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= + lodash.escaperegexp@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347" integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c= +lodash.flatten@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= + lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" @@ -7506,6 +7550,23 @@ realpath-native@^1.1.0: dependencies: util.promisify "^1.0.0" +redis-commands@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.5.0.tgz#80d2e20698fe688f227127ff9e5164a7dd17e785" + integrity sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg== + +redis-errors@^1.0.0, redis-errors@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad" + integrity sha1-62LSrbFeTq9GEMBK/hUpOEJQq60= + +redis-parser@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4" + integrity sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ= + dependencies: + redis-errors "^1.0.0" + referrer-policy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/referrer-policy/-/referrer-policy-1.2.0.tgz#b99cfb8b57090dc454895ef897a4cc35ef67a98e" @@ -8203,6 +8264,11 @@ stacktrace-js@^2.0.0: stack-generator "^2.0.1" stacktrace-gps "^3.0.1" +standard-as-callback@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.0.1.tgz#ed8bb25648e15831759b6023bdb87e6b60b38126" + integrity sha512-NQOxSeB8gOI5WjSaxjBgog2QFw55FV8TkS6Y07BiB3VJ8xNTvUYm0wl0s8ObgQ5NhdpnNfigMIKjgPESzgr4tg== + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"