背景:
我在将sqlx
与juniper
的订阅功能集成时遇到了困难。
从sqlx::query::QueryAs::fetch()
获取了一个Pin<Box<dyn Stream<Item = Result<User, sqlx::Error>> + 'e + Send>>
。
juniper
需要将订阅返回为Pin<Box<dyn Stream<Item = Result<User, juniper::FieldError>> + Send>>
。
注意从Result<User, sqlx::Error>
到Result<User, juniper::FieldError>
的更改。使用futures::TryStreamExt
中的map_err()
,我创建了以下代码来执行查询并转换错误类型。
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
和生命周期不够熟悉,无法理解这个错误的影响。在查看了更多信息后,似乎ref_e
是订阅对juniper
的Executor
引用的生命周期。
尝试:
- 根据graphql-rust/juniper#143中讨论提供给
juniper::Context
的生命周期。 - 更高级别的trait边界
版本:
sqlx-0.4.1
juniper
固定于master
上的提交cd66bdb