use deadpool_redis::redis::AsyncCommands;
use dir::FailingDirectory;
use eyre::{Result, ensure};
use tantivy::{
Index, IndexSettings, ReloadPolicy,
directory::RamDirectory,
doc,
schema::{FAST, INDEXED, STORED, SchemaBuilder},
};
use utils::{create_test_index, redis_pool, search};
use crate::{CachingDirectory, keys};
mod dir;
mod utils;
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn index_and_search_with_cache() -> Result<()> {
let pool = redis_pool().await?;
let index = create_test_index(pool.clone())?;
let results = search(&index, "old")?;
assert_eq!(results, vec!["The Old Man and the Sea"]);
let results = search(&index, "Moby")?;
assert_eq!(results, vec!["Moby Dick"]);
let results = search(&index, "old")?;
assert_eq!(results, vec!["The Old Man and the Sea"]);
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn cache_is_populated_after_open() -> Result<()> {
let pool = redis_pool().await?;
let index = create_test_index(pool.clone())?;
let _results = search(&index, "sea")?;
let mut conn = pool.get().await?;
let segment_metas = index.searchable_segment_metas()?;
ensure!(!segment_metas.is_empty(), "expected at least one segment");
let cached_exts = ["idx", "pos", "term", "fast", "store", "fieldnorm"];
for meta in &segment_metas {
for path in meta.list_files() {
if path
.extension()
.and_then(|ext| ext.to_str())
.is_none_or(|ext| !cached_exts.contains(&ext))
{
continue;
}
let key = keys::footer(&path)?;
let exists: bool = conn.exists(&key).await?;
ensure!(exists, "expected cache key {key} to exist");
}
}
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn second_open_uses_cache() -> Result<()> {
let pool = redis_pool().await?;
let ram = RamDirectory::create();
let dir = CachingDirectory::new(ram.clone(), pool.clone());
let mut builder = SchemaBuilder::new();
let text_opts = utils::text_options();
builder.add_text_field("title", text_opts | STORED);
builder.add_u64_field("count", FAST | INDEXED | STORED);
let schema = builder.build();
let index = Index::create(dir, schema.clone(), IndexSettings::default())?;
let title = index.schema().get_field("title")?;
let count = index.schema().get_field("count")?;
let mut writer = index.writer_with_num_threads(1, 15_000_000)?;
writer.add_document(doc!(title => "hello world", count => 1u64))?;
writer.commit()?;
let results = search(&index, "hello")?;
assert_eq!(results, vec!["hello world"]);
let dir2 = CachingDirectory::new(ram.clone(), pool.clone());
let index2 = Index::open(dir2)?;
let results = search(&index2, "hello")?;
assert_eq!(results, vec!["hello world"]);
let dir3 = CachingDirectory::new(FailingDirectory(ram), pool.clone());
let index3 = Index::open(dir3)?;
let _reader: tantivy::IndexReader = index3
.reader_builder()
.reload_policy(ReloadPolicy::Manual)
.try_into()?;
Ok(())
}