【问题标题】:Netflix DGS SubscriptionsNetflix DGS 订阅
【发布时间】:2021-07-14 13:35:55
【问题描述】:

我正在关注DGS subscriptions 的文档,我没有收到任何错误,但也没有取回任何数据。

设置非常简单。在 schema.graphqls 文件中,我定义了订阅:

type Subscription {
    ratings: Rating
}

type Rating {
    stars: Int
}

而Java代码如下:

@DgsComponent
public class SubscriptionDataFetcher {
    @DgsData(parentType = "Subscription", field = "ratings")
    public Publisher<Rating> ratings() {
        return Flux.interval(Duration.ofSeconds(1)).map(t -> new Rating(4));
    }
}

如果我现在将 websocket 连接到我的后端,它连接得很好,但没有按预期取回任何数据(不管我怎么做,也尝试使用 JavaScript,也连接得很好,但没有得到任何数据)。

例如使用 curl 连接(但使用 JavaScript 结果是一样的,连接但没有数据):

curl -o - --http1.1 \
    --include \
    --no-buffer \
    --header "Connection: Upgrade" \
    --header "Upgrade: websocket" \
    --header "Host: localhost:8443" \
    --header "Origin: https://localhost:8443" \
    --header "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==" \
    --header "Sec-WebSocket-Version: 13" \
    https://localhost:8443/subscriptions\?query\=ewoicXVlcnkiOiAic3Vic2NyaXB0aW9uIHsgIHN0b2NrcyB7bmFtZX0gfSIKfQ==

我也尝试过通过 Graphiql 界面进行连接,但出现错误:

subscription {
  ratings {
    stars
  }
}

错误信息:

{
  "message": "response is not defined",
  "stack": "ReferenceError: response is not defined\n    at https://localhost:8443/graphiql:46:35\n    at async Object.onRun (https://unpkg.com/graphiql/graphiql.min.js:1:540500)"
}

从链接中的示例中我不清楚的另一件事是如何实际管理订阅。因此,例如,假设我想在发生突变时发布通知。任何关于如何使用 Netflix DGS 框架来完成的指针也将不胜感激。

【问题讨论】:

    标签: graphql-java netflix netflix-dgs


    【解决方案1】:

    不幸的是,DGS 附带的 graphiql 界面似乎无法正确处理订阅 - 如果您将 playground-spring-boot-starter 添加到您的项目中,/playground 将提供更完善的工具,它完全支持订阅。如果您在那里尝试订阅,它应该可以工作(假设您已经按照文档添加了graphql-dgs-subscriptions-websockets-autoconfigure)。

    关于您的第二个问题,即如果发生突变,如何发布通知 - 不幸的是,文档中缺少这一点,但 examples repo 中有一个示例。

    我在这里简化了这个例子。如果你想支持这样的订阅和突变:

    @DgsSubscription
    public Publisher<Review> reviewAdded() {
        return reviewsService.getReviewsPublisher();
    }
    
    @DgsMutation
    public Review addReview(@InputArgument SubmittedReview review) {
        return reviewsService.saveReview(review);
    }
    

    在您的服务中,您将创建一个 Flux(返回给订阅者)并保留对其发射器的引用,以便您可以在发生突变时调用 next。

    @Service
    public class ReviewsService {
    
        private FluxSink<Review> reviewsStream;
        private ConnectableFlux<Review> reviewsPublisher;
    
        @PostConstruct
        public void init() {
            Flux<Review> publisher = Flux.create(emitter -> {
                reviewsStream = emitter;
            });
    
            reviewsPublisher = publisher.publish();
            reviewsPublisher.connect();
        }
    
        public Review saveReview(SubmittedReview reviewInput) {
            Review review = Review.newBuilder()
                    .username(reviewInput.getUsername())
                    .starScore(reviewInput.getStarScore())
                    .submittedDate(OffsetDateTime.now()).build();
    
            // Save to the database, etc.
    
            reviewsStream.next(review); // publishes the review to subscribers
            return review;
        }
    
        public Publisher<Review> getReviewsPublisher() {
            return reviewsPublisher;
        }
    }
    

    【讨论】:

    • 整个例子很棒,谢谢。但是,似乎我遇到了 graphiql 无法正确处理订阅的问题,但是当我尝试使用 Playground 时,您建议什么也没有出现,只是“加载 Graphql Playground”。你以前用过这个游乐场吗?关于为什么这可能不起作用的任何想法?
    • 是的,我已经尝试将它添加到 dgs-examples-kotlin 存储库中并且效果很好。不确定。如果你有我可以运行的公共回购,我有机会可以看看。
    • 明白了,好的,很高兴知道。我没有公开回购,但我会继续寻找。感谢您的回复!
    • 作为后续行动,我从来没有让操场工作,但我能够通过运行github.com/hasura/graphqurl 来确认我的订阅正在工作(使用@SimonW 提供的指导)。显然不如 GUI 方便,但可以很好地确保我的订阅正常工作。
    猜你喜欢
    • 2021-06-22
    • 2023-02-02
    • 2021-07-14
    • 2021-12-23
    • 2017-07-07
    • 1970-01-01
    • 2021-06-17
    • 2016-01-03
    • 2022-07-28
    相关资源
    最近更新 更多