1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//! EMB-E2 (j): `embed.rewalk_longer` walks one field again, once, for the
//! records it passed with no vector because their text was longer than the
//! model reads, so windows can cover them.
//!
//! It is not a reset. The field's position keeps its `through`, `V`; the
//! call opens a walk toward `V` itself and marks it a rewalk
//! ([`embedded::rewalk_key`]). That walk reads from the empty tree to `V`,
//! at most `embed_page_records` changes a page, and lists only the texts with
//! no vector and no windows at `V` (`embed_pending`). The page that ends it
//! removes the marker in its own commit, and the position is as it was:
//! anything changed after `V` is the next walk's, as always.
//!
//! Durable commits: one, writing the marker and the opened position.
use super::embedded::{self, Toward};
use super::{Failure, Storage, branch_name, identifier, version};
use crate::serve::protocol::Version;
impl Storage {
/// Opens the rewalk of `branch`'s `collection.field` toward its position's
/// `through`, which it answers.
///
/// # Errors
/// `branch_missing`; `embed_field_not_declared`;
/// `embed_rewalk_not_ready` when the field has no position of `branch`'s
/// own with a finished walk; `embed_walk_open` while a walk or rewalk is
/// open; whatever a read or the commit answers.
pub fn embed_rewalk_longer(
&mut self,
branch: &str,
collection: &str,
field: &str,
) -> Result<Version, Failure> {
identifier(branch)?;
identifier(collection)?;
identifier(field)?;
let record = self
.refs
.get(&branch_name(branch))
.ok_or_else(|| Failure::new("branch_missing", branch))?;
let head = super::Captured {
branch: branch.to_owned(),
version: version(record),
shards: record.shards.clone(),
};
self.declared(&head, collection, field)?;
let companion = embedded::companion_name(branch);
let key = embedded::position_key(collection, field);
let not_ready = || {
Failure::new(
"embed_rewalk_not_ready",
format!("{collection}.{field} has no finished walk of {branch}'s own"),
)
};
let mut position = self.position(&companion, &key)?.ok_or_else(not_ready)?;
if position.toward.is_some() {
return Err(Failure::new(
"embed_walk_open",
"a rewalk cannot begin while a walk is open",
));
}
let through = position
.through
.filter(|_| position.branch == branch)
.ok_or_else(not_ready)?;
position.toward = Some(Toward {
version: through,
after: String::new(),
});
let marker = serde_json::to_vec(&through).map_err(Failure::storage)?;
let writes = [
(embedded::rewalk_key(collection, field), Some(marker)),
(key, Some(embedded::encode_position(&position)?)),
];
self.commit_namespace(&companion, &writes)?;
Ok(through)
}
}