introduce TaskListIdentifier

This commit is contained in:
ad hoc 2022-05-16 20:16:23 +02:00
parent aa50acb031
commit 5a5066023b
No known key found for this signature in database
GPG Key ID: 4F00A782990CC643
4 changed files with 54 additions and 18 deletions

View File

@ -216,6 +216,7 @@ impl From<Task> for TaskView {
TaskType::IndexUpdate, TaskType::IndexUpdate,
Some(TaskDetails::IndexInfo { primary_key }), Some(TaskDetails::IndexInfo { primary_key }),
), ),
TaskContent::Dump { path: _ } => todo!(),
}; };
// An event always has at least one event: "Created" // An event always has at least one event: "Created"

View File

@ -351,6 +351,7 @@ where
Ok(TaskResult::Other) Ok(TaskResult::Other)
} }
TaskContent::Dump { path: _ } => Ok(TaskResult::Other),
} }
} }
@ -504,7 +505,7 @@ mod test {
proptest! { proptest! {
#[test] #[test]
fn test_process_task( fn test_process_task(
task in any::<Task>().prop_filter("uid must be Some", |t| t.index_uid.is_some()), task in any::<Task>().prop_filter("IndexUid should be Some", |s| s.index_uid.is_some()),
index_exists in any::<bool>(), index_exists in any::<bool>(),
index_op_fails in any::<bool>(), index_op_fails in any::<bool>(),
any_int in any::<u64>(), any_int in any::<u64>(),
@ -580,6 +581,7 @@ mod test {
.then(move |_| result()); .then(move |_| result());
} }
} }
TaskContent::Dump { path: _ } => { }
} }
mocker.when::<(), IndexResult<IndexStats>>("stats") mocker.when::<(), IndexResult<IndexStats>>("stats")
@ -608,6 +610,7 @@ mod test {
} }
// if index already exists, create index will return an error // if index already exists, create index will return an error
TaskContent::IndexCreation { .. } if index_exists => (), TaskContent::IndexCreation { .. } if index_exists => (),
TaskContent::Dump { .. } => (),
// The index exists and get should be called // The index exists and get should be called
_ if index_exists => { _ if index_exists => {
index_store index_store
@ -648,7 +651,7 @@ mod test {
// Test for some expected output scenarios: // Test for some expected output scenarios:
// Index creation and deletion cannot fail because of a failed index op, since they // Index creation and deletion cannot fail because of a failed index op, since they
// don't perform index ops. // don't perform index ops.
if index_op_fails && !matches!(task.content, TaskContent::IndexDeletion | TaskContent::IndexCreation { primary_key: None } | TaskContent::IndexUpdate { primary_key: None }) if index_op_fails && !matches!(task.content, TaskContent::IndexDeletion | TaskContent::IndexCreation { primary_key: None } | TaskContent::IndexUpdate { primary_key: None } | TaskContent::Dump { .. })
|| (index_exists && matches!(task.content, TaskContent::IndexCreation { .. })) || (index_exists && matches!(task.content, TaskContent::IndexCreation { .. }))
|| (!index_exists && matches!(task.content, TaskContent::IndexDeletion || (!index_exists && matches!(task.content, TaskContent::IndexDeletion
| TaskContent::DocumentDeletion(_) | TaskContent::DocumentDeletion(_)

View File

@ -21,8 +21,13 @@ use super::{TaskFilter, TaskPerformer, TaskStore};
#[derive(Eq, Debug, Clone, Copy)] #[derive(Eq, Debug, Clone, Copy)]
enum TaskType { enum TaskType {
DocumentAddition { number: usize }, DocumentAddition {
DocumentUpdate { number: usize }, number: usize,
},
DocumentUpdate {
number: usize,
},
/// Any other kind of task, including Dumps
Other, Other,
} }
@ -63,7 +68,7 @@ impl Ord for PendingTask {
#[derive(Debug)] #[derive(Debug)]
struct TaskList { struct TaskList {
index: String, id: TaskListIdentifier,
tasks: BinaryHeap<PendingTask>, tasks: BinaryHeap<PendingTask>,
} }
@ -82,9 +87,9 @@ impl DerefMut for TaskList {
} }
impl TaskList { impl TaskList {
fn new(index: String) -> Self { fn new(id: TaskListIdentifier) -> Self {
Self { Self {
index, id,
tasks: Default::default(), tasks: Default::default(),
} }
} }
@ -92,7 +97,7 @@ impl TaskList {
impl PartialEq for TaskList { impl PartialEq for TaskList {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.index == other.index self.id == other.id
} }
} }
@ -100,11 +105,20 @@ impl Eq for TaskList {}
impl Ord for TaskList { impl Ord for TaskList {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
match (self.peek(), other.peek()) { match (&self.id, &other.id) {
(None, None) => Ordering::Equal, (TaskListIdentifier::Index(_), TaskListIdentifier::Index(_)) => {
(None, Some(_)) => Ordering::Less, match (self.peek(), other.peek()) {
(Some(_), None) => Ordering::Greater, (None, None) => Ordering::Equal,
(Some(lhs), Some(rhs)) => lhs.cmp(rhs), (None, Some(_)) => Ordering::Less,
(Some(_), None) => Ordering::Greater,
(Some(lhs), Some(rhs)) => lhs.cmp(rhs),
}
}
(TaskListIdentifier::Index(_), TaskListIdentifier::Dump) => Ordering::Greater,
(TaskListIdentifier::Dump, TaskListIdentifier::Index(_)) => Ordering::Less,
(TaskListIdentifier::Dump, TaskListIdentifier::Dump) => {
unreachable!("There should be only one Dump task list")
}
} }
} }
} }
@ -115,19 +129,27 @@ impl PartialOrd for TaskList {
} }
} }
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
enum TaskListIdentifier {
Index(String),
Dump,
}
#[derive(Default)] #[derive(Default)]
struct TaskQueue { struct TaskQueue {
/// Maps index uids to their TaskList, for quick access /// Maps index uids to their TaskList, for quick access
index_tasks: HashMap<String, Arc<AtomicRefCell<TaskList>>>, index_tasks: HashMap<TaskListIdentifier, Arc<AtomicRefCell<TaskList>>>,
/// A queue that orders TaskList by the priority of their fist update /// A queue that orders TaskList by the priority of their fist update
queue: BinaryHeap<Arc<AtomicRefCell<TaskList>>>, queue: BinaryHeap<Arc<AtomicRefCell<TaskList>>>,
} }
impl TaskQueue { impl TaskQueue {
fn insert(&mut self, task: Task) { fn insert(&mut self, task: Task) {
// TODO(marin): The index uid should be remaped to a task queue identifier here
let uid = task.index_uid.unwrap().into_inner();
let id = task.id; let id = task.id;
let uid = match task.index_uid {
Some(uid) => TaskListIdentifier::Index(uid.into_inner()),
None => unreachable!(),
};
let kind = match task.content { let kind = match task.content {
TaskContent::DocumentAddition { TaskContent::DocumentAddition {
documents_count, documents_count,
@ -161,7 +183,7 @@ impl TaskQueue {
list.push(task); list.push(task);
} }
Entry::Vacant(entry) => { Entry::Vacant(entry) => {
let mut task_list = TaskList::new(entry.key().to_owned()); let mut task_list = TaskList::new(entry.key().clone());
task_list.push(task); task_list.push(task);
let task_list = Arc::new(AtomicRefCell::new(task_list)); let task_list = Arc::new(AtomicRefCell::new(task_list));
entry.insert(task_list.clone()); entry.insert(task_list.clone());
@ -182,7 +204,7 @@ impl TaskQueue {
// After being mutated, the head is reinserted to the correct position. // After being mutated, the head is reinserted to the correct position.
self.queue.push(head); self.queue.push(head);
} else { } else {
self.index_tasks.remove(&head.borrow().index); self.index_tasks.remove(&head.borrow().id);
} }
Some(result) Some(result)

View File

@ -78,6 +78,12 @@ pub struct Task {
/// then this is None /// then this is None
// TODO: when next forward breaking dumps, it would be a good idea to move this field inside of // TODO: when next forward breaking dumps, it would be a good idea to move this field inside of
// the TaskContent. // the TaskContent.
#[cfg_attr(
test,
proptest(
strategy = "proptest::option::weighted(proptest::option::Probability::new(0.99), IndexUid::arbitrary())"
)
)]
pub index_uid: Option<IndexUid>, pub index_uid: Option<IndexUid>,
pub content: TaskContent, pub content: TaskContent,
pub events: Vec<TaskEvent>, pub events: Vec<TaskEvent>,
@ -165,6 +171,10 @@ pub enum TaskContent {
IndexUpdate { IndexUpdate {
primary_key: Option<String>, primary_key: Option<String>,
}, },
Dump {
#[cfg_attr(test, proptest(value = "PathBuf::from(\".\")"))]
path: PathBuf,
},
} }
#[cfg(test)] #[cfg(test)]