Overview
graphql-redis-subscription@2.5.0
packagedocker-compose.yml
below postAdded
is executed in GraphQL Playground. Instead of hanging to listen for events, it had crashed before I performed createPost
mutation.My code (I only include some important details)
posts.resolver.ts
import { Inject, UseGuards } from '@nestjs/common';
import { Args, Context, Mutation, Resolver, Subscription } from '@nestjs/graphql';
import { RedisPubSub } from 'graphql-redis-subscriptions';
import { GraphqlJwtAuthGuard } from '../auth/guards';
import { RequestWithUser } from '../auth/interfaces';
import { PUB_SUB } from '../pubsub/pubsub.module'
const POST_ADDED_EVENT = 'postAdded';
@Resolver(() => Post)
export class PostsResolver {
constructor(
private postsService: PostsService,
@Inject(PUB_SUB) private pubSub: RedisPubSub,
) {}
// my subscription (issue)
@Subscription(() => Post)
postAdded() {
return this.pubSub.asyncIterator(POST_ADDED_EVENT);
}
// createPost method
@Mutation(() => Post)
@UseGuards(GraphqlJwtAuthGuard)
async createPost(
@Args('input') createPostInput: CreatePostInput,
@Context() context: { req: RequestWithUser },
) {
// just create a new post (assuming it works)
const newPost = await this.postsService.create(
createPostInput,
context.req.user,
);
this.pubSub.publish(POST_ADDED_EVENT, { postAdded: newPost });
return newPost;
}
}
pubsub.module.ts
import { ConfigService } from '@nestjs/config';
import { RedisPubSub } from 'graphql-redis-subscriptions';
import { Global, Module } from '@nestjs/common';
export const PUB_SUB = 'PUB_SUB';
@Global()
@Module({
providers: [
{
provide: PUB_SUB,
useFactory: (configService: ConfigService) =>
new RedisPubSub({
connection: {
host: configService.get('REDIS_HOST'),
port: configService.get('REDIS_PORT'),
},
}),
inject: [ConfigService],
},
],
exports: [PUB_SUB],
})
export class PubSubModule {}
app.module.ts
import { PubSubModule } from './pubsub/pubsub.module';
@Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
playground: true,
autoSchemaFile: path.join(process.cwd(), 'src/schema.gql'),
installSubscriptionHandlers: true,
}),
PubSubModule,
ConfigModule.forRoot({
isGlobal: true,
validationSchema: Joi.object({
REDIS_HOST: Joi.string().required(),
REDIS_PORT: Joi.number().required()
}),
}),
],
providers: [AppService, AppResolver],
})
export class AppModule {}
version: '3'
services:
redis:
image: 'redis:alpine'
ports:
- '6379:6379'
redis-commander:
image: rediscommander/redis-commander:latest
environment:
- REDIS_HOSTS=local:redis:6379
ports:
- '8081:8081'
depends_on:
- redis
All the environment variables have already been defined in .env
file.
REDIS_HOST="localhost"
REDIS_PORT=6379
When I run yarn start:dev
and execute the subscription in GraphQL Playground
subscription {
postAdded {
id
title
paragraphs
}
}
it raises an error like this:
{
"errors": [
{
"message": "Cannot read properties of undefined (reading 'length')",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"postAdded"
]
}
]
}
The terminal that monitors NestJS also raises an error like this:
[Nest] 8080 - 07/21/2022, 9:30:24 AM ERROR [ExceptionsHandler] Cannot read properties of undefined (reading 'length')
TypeError: Cannot read properties of undefined (reading 'length')
at JavascriptRedisParser.execute (C:\Users\HP\nestjs-project\node_modules\redis-parser\lib\parser.js:530:38)
at Object.data (C:\Users\HP\nestjs-project\node_modules\ioredis\built\DataHandler.js:25:20)
at TransformOperationExecutor.transform (C:\Users\HP\nestjs-project\node_modules\src\TransformOperationExecutor.ts:207:39)
at TransformOperationExecutor.transform (C:\Users\HP\nestjs-project\node_modules\src\TransformOperationExecutor.ts:327:31)
at TransformOperationExecutor.transform (C:\Users\HP\nestjs-project\node_modules\src\TransformOperationExecutor.ts:327:31)
at TransformOperationExecutor.transform (C:\Users\HP\nestjs-project\node_modules\src\TransformOperationExecutor.ts:327:31)
at TransformOperationExecutor.transform (C:\Users\HP\nestjs-project\node_modules\src\TransformOperationExecutor.ts:327:31)
at TransformOperationExecutor.transform (C:\Users\HP\nestjs-project\node_modules\src\TransformOperationExecutor.ts:327:31)
at ClassTransformer.instanceToPlain (C:\Users\HP\nestjs-project\node_modules\src\ClassTransformer.ts:25:21)
at Object.classToPlain (C:\Users\HP\nestjs-project\node_modules\src\index.ts:23:27)
I have installed all the necessary dependencies like ioredis
, graphql-redis-subscriptions
and even graphql-subscriptions
but the errors still exist. Redis also seems to be running properly.
I have tried reading the error logs but it did not occur in my source code and doing some research on StackOverFlow but none seems to have solved the problem.
are you by any chance using a global ClassSerializerInterceptor?? Because I was running into the same problem just today and I solved by removing the interceptor. It happened because the subscription needs to receive an instance of AsyncIterable but the class serializer turns it into a plain object.
Apart from that I would recommend you change the GraphQl config, remove the installSubscriptionHandlers and change the config like this:
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
playground: true,
autoSchemaFile: path.join(process.cwd(), 'src/schema.gql'),
// remove this option:
// installSubscriptionHandlers: true,
// add the following:
subscriptions: {
"graphql-ws": true // or config object
}
}),
you can read more about it in the nestjs docs
I hope this solves your problem.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.