feat: Add Stats functions
This commit is contained in:
parent
c55b0221ad
commit
383e9aa093
82
Cargo.lock
generated
82
Cargo.lock
generated
@ -2,6 +2,88 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustysearch"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.189"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.189"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
@ -9,3 +9,5 @@ license = "MIT"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.189", features = ["derive"] }
|
||||
serde_json = "1.0.107"
|
||||
|
2
src/lib.rs
Normal file
2
src/lib.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod types;
|
||||
pub mod search;
|
63
src/main.rs
63
src/main.rs
@ -1,62 +1,7 @@
|
||||
use std::{fs, path::Path};
|
||||
|
||||
pub struct Rustysearch {
|
||||
base_directory: String,
|
||||
index_path: String,
|
||||
docs_path: String,
|
||||
stats_path: String,
|
||||
}
|
||||
|
||||
impl Rustysearch {
|
||||
/// **Sets up the object & the data directory**
|
||||
///
|
||||
/// Requires a ``base_directory`` parameter, which specifies the parent
|
||||
/// directory the index/document/stats data will be kept in.
|
||||
///
|
||||
pub fn new(path: &str) -> Self {
|
||||
Self {
|
||||
base_directory: path.to_string(),
|
||||
index_path: format!("{}/index", path),
|
||||
docs_path: format!("{}/docs", path),
|
||||
stats_path: format!("{}/stats.json", path),
|
||||
}
|
||||
}
|
||||
|
||||
/// **Handles the creation of the various data directories**
|
||||
///
|
||||
/// If the paths do not exist, it will create them. As a side effect, you
|
||||
/// must have read/write access to the location you're trying to create
|
||||
/// the data at.
|
||||
///
|
||||
fn setup(&self) {
|
||||
// Create the base directory
|
||||
if !Path::new(&self.base_directory).exists() {
|
||||
fs::create_dir(&self.base_directory).expect("Unable to create base directory");
|
||||
}
|
||||
// Create the index directory
|
||||
if !Path::new(&self.index_path).exists() {
|
||||
fs::create_dir(&self.index_path).expect("Unable to create index directory");
|
||||
}
|
||||
// Create the docs directory
|
||||
if !Path::new(&self.docs_path).exists() {
|
||||
fs::create_dir(&self.docs_path).expect("Unable to create docs directory");
|
||||
}
|
||||
}
|
||||
|
||||
/// **Reads the index-wide stats**
|
||||
///
|
||||
/// If the stats do not exist, it makes returns data with the current
|
||||
/// version of ``rustysearch`` & zero docs (used in scoring).
|
||||
///
|
||||
pub fn read_stats(&self) -> String {
|
||||
if !Path::new(&self.stats_path).exists() {
|
||||
return String::from("{\"version\": \"0.1.0\", \"docs\": 0}");
|
||||
}
|
||||
|
||||
return String::from("");
|
||||
}
|
||||
}
|
||||
use rustysearch::search::Rustysearch;
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!")
|
||||
println!("Hello, world!");
|
||||
let search = Rustysearch::new("/tmp/rustysearch");
|
||||
search.setup();
|
||||
}
|
101
src/search.rs
Normal file
101
src/search.rs
Normal file
@ -0,0 +1,101 @@
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use crate::types::Stats;
|
||||
|
||||
pub struct Rustysearch {
|
||||
base_directory: String,
|
||||
index_path: String,
|
||||
docs_path: String,
|
||||
stats_path: String,
|
||||
}
|
||||
|
||||
impl Rustysearch {
|
||||
/// **Sets up the object & the data directory**
|
||||
///
|
||||
/// Requires a ``base_directory`` parameter, which specifies the parent
|
||||
/// directory the index/document/stats data will be kept in.
|
||||
///
|
||||
pub fn new(path: &str) -> Self {
|
||||
Self {
|
||||
base_directory: path.to_string(),
|
||||
index_path: format!("{}/index", path),
|
||||
docs_path: format!("{}/docs", path),
|
||||
stats_path: format!("{}/stats.json", path),
|
||||
}
|
||||
}
|
||||
|
||||
/// **Handles the creation of the various data directories**
|
||||
///
|
||||
/// If the paths do not exist, it will create them. As a side effect, you
|
||||
/// must have read/write access to the location you're trying to create
|
||||
/// the data at.
|
||||
///
|
||||
pub fn setup(&self) {
|
||||
// Create the base directory
|
||||
if !Path::new(&self.base_directory).exists() {
|
||||
fs::create_dir(&self.base_directory).expect("Unable to create base directory");
|
||||
}
|
||||
// Create the index directory
|
||||
if !Path::new(&self.index_path).exists() {
|
||||
fs::create_dir(&self.index_path).expect("Unable to create index directory");
|
||||
}
|
||||
// Create the docs directory
|
||||
if !Path::new(&self.docs_path).exists() {
|
||||
fs::create_dir(&self.docs_path).expect("Unable to create docs directory");
|
||||
}
|
||||
}
|
||||
|
||||
/// **Reads the index-wide stats**
|
||||
///
|
||||
/// If the stats do not exist, it makes returns data with the current
|
||||
/// version of ``rustysearch`` & zero docs (used in scoring).
|
||||
///
|
||||
pub fn read_stats(&self) -> Stats {
|
||||
if !Path::new(&self.stats_path).exists() {
|
||||
let stats = Stats {
|
||||
version: String::from("0.1.0"),
|
||||
total_docs: 0,
|
||||
};
|
||||
return stats;
|
||||
}
|
||||
|
||||
// Read the stats file
|
||||
let stats_json = fs::read_to_string(&self.stats_path).expect("Unable to read stats");
|
||||
let stats: Stats = serde_json::from_str(&stats_json).unwrap();
|
||||
return stats;
|
||||
}
|
||||
|
||||
/// **Writes the index-wide stats**
|
||||
///
|
||||
/// Takes a ``new_stats`` parameter, which should be a dictionary of
|
||||
/// stat data. Example stat data::
|
||||
///
|
||||
/// {
|
||||
/// 'version': '1.0.0',
|
||||
/// 'total_docs': 25,
|
||||
/// }
|
||||
///
|
||||
pub fn write_stats(&self, new_stats: Stats) {
|
||||
// Write new_stats as json to stats_path
|
||||
let new_stats_json = serde_json::to_string(&new_stats).unwrap();
|
||||
fs::write(&self.stats_path, new_stats_json).expect("Unable to write stats");
|
||||
}
|
||||
|
||||
/// **Increments the total number of documents the index is aware of**
|
||||
///
|
||||
/// This is important for scoring reasons & is typically called as part
|
||||
/// of the indexing process.
|
||||
///
|
||||
pub fn increment_total_docs(&self) {
|
||||
let mut current_stats = self.read_stats();
|
||||
current_stats.total_docs += 1;
|
||||
self.write_stats(current_stats);
|
||||
}
|
||||
|
||||
/// **Returns the total number of documents the index is aware of**
|
||||
///
|
||||
pub fn get_total_docs(&self) -> i32 {
|
||||
let stats = self.read_stats();
|
||||
return stats.total_docs;
|
||||
}
|
||||
}
|
7
src/types.rs
Normal file
7
src/types.rs
Normal file
@ -0,0 +1,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Stats{
|
||||
pub version: String,
|
||||
pub total_docs: i32,
|
||||
}
|
76
tests/rustysearch.rs
Normal file
76
tests/rustysearch.rs
Normal file
@ -0,0 +1,76 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rustysearch::{types::Stats, search::Rustysearch};
|
||||
|
||||
#[test]
|
||||
fn test_write_new_stats(){
|
||||
let stats = Stats{
|
||||
version: String::from("0.1.0"),
|
||||
total_docs: 0,
|
||||
};
|
||||
|
||||
assert_eq!(stats.version, "0.1.0");
|
||||
assert_eq!(stats.total_docs, 0);
|
||||
|
||||
let search = Rustysearch::new("/tmp/rustysearch");
|
||||
search.setup();
|
||||
|
||||
search.write_stats(stats);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_stats(){
|
||||
let search = Rustysearch::new("/tmp/rustysearch");
|
||||
search.setup();
|
||||
|
||||
clean_stats();
|
||||
|
||||
let stats = search.read_stats();
|
||||
assert_eq!(stats.version, "0.1.0");
|
||||
assert_eq!(stats.total_docs, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_increment_total_docs(){
|
||||
let search = Rustysearch::new("/tmp/rustysearch");
|
||||
search.setup();
|
||||
|
||||
clean_stats();
|
||||
|
||||
let stats = search.read_stats();
|
||||
assert_eq!(stats.total_docs, 0);
|
||||
|
||||
search.increment_total_docs();
|
||||
let stats = search.read_stats();
|
||||
assert_eq!(stats.total_docs, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_total_docs(){
|
||||
let search = Rustysearch::new("/tmp/rustysearch");
|
||||
search.setup();
|
||||
|
||||
clean_stats();
|
||||
|
||||
let stats = search.read_stats();
|
||||
assert_eq!(stats.total_docs, 0);
|
||||
|
||||
search.increment_total_docs();
|
||||
let stats = search.read_stats();
|
||||
assert_eq!(stats.total_docs, 1);
|
||||
|
||||
let total_docs = search.get_total_docs();
|
||||
assert_eq!(total_docs, 1);
|
||||
}
|
||||
|
||||
fn clean_stats(){
|
||||
let search = Rustysearch::new("/tmp/rustysearch");
|
||||
search.setup();
|
||||
|
||||
let new_stats = Stats{
|
||||
version: String::from("0.1.0"),
|
||||
total_docs: 0,
|
||||
};
|
||||
search.write_stats(new_stats);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user