caio.co/de/cantine

Add a simple /info endpoint

This can serve as a health-check and as an initial "what can I ask this
index about" answer.

Right now, this is what you get:

    {
        "total_recipes": 1183461,
        "features": {
            "num_ingredients": [ { "min": 2, "max": 93, "count": 1183461 } ],
            "instructions_length": [ { "min": 18, "max": 34663, "count": 1183461 } ],
            "prep_time": [ { "min": 0, "max": 129600, "count": 755741 } ],
            "total_time": [ { "min": 0, "max": 259200, "count": 592741 } ],
            "cook_time": [ { "min": 1, "max": 878040, "count": 605199 } ],
            "calories": [ { "min": 1, "max": 1285624091, "count": 311252 } ],
            "fat_content": [ { "min": 0, "max": 50693.902, "count": 275000 } ],
            "carb_content": [ { "min": 0, "max": 7266.2, "count": 276161 } ],
            "protein_content": [ { "min": 0, "max": 15727.4, "count": 267743 } ],
            "diet_lowcarb": [ { "min": 0.5, "max": 1, "count": 863199 } ],
            "diet_vegetarian": [ { "min": 1, "max": 1, "count": 22716 } ],
            "diet_vegan": [ { "min": 1, "max": 1, "count": 13788 } ],
            "diet_keto": [ { "min": 0.5, "max": 1, "count": 109035 } ],
            "diet_paleo": [ { "min": 0.5, "max": 1, "count": 412171 } ]
      }
    }
Id
6a9e923666a650a49c6201c77a8ef1fef488503b
Author
Caio
Commit time
2019-12-30T11:53:48+01:00

Modified cantine/src/main.rs

@@ -9,6 +9,7

use actix_web::{http::StatusCode, middleware, web, App, HttpResponse, HttpServer, Result};
use env_logger;
+use serde::Serialize;
use structopt::StructOpt;
use tokio::time::timeout;
use uuid::Uuid;
@@ -22,8 +23,8
database::DatabaseReader,
index::{After, RecipeIndex},
model::{
- FeaturesAggregationResult, Recipe, RecipeCard, RecipeId, RecipeInfo, SearchCursor,
- SearchQuery, SearchResult, Sort,
+ FeaturesAggregationQuery, FeaturesAggregationResult, Recipe, RecipeCard, RecipeId,
+ RecipeInfo, SearchCursor, SearchQuery, SearchResult, Sort,
},
};

@@ -65,6 +66,16
} else {
Ok(HttpResponse::new(StatusCode::NOT_FOUND))
}
+}
+
+#[derive(Serialize, Clone)]
+pub struct IndexInfo {
+ pub total_recipes: u64,
+ pub features: FeaturesAggregationResult,
+}
+
+pub async fn index_info(info: web::Data<IndexInfo>) -> Result<HttpResponse> {
+ Ok(HttpResponse::Ok().json(info.get_ref()))
}

pub async fn search(
@@ -197,6 +208,20
_ => Ok(Box::new(BooleanQuery::from(subqueries))),
}
}
+
+ pub fn index_info(&self) -> TantivyResult<IndexInfo> {
+ let searcher = self.reader.searcher();
+ let features = self.recipe_index.aggregate_features(
+ &searcher,
+ &AllQuery,
+ FeaturesAggregationQuery::full_range(),
+ )?;
+
+ Ok(IndexInfo {
+ total_recipes: searcher.num_docs(),
+ features,
+ })
+ }
}

#[actix_rt::main]
@@ -228,15 +253,19
let threshold = options.agg_threshold.unwrap_or(std::usize::MAX);
let database: RecipeDatabase = Arc::new(DatabaseReader::open(&db_path)?);

+ let info = search_state.index_info().expect("Working index");
+
HttpServer::new(move || {
App::new()
.wrap(middleware::Logger::default())
.app_data(web::Data::new(search_state.clone()))
.app_data(web::Data::new(database.clone()))
.app_data(web::Data::new(Config { timeout, threshold }))
+ .app_data(web::Data::new(info.clone()))
.data(web::JsonConfig::default().limit(4096))
.service(web::resource("/recipe/{uuid}").route(web::get().to(recipe)))
.service(web::resource("/search").route(web::post().to(search)))
+ .service(web::resource("/info").route(web::get().to(index_info)))
})
.bind("127.0.0.1:8080")?
.run()