rust - 如何在 Rust 中使用 `sqlx` 和 `juniper` 订阅?
问题描述
背景:
我无法sqlx
与juniper
订阅集成。
我Pin<Box<dyn Stream<Item = Result<User, sqlx::Error>> + 'e + Send>>
从sqlx::query::QueryAs::fetch()
.
juniper
需要订阅返回为Pin<Box<dyn Stream<Item = Result<User, juniper::FieldError>> + Send>>
.
注意从Result<User, sqlx::Error>
到的变化Result<User, juniper::FieldError>
。使用map_err()
fromfutures::TryStreamExt
,我创建了以下代码来执行查询并转换错误类型。
type UsersStream =
Pin<Box<dyn Stream<Item = Result<User, FieldError>> + Send>>;
#[juniper::graphql_subscription(Context = Context)]
impl SubscriptionRoot {
async fn users(context: &Context) -> UsersStream {
let sqlx::query_as!(User, "SELECT * FROM users")
.fetch(&context.pool)
.map_err(|e| {
FieldError::new(
"Database error",
graphql_value!(format!("{}", e)))
})
.boxed()
}
}
这在编译时失败并出现以下错误:
error[E0759]: `executor` has lifetime `'ref_e` but it needs to satisfy a `'static` lifetime requirement
--> server/src/graphql/subscription.rs:27:1
|
27 | #[juniper::graphql_subscription(Context = Context)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| this data with lifetime `'ref_e`...
| ...is captured here...
...
63 | / sqlx::query_as!(User, "SELECT * FROM users")
64 | | .fetch(&context.pool)
65 | | .map_err(|e| {
66 | | FieldError::new(
... |
69 | | })
70 | | .boxed()
| |____________________- ...and is required to live as long as `'static` here
|
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
我对Stream
s 或生命周期不够熟悉,无法理解此错误的含义。在进一步研究之后,这似乎ref_e
是订阅对juniper
's的引用的生命周期Executor
。
尝试:
- 提供生命周期,
juniper::Context
如graphql-rust/juniper#143中所述。 - 更高等级的特征界限
版本:
sqlx-0.4.1
juniper
cd66bdb
固定承诺master
解决方案
Mathieu的回答是正确的。因此,我将解释错误背后的原因。
这里的根本问题是,当您返回时,UsersStream
您将数据移出函数fn users(..)
。现在函数的调用者users(..)
拥有返回的数据,并且(理论上)可以做任何它想做的事情,包括在应用程序的生命周期内保留数据,即赋予数据“静态生命周期”。但是如果UsersStream
引用了一个生命周期有限的数据( ),那么当数据的所有者丢弃数据context.pool
时会发生什么?pool
当数据被删除时,它将引用空指针。所以编译器会抛出错误来防止这种情况发生。
所以你可以在这里做的是以某种方式传递拥有的数据(pool
)而不是引用,确保它与现在拥有的数据pool
具有相同的生命周期。正是这样做,它创建了一个拥有的数据副本(引用计数或字节副本)。UsersStream
clone()
推荐阅读
- angular - Angular 6 - httpClient 发布 XML 文件
- spring-boot - Spring Boot 2.0 WebClient 在继续之前处理 404
- javascript - 在元素中查找行,然后用标签包装它
- javascript - 如何计算 CheckSum 8 Xor
- macos - C++:无法读取 macOS 包中的资源文件
- python-3.6 - 将 Vertica 连接为 Django 后端
- android - MediaStore.ACTION_VIDEO_CAPTURE 从 Nohat 设备上的预览屏幕播放录制的视频时应用程序崩溃
- google-translate - 如何使用 google translate api 进行“文字”翻译而不是有意义的翻译?
- c# - 将参考项目升级到 .Net Standard 2.0 后无法编译 UWP 类库
- soapui - 如何获取测试步骤编号并将其打印在脚本日志中