【问题标题】:Why does it throw an error cannot read property of undefined (reading 'length') when running a GraphQL Subscription with Redis?为什么在使用 Redis 运行 GraphQL 订阅时会抛出错误 cannot read property of undefined (reading \'length\')?
【发布时间】:2022-08-16 03:25:52
【问题描述】:

概述

  • 使用装有 Window OS 的笔记本电脑使用 GraphQL 处理 NestJS 项目
  • 使用graphql-redis-subscription@2.5.0 包对 GraphQL 订阅进行实验
  • Redis 用在 docker 容器中,见下面的docker-compose.yml
  • 在 GraphQL Playground 中执行订阅 postAdded 时出现问题。它没有挂起监听事件,而是在我执行createPost 突变之前崩溃了。

我的代码(我只包括一些重要的细节)

post.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

所有环境变量都已在.env 文件中定义。

REDIS_HOST=\"localhost\"
REDIS_PORT=6379

当我运行 yarn start:dev 并在 GraphQL Playground 中执行订阅时

subscription {
  postAdded {
    id
    title
    paragraphs
  }
}

它会引发这样的错误:

{
  \"errors\": [
    {
      \"message\": \"Cannot read properties of undefined (reading \'length\')\",
      \"locations\": [
        {
          \"line\": 2,
          \"column\": 3
        }
      ],
      \"path\": [
        \"postAdded\"
      ]
    }
  ]
}

监控 NestJS 的终端也会引发如下错误:

[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)

我已经安装了所有必要的依赖项,例如 ioredis、graphql-redis-subscriptions 甚至 graphql-subscriptions,但错误仍然存​​在。 Redis 似乎也运行正常。

我已经尝试阅读错误日志,但它并没有出现在我的源代码中,并且对 StackOverFlow 进行了一些研究,但似乎都没有解决问题。

    标签: node.js typescript redis graphql nestjs


    【解决方案1】:

    您是否有机会使用全球 ClassSerializerInterceptor??因为我今天遇到了同样的问题,我通过删除拦截器解决了。发生这种情况是因为订阅需要接收 AsyncIterable 的实例,但类序列化程序将其转换为普通对象。

    除此之外,我建议您更改 GraphQl 配置,删除 installSubscriptionHandlers 并像这样更改配置:

    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
      }
    }),
    

    您可以在nestjs docs 中阅读更多相关信息

    我希望这能解决你的问题。

    【讨论】:

      猜你喜欢
      • 2020-11-07
      • 2020-03-03
      • 2022-10-06
      • 2017-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-19
      • 2020-07-18
      相关资源
      最近更新 更多