我有一个学习项目,正在构建分段的 WAL,并且正在为日志文件和整个 WAL(分段透明)实现 Stream https://github.com/danthegoodman1/WriteAhead/blob/1597d3357678fec402fe5b2fd3a6d4b0f5f53f3a/src/write_ahead.rs#L529-L556
目前,我遇到了编译器错误:
Compiling writeahead v0.1.0 (/Users/dangoodman/code/WriteAhead)
warning: unused import: `TryStreamExt`
--> src/write_ahead.rs:2:23
|
2 | use futures::{Stream, TryStreamExt};
| ^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
error: lifetime may not live long enough
--> src/write_ahead.rs:515:28
|
497 | impl<'a, F: FileIO> WriteAheadStream<'a, F> {
| -- lifetime `'a` defined here
...
510 | fn advance_to_next_stream(&mut self) -> Option<()> {
| - let's call the lifetime of this reference `'1`
...
515 | let next_logfile = self
| ____________________________^
516 | | .write_ahead
517 | | .log_files
518 | | .get_mut(&self.current_logfile_id)?;
| |______________________________________________^ argument requires that `'1` must outlive `'a`
warning: `writeahead` (lib) generated 1 warning
error: could not compile `writeahead` (lib) due to 1 previous error; 1 warning emitted
这是有问题的代码的简化版本:
use std::collections::BTreeMap;
pub struct Logfile<F> {
fio: F,
}
pub struct LogFileStream<'a, F> {
logfile: &'a mut Logfile<F>,
}
impl<'a, F> LogFileStream<'a, F> {
pub fn new(logfile: &'a mut Logfile<F>) -> Self {
Self { logfile }
}
}
pub struct WriteAhead<F> {
log_files: BTreeMap<u64, Logfile<F>>,
}
pub struct WriteAheadStream<'a, F> {
write_ahead: &'a mut WriteAhead<F>,
current_logfile_id: u64,
current_stream: Option<LogFileStream<'a, F>>,
}
impl<'a, F> WriteAheadStream<'a, F> {
// Helper to get next stream when current one is exhausted
fn advance_to_next_stream(&mut self) -> Option<()> {
// If we have an active stream, drop it
self.current_stream = None;
// Try to get next logfile
let next_logfile = self
.write_ahead
.log_files
.get_mut(&self.current_logfile_id)?;
// Create new stream
self.current_stream = Some(LogFileStream::new(next_logfile));
self.current_logfile_id += 1;
Some(())
}
}
我不确定如何表达这应该比它更长久。我期望 WriteAhead 将是单线程的,并拥有 Logfiles、LogFileStream 和 WriteAheadStreams 的生命周期。
也许我没有很好地表达所有权层次结构,但我不确定如何做到这一点。目标是 Axum 或其他网络服务之类的东西可以将其包装在 Arc
我不确定你的做法是否明智,但让我严格评论一下这个问题。您的
fn advance_to_next_stream(&mut self) -> ...
采用 self
参数,其生命周期是任意的,并且它可能比 'a
短。
这使得任何 self.field
访问的生命周期也较短,即使 field
具有不同生命周期的引用类型。
但是,您可以要求
self
寿命足够长:
fn advance_to_next_stream(&'a mut self) -> Option<()>
// ^^^
现在您的代码符合要求。