Extract Searcher::open_or_recreate() from main()

This commit is contained in:
Kitaiti Makoto 2021-01-06 23:25:41 +09:00
parent 43f32d30cb
commit 09d9164a1c
2 changed files with 63 additions and 60 deletions

View File

@ -1,15 +1,17 @@
use crate::{ use crate::{
config::SearchTokenizerConfig, instance::Instance, posts::Post, schema::posts, config::SearchTokenizerConfig, instance::Instance, posts::Post, schema::posts,
search::query::PlumeQuery, tags::Tag, Connection, Result, search::query::PlumeQuery, tags::Tag, Connection, Error, Result, CONFIG,
}; };
use chrono::Datelike; use chrono::{Datelike, Utc};
use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl}; use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl};
use itertools::Itertools; use itertools::Itertools;
use std::fs;
use std::{cmp, fs::create_dir_all, io, path::Path, sync::Mutex}; use std::{cmp, fs::create_dir_all, io, path::Path, sync::Mutex};
use tantivy::{ use tantivy::{
collector::TopDocs, directory::MmapDirectory, schema::*, Index, IndexReader, IndexWriter, collector::TopDocs, directory::MmapDirectory, schema::*, Index, IndexReader, IndexWriter,
ReloadPolicy, TantivyError, Term, ReloadPolicy, TantivyError, Term,
}; };
use tracing::warn;
use whatlang::{detect as detect_lang, Lang}; use whatlang::{detect as detect_lang, Lang};
#[derive(Debug)] #[derive(Debug)]
@ -67,6 +69,62 @@ impl Searcher {
schema_builder.build() schema_builder.build()
} }
pub fn open_or_recreate() -> Self {
let mut open_searcher = Self::open(&CONFIG.search_index, &CONFIG.search_tokenizers);
if let Err(Error::Search(SearcherError::InvalidIndexDataError)) = open_searcher {
if Self::create(&CONFIG.search_index, &CONFIG.search_tokenizers).is_err() {
let current_path = Path::new(&CONFIG.search_index);
let backup_path = format!("{}.{}", &current_path.display(), Utc::now().timestamp());
let backup_path = Path::new(&backup_path);
fs::rename(current_path, backup_path)
.expect("main: error on backing up search index directory for recreating");
if Self::create(&CONFIG.search_index, &CONFIG.search_tokenizers).is_ok() {
if fs::remove_dir_all(backup_path).is_err() {
warn!(
"error on removing backup directory: {}. it remains",
backup_path.display()
);
}
} else {
panic!("main: error on recreating search index in new index format. remove search index and run `plm search init` manually");
}
}
open_searcher = Self::open(&CONFIG.search_index, &CONFIG.search_tokenizers);
}
#[allow(clippy::match_wild_err_arm)]
let searcher = match open_searcher {
Err(Error::Search(e)) => match e {
SearcherError::WriteLockAcquisitionError => panic!(
r#"
Your search index is locked. Plume can't start. To fix this issue
make sure no other Plume instance is started, and run:
plm search unlock
Then try to restart Plume.
"#
),
SearcherError::IndexOpeningError => panic!(
r#"
Plume was unable to open the search index. If you created the index
before, make sure to run Plume in the same directory it was created in, or
to set SEARCH_INDEX accordingly. If you did not yet create the search
index, run this command:
plm search init
Then try to restart Plume
"#
),
e => Err(e).unwrap(),
},
Err(_) => panic!("Unexpected error while opening search index"),
Ok(s) => s,
};
searcher
}
pub fn create(path: &dyn AsRef<Path>, tokenizers: &SearchTokenizerConfig) -> Result<Self> { pub fn create(path: &dyn AsRef<Path>, tokenizers: &SearchTokenizerConfig) -> Result<Self> {
let schema = Self::schema(); let schema = Self::schema();

View File

@ -10,20 +10,17 @@ extern crate serde_json;
#[macro_use] #[macro_use]
extern crate validator_derive; extern crate validator_derive;
use chrono::Utc;
use clap::App; use clap::App;
use diesel::r2d2::ConnectionManager; use diesel::r2d2::ConnectionManager;
use plume_models::{ use plume_models::{
db_conn::{DbPool, PragmaForeignKey}, db_conn::{DbPool, PragmaForeignKey},
instance::Instance, instance::Instance,
migrations::IMPORTED_MIGRATIONS, migrations::IMPORTED_MIGRATIONS,
search::{Searcher as UnmanagedSearcher, SearcherError}, search::Searcher as UnmanagedSearcher,
Connection, Error, CONFIG, Connection, CONFIG,
}; };
use rocket_csrf::CsrfFairingBuilder; use rocket_csrf::CsrfFairingBuilder;
use scheduled_thread_pool::ScheduledThreadPool; use scheduled_thread_pool::ScheduledThreadPool;
use std::fs;
use std::path::Path;
use std::process::exit; use std::process::exit;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::Duration; use std::time::Duration;
@ -103,59 +100,7 @@ Then try to restart Plume.
} }
let workpool = ScheduledThreadPool::with_name("worker {}", num_cpus::get()); let workpool = ScheduledThreadPool::with_name("worker {}", num_cpus::get());
// we want a fast exit here, so // we want a fast exit here, so
let mut open_searcher = let searcher = Arc::new(UnmanagedSearcher::open_or_recreate());
UnmanagedSearcher::open(&CONFIG.search_index, &CONFIG.search_tokenizers);
if let Err(Error::Search(SearcherError::InvalidIndexDataError)) = open_searcher {
if UnmanagedSearcher::create(&CONFIG.search_index, &CONFIG.search_tokenizers).is_err() {
let current_path = Path::new(&CONFIG.search_index);
let backup_path = format!("{}.{}", &current_path.display(), Utc::now().timestamp());
let backup_path = Path::new(&backup_path);
fs::rename(current_path, backup_path)
.expect("main: error on backing up search index directory for recreating");
if UnmanagedSearcher::create(&CONFIG.search_index, &CONFIG.search_tokenizers).is_ok() {
if fs::remove_dir_all(backup_path).is_err() {
warn!(
"error on removing backup directory: {}. it remains",
backup_path.display()
);
}
} else {
panic!("main: error on recreating search index in new index format. remove search index and run `plm search init` manually");
}
}
open_searcher = UnmanagedSearcher::open(&CONFIG.search_index, &CONFIG.search_tokenizers);
}
#[allow(clippy::match_wild_err_arm)]
let searcher = match open_searcher {
Err(Error::Search(e)) => match e {
SearcherError::WriteLockAcquisitionError => panic!(
r#"
Your search index is locked. Plume can't start. To fix this issue
make sure no other Plume instance is started, and run:
plm search unlock
Then try to restart Plume.
"#
),
SearcherError::IndexOpeningError => panic!(
r#"
Plume was unable to open the search index. If you created the index
before, make sure to run Plume in the same directory it was created in, or
to set SEARCH_INDEX accordingly. If you did not yet create the search
index, run this command:
plm search init
Then try to restart Plume
"#
),
e => Err(e).unwrap(),
},
Err(_) => panic!("Unexpected error while opening search index"),
Ok(s) => Arc::new(s),
};
let commiter = searcher.clone(); let commiter = searcher.clone();
workpool.execute_with_fixed_delay( workpool.execute_with_fixed_delay(
Duration::from_secs(5), Duration::from_secs(5),