mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-11-25 22:34:28 +01:00
Merge #3647
3647: Improve the health route by ensuring lmdb is not down r=irevoire a=irevoire Fixes #3644 In this PR, I try to make a small read on the `AuthController` and `IndexScheduler` databases. The idea is not to validate that everything works but just to avoid the bug we had last time when lmdb was stuck forever. In order to get access to the `AuthController` without going through the extractor, I need to wrap it in the `Data` type from `actix-web`. And to do that, I had to patch our extractor so it works with the `Data` type as well. Co-authored-by: Tamo <tamo@meilisearch.com>
This commit is contained in:
commit
bc25f378e8
@ -429,6 +429,13 @@ impl IndexScheduler {
|
|||||||
Ok(this)
|
Ok(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return `Ok(())` if the index scheduler is able to access one of its database.
|
||||||
|
pub fn health(&self) -> Result<()> {
|
||||||
|
let rtxn = self.env.read_txn()?;
|
||||||
|
self.all_tasks.first(&rtxn)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn index_budget(
|
fn index_budget(
|
||||||
tasks_path: &Path,
|
tasks_path: &Path,
|
||||||
base_map_size: usize,
|
base_map_size: usize,
|
||||||
|
@ -34,6 +34,12 @@ impl AuthController {
|
|||||||
Ok(Self { store: Arc::new(store), master_key: master_key.clone() })
|
Ok(Self { store: Arc::new(store), master_key: master_key.clone() })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return `Ok(())` if the auth controller is able to access one of its database.
|
||||||
|
pub fn health(&self) -> Result<()> {
|
||||||
|
self.store.health()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the size of the `AuthController` database in bytes.
|
/// Return the size of the `AuthController` database in bytes.
|
||||||
pub fn size(&self) -> Result<u64> {
|
pub fn size(&self) -> Result<u64> {
|
||||||
self.store.size()
|
self.store.size()
|
||||||
|
@ -61,6 +61,13 @@ impl HeedAuthStore {
|
|||||||
Ok(Self { env, keys, action_keyid_index_expiration, should_close_on_drop: true })
|
Ok(Self { env, keys, action_keyid_index_expiration, should_close_on_drop: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return `Ok(())` if the auth store is able to access one of its database.
|
||||||
|
pub fn health(&self) -> Result<()> {
|
||||||
|
let rtxn = self.env.read_txn()?;
|
||||||
|
self.keys.first(&rtxn)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the size in bytes of database
|
/// Return the size in bytes of database
|
||||||
pub fn size(&self) -> Result<u64> {
|
pub fn size(&self) -> Result<u64> {
|
||||||
Ok(self.env.real_disk_size()?)
|
Ok(self.env.real_disk_size()?)
|
||||||
|
@ -86,7 +86,7 @@ impl SegmentAnalytics {
|
|||||||
pub async fn new(
|
pub async fn new(
|
||||||
opt: &Opt,
|
opt: &Opt,
|
||||||
index_scheduler: Arc<IndexScheduler>,
|
index_scheduler: Arc<IndexScheduler>,
|
||||||
auth_controller: AuthController,
|
auth_controller: Arc<AuthController>,
|
||||||
) -> Arc<dyn Analytics> {
|
) -> Arc<dyn Analytics> {
|
||||||
let instance_uid = super::find_user_id(&opt.db_path);
|
let instance_uid = super::find_user_id(&opt.db_path);
|
||||||
let first_time_run = instance_uid.is_none();
|
let first_time_run = instance_uid.is_none();
|
||||||
@ -376,7 +376,11 @@ impl Segment {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(mut self, index_scheduler: Arc<IndexScheduler>, auth_controller: AuthController) {
|
async fn run(
|
||||||
|
mut self,
|
||||||
|
index_scheduler: Arc<IndexScheduler>,
|
||||||
|
auth_controller: Arc<AuthController>,
|
||||||
|
) {
|
||||||
const INTERVAL: Duration = Duration::from_secs(60 * 60); // one hour
|
const INTERVAL: Duration = Duration::from_secs(60 * 60); // one hour
|
||||||
// The first batch must be sent after one hour.
|
// The first batch must be sent after one hour.
|
||||||
let mut interval =
|
let mut interval =
|
||||||
@ -408,10 +412,10 @@ impl Segment {
|
|||||||
async fn tick(
|
async fn tick(
|
||||||
&mut self,
|
&mut self,
|
||||||
index_scheduler: Arc<IndexScheduler>,
|
index_scheduler: Arc<IndexScheduler>,
|
||||||
auth_controller: AuthController,
|
auth_controller: Arc<AuthController>,
|
||||||
) {
|
) {
|
||||||
if let Ok(stats) =
|
if let Ok(stats) =
|
||||||
create_all_stats(index_scheduler.into(), auth_controller, &AuthFilter::default())
|
create_all_stats(index_scheduler.into(), auth_controller.into(), &AuthFilter::default())
|
||||||
{
|
{
|
||||||
// Replace the version number with the prototype name if any.
|
// Replace the version number with the prototype name if any.
|
||||||
let version = if let Some(prototype) = crate::prototype_name() {
|
let version = if let Some(prototype) = crate::prototype_name() {
|
||||||
|
@ -4,6 +4,7 @@ use std::marker::PhantomData;
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
|
|
||||||
|
use actix_web::web::Data;
|
||||||
use actix_web::FromRequest;
|
use actix_web::FromRequest;
|
||||||
pub use error::AuthenticationError;
|
pub use error::AuthenticationError;
|
||||||
use futures::future::err;
|
use futures::future::err;
|
||||||
@ -23,7 +24,7 @@ impl<P, D> GuardedData<P, D> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn auth_bearer(
|
async fn auth_bearer(
|
||||||
auth: AuthController,
|
auth: Data<AuthController>,
|
||||||
token: String,
|
token: String,
|
||||||
index: Option<String>,
|
index: Option<String>,
|
||||||
data: Option<D>,
|
data: Option<D>,
|
||||||
@ -43,7 +44,7 @@ impl<P, D> GuardedData<P, D> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn auth_token(auth: AuthController, data: Option<D>) -> Result<Self, ResponseError>
|
async fn auth_token(auth: Data<AuthController>, data: Option<D>) -> Result<Self, ResponseError>
|
||||||
where
|
where
|
||||||
P: Policy + 'static,
|
P: Policy + 'static,
|
||||||
{
|
{
|
||||||
@ -60,7 +61,7 @@ impl<P, D> GuardedData<P, D> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn authenticate(
|
async fn authenticate(
|
||||||
auth: AuthController,
|
auth: Data<AuthController>,
|
||||||
token: String,
|
token: String,
|
||||||
index: Option<String>,
|
index: Option<String>,
|
||||||
) -> Result<Option<AuthFilter>, ResponseError>
|
) -> Result<Option<AuthFilter>, ResponseError>
|
||||||
@ -90,7 +91,7 @@ impl<P: Policy + 'static, D: 'static + Clone> FromRequest for GuardedData<P, D>
|
|||||||
req: &actix_web::HttpRequest,
|
req: &actix_web::HttpRequest,
|
||||||
_payload: &mut actix_web::dev::Payload,
|
_payload: &mut actix_web::dev::Payload,
|
||||||
) -> Self::Future {
|
) -> Self::Future {
|
||||||
match req.app_data::<AuthController>().cloned() {
|
match req.app_data::<Data<AuthController>>().cloned() {
|
||||||
Some(auth) => match req
|
Some(auth) => match req
|
||||||
.headers()
|
.headers()
|
||||||
.get("Authorization")
|
.get("Authorization")
|
||||||
@ -122,10 +123,15 @@ impl<P: Policy + 'static, D: 'static + Clone> FromRequest for GuardedData<P, D>
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait Policy {
|
pub trait Policy {
|
||||||
fn authenticate(auth: AuthController, token: &str, index: Option<&str>) -> Option<AuthFilter>;
|
fn authenticate(
|
||||||
|
auth: Data<AuthController>,
|
||||||
|
token: &str,
|
||||||
|
index: Option<&str>,
|
||||||
|
) -> Option<AuthFilter>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod policies {
|
pub mod policies {
|
||||||
|
use actix_web::web::Data;
|
||||||
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};
|
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};
|
||||||
use meilisearch_auth::{AuthController, AuthFilter, SearchRules};
|
use meilisearch_auth::{AuthController, AuthFilter, SearchRules};
|
||||||
// reexport actions in policies in order to be used in routes configuration.
|
// reexport actions in policies in order to be used in routes configuration.
|
||||||
@ -178,7 +184,7 @@ pub mod policies {
|
|||||||
/// Otherwise, returns an object containing the generated permissions: the search filters to add to a search, and the list of allowed indexes
|
/// Otherwise, returns an object containing the generated permissions: the search filters to add to a search, and the list of allowed indexes
|
||||||
/// (that may contain more indexes than requested).
|
/// (that may contain more indexes than requested).
|
||||||
fn authenticate(
|
fn authenticate(
|
||||||
auth: AuthController,
|
auth: Data<AuthController>,
|
||||||
token: &str,
|
token: &str,
|
||||||
index: Option<&str>,
|
index: Option<&str>,
|
||||||
) -> Option<AuthFilter> {
|
) -> Option<AuthFilter> {
|
||||||
|
@ -88,7 +88,7 @@ fn is_empty_db(db_path: impl AsRef<Path>) -> bool {
|
|||||||
|
|
||||||
pub fn create_app(
|
pub fn create_app(
|
||||||
index_scheduler: Data<IndexScheduler>,
|
index_scheduler: Data<IndexScheduler>,
|
||||||
auth_controller: AuthController,
|
auth_controller: Data<AuthController>,
|
||||||
opt: Opt,
|
opt: Opt,
|
||||||
analytics: Arc<dyn Analytics>,
|
analytics: Arc<dyn Analytics>,
|
||||||
enable_dashboard: bool,
|
enable_dashboard: bool,
|
||||||
@ -136,7 +136,7 @@ enum OnFailure {
|
|||||||
KeepDb,
|
KeepDb,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_meilisearch(opt: &Opt) -> anyhow::Result<(Arc<IndexScheduler>, AuthController)> {
|
pub fn setup_meilisearch(opt: &Opt) -> anyhow::Result<(Arc<IndexScheduler>, Arc<AuthController>)> {
|
||||||
let empty_db = is_empty_db(&opt.db_path);
|
let empty_db = is_empty_db(&opt.db_path);
|
||||||
let (index_scheduler, auth_controller) = if let Some(ref snapshot_path) = opt.import_snapshot {
|
let (index_scheduler, auth_controller) = if let Some(ref snapshot_path) = opt.import_snapshot {
|
||||||
let snapshot_path_exists = snapshot_path.exists();
|
let snapshot_path_exists = snapshot_path.exists();
|
||||||
@ -195,6 +195,7 @@ pub fn setup_meilisearch(opt: &Opt) -> anyhow::Result<(Arc<IndexScheduler>, Auth
|
|||||||
|
|
||||||
// We create a loop in a thread that registers snapshotCreation tasks
|
// We create a loop in a thread that registers snapshotCreation tasks
|
||||||
let index_scheduler = Arc::new(index_scheduler);
|
let index_scheduler = Arc::new(index_scheduler);
|
||||||
|
let auth_controller = Arc::new(auth_controller);
|
||||||
if let ScheduleSnapshot::Enabled(snapshot_delay) = opt.schedule_snapshot {
|
if let ScheduleSnapshot::Enabled(snapshot_delay) = opt.schedule_snapshot {
|
||||||
let snapshot_delay = Duration::from_secs(snapshot_delay);
|
let snapshot_delay = Duration::from_secs(snapshot_delay);
|
||||||
let index_scheduler = index_scheduler.clone();
|
let index_scheduler = index_scheduler.clone();
|
||||||
@ -380,7 +381,7 @@ fn import_dump(
|
|||||||
pub fn configure_data(
|
pub fn configure_data(
|
||||||
config: &mut web::ServiceConfig,
|
config: &mut web::ServiceConfig,
|
||||||
index_scheduler: Data<IndexScheduler>,
|
index_scheduler: Data<IndexScheduler>,
|
||||||
auth: AuthController,
|
auth: Data<AuthController>,
|
||||||
opt: &Opt,
|
opt: &Opt,
|
||||||
analytics: Arc<dyn Analytics>,
|
analytics: Arc<dyn Analytics>,
|
||||||
) {
|
) {
|
||||||
|
@ -74,13 +74,14 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
async fn run_http(
|
async fn run_http(
|
||||||
index_scheduler: Arc<IndexScheduler>,
|
index_scheduler: Arc<IndexScheduler>,
|
||||||
auth_controller: AuthController,
|
auth_controller: Arc<AuthController>,
|
||||||
opt: Opt,
|
opt: Opt,
|
||||||
analytics: Arc<dyn Analytics>,
|
analytics: Arc<dyn Analytics>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let enable_dashboard = &opt.env == "development";
|
let enable_dashboard = &opt.env == "development";
|
||||||
let opt_clone = opt.clone();
|
let opt_clone = opt.clone();
|
||||||
let index_scheduler = Data::from(index_scheduler);
|
let index_scheduler = Data::from(index_scheduler);
|
||||||
|
let auth_controller = Data::from(auth_controller);
|
||||||
|
|
||||||
let http_server = HttpServer::new(move || {
|
let http_server = HttpServer::new(move || {
|
||||||
create_app(
|
create_app(
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
|
use actix_web::web::Data;
|
||||||
use actix_web::{web, HttpRequest, HttpResponse};
|
use actix_web::{web, HttpRequest, HttpResponse};
|
||||||
use deserr::actix_web::{AwebJson, AwebQueryParameter};
|
use deserr::actix_web::{AwebJson, AwebQueryParameter};
|
||||||
use deserr::Deserr;
|
use deserr::Deserr;
|
||||||
@ -35,7 +36,7 @@ pub fn configure(cfg: &mut web::ServiceConfig) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_api_key(
|
pub async fn create_api_key(
|
||||||
auth_controller: GuardedData<ActionPolicy<{ actions::KEYS_CREATE }>, AuthController>,
|
auth_controller: GuardedData<ActionPolicy<{ actions::KEYS_CREATE }>, Data<AuthController>>,
|
||||||
body: AwebJson<CreateApiKey, DeserrJsonError>,
|
body: AwebJson<CreateApiKey, DeserrJsonError>,
|
||||||
_req: HttpRequest,
|
_req: HttpRequest,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
@ -66,7 +67,7 @@ impl ListApiKeys {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn list_api_keys(
|
pub async fn list_api_keys(
|
||||||
auth_controller: GuardedData<ActionPolicy<{ actions::KEYS_GET }>, AuthController>,
|
auth_controller: GuardedData<ActionPolicy<{ actions::KEYS_GET }>, Data<AuthController>>,
|
||||||
list_api_keys: AwebQueryParameter<ListApiKeys, DeserrQueryParamError>,
|
list_api_keys: AwebQueryParameter<ListApiKeys, DeserrQueryParamError>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
let paginate = list_api_keys.into_inner().as_pagination();
|
let paginate = list_api_keys.into_inner().as_pagination();
|
||||||
@ -84,7 +85,7 @@ pub async fn list_api_keys(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_api_key(
|
pub async fn get_api_key(
|
||||||
auth_controller: GuardedData<ActionPolicy<{ actions::KEYS_GET }>, AuthController>,
|
auth_controller: GuardedData<ActionPolicy<{ actions::KEYS_GET }>, Data<AuthController>>,
|
||||||
path: web::Path<AuthParam>,
|
path: web::Path<AuthParam>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
let key = path.into_inner().key;
|
let key = path.into_inner().key;
|
||||||
@ -103,7 +104,7 @@ pub async fn get_api_key(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn patch_api_key(
|
pub async fn patch_api_key(
|
||||||
auth_controller: GuardedData<ActionPolicy<{ actions::KEYS_UPDATE }>, AuthController>,
|
auth_controller: GuardedData<ActionPolicy<{ actions::KEYS_UPDATE }>, Data<AuthController>>,
|
||||||
body: AwebJson<PatchApiKey, DeserrJsonError>,
|
body: AwebJson<PatchApiKey, DeserrJsonError>,
|
||||||
path: web::Path<AuthParam>,
|
path: web::Path<AuthParam>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
@ -123,7 +124,7 @@ pub async fn patch_api_key(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn delete_api_key(
|
pub async fn delete_api_key(
|
||||||
auth_controller: GuardedData<ActionPolicy<{ actions::KEYS_DELETE }>, AuthController>,
|
auth_controller: GuardedData<ActionPolicy<{ actions::KEYS_DELETE }>, Data<AuthController>>,
|
||||||
path: web::Path<AuthParam>,
|
path: web::Path<AuthParam>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
let key = path.into_inner().key;
|
let key = path.into_inner().key;
|
||||||
|
@ -19,7 +19,7 @@ pub fn configure(cfg: &mut web::ServiceConfig) {
|
|||||||
|
|
||||||
pub async fn create_dump(
|
pub async fn create_dump(
|
||||||
index_scheduler: GuardedData<ActionPolicy<{ actions::DUMPS_CREATE }>, Data<IndexScheduler>>,
|
index_scheduler: GuardedData<ActionPolicy<{ actions::DUMPS_CREATE }>, Data<IndexScheduler>>,
|
||||||
auth_controller: GuardedData<ActionPolicy<{ actions::DUMPS_CREATE }>, AuthController>,
|
auth_controller: GuardedData<ActionPolicy<{ actions::DUMPS_CREATE }>, Data<AuthController>>,
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
analytics: web::Data<dyn Analytics>,
|
analytics: web::Data<dyn Analytics>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
|
@ -17,7 +17,7 @@ pub fn configure(config: &mut web::ServiceConfig) {
|
|||||||
|
|
||||||
pub async fn get_metrics(
|
pub async fn get_metrics(
|
||||||
index_scheduler: GuardedData<ActionPolicy<{ actions::METRICS_GET }>, Data<IndexScheduler>>,
|
index_scheduler: GuardedData<ActionPolicy<{ actions::METRICS_GET }>, Data<IndexScheduler>>,
|
||||||
auth_controller: GuardedData<ActionPolicy<{ actions::METRICS_GET }>, AuthController>,
|
auth_controller: GuardedData<ActionPolicy<{ actions::METRICS_GET }>, Data<AuthController>>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
let auth_filters = index_scheduler.filters();
|
let auth_filters = index_scheduler.filters();
|
||||||
if !auth_filters.all_indexes_authorized() {
|
if !auth_filters.all_indexes_authorized() {
|
||||||
|
@ -238,7 +238,7 @@ pub struct Stats {
|
|||||||
|
|
||||||
async fn get_stats(
|
async fn get_stats(
|
||||||
index_scheduler: GuardedData<ActionPolicy<{ actions::STATS_GET }>, Data<IndexScheduler>>,
|
index_scheduler: GuardedData<ActionPolicy<{ actions::STATS_GET }>, Data<IndexScheduler>>,
|
||||||
auth_controller: GuardedData<ActionPolicy<{ actions::STATS_GET }>, AuthController>,
|
auth_controller: GuardedData<ActionPolicy<{ actions::STATS_GET }>, Data<AuthController>>,
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
analytics: web::Data<dyn Analytics>,
|
analytics: web::Data<dyn Analytics>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
@ -253,7 +253,7 @@ async fn get_stats(
|
|||||||
|
|
||||||
pub fn create_all_stats(
|
pub fn create_all_stats(
|
||||||
index_scheduler: Data<IndexScheduler>,
|
index_scheduler: Data<IndexScheduler>,
|
||||||
auth_controller: AuthController,
|
auth_controller: Data<AuthController>,
|
||||||
filters: &meilisearch_auth::AuthFilter,
|
filters: &meilisearch_auth::AuthFilter,
|
||||||
) -> Result<Stats, ResponseError> {
|
) -> Result<Stats, ResponseError> {
|
||||||
let mut last_task: Option<OffsetDateTime> = None;
|
let mut last_task: Option<OffsetDateTime> = None;
|
||||||
@ -318,9 +318,14 @@ struct KeysResponse {
|
|||||||
|
|
||||||
pub async fn get_health(
|
pub async fn get_health(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
|
index_scheduler: Data<IndexScheduler>,
|
||||||
|
auth_controller: Data<AuthController>,
|
||||||
analytics: web::Data<dyn Analytics>,
|
analytics: web::Data<dyn Analytics>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
analytics.health_seen(&req);
|
analytics.health_seen(&req);
|
||||||
|
|
||||||
|
index_scheduler.health().unwrap();
|
||||||
|
auth_controller.health().unwrap();
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(serde_json::json!({ "status": "available" })))
|
Ok(HttpResponse::Ok().json(serde_json::json!({ "status": "available" })))
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ impl Server {
|
|||||||
> {
|
> {
|
||||||
actix_web::test::init_service(create_app(
|
actix_web::test::init_service(create_app(
|
||||||
self.service.index_scheduler.clone().into(),
|
self.service.index_scheduler.clone().into(),
|
||||||
self.service.auth.clone(),
|
self.service.auth.clone().into(),
|
||||||
self.service.options.clone(),
|
self.service.options.clone(),
|
||||||
analytics::MockAnalytics::new(&self.service.options),
|
analytics::MockAnalytics::new(&self.service.options),
|
||||||
true,
|
true,
|
||||||
|
@ -13,7 +13,7 @@ use crate::common::encoder::Encoder;
|
|||||||
|
|
||||||
pub struct Service {
|
pub struct Service {
|
||||||
pub index_scheduler: Arc<IndexScheduler>,
|
pub index_scheduler: Arc<IndexScheduler>,
|
||||||
pub auth: AuthController,
|
pub auth: Arc<AuthController>,
|
||||||
pub options: Opt,
|
pub options: Opt,
|
||||||
pub api_key: Option<String>,
|
pub api_key: Option<String>,
|
||||||
}
|
}
|
||||||
@ -107,7 +107,7 @@ impl Service {
|
|||||||
pub async fn request(&self, mut req: test::TestRequest) -> (Value, StatusCode) {
|
pub async fn request(&self, mut req: test::TestRequest) -> (Value, StatusCode) {
|
||||||
let app = test::init_service(create_app(
|
let app = test::init_service(create_app(
|
||||||
self.index_scheduler.clone().into(),
|
self.index_scheduler.clone().into(),
|
||||||
self.auth.clone(),
|
self.auth.clone().into(),
|
||||||
self.options.clone(),
|
self.options.clone(),
|
||||||
analytics::MockAnalytics::new(&self.options),
|
analytics::MockAnalytics::new(&self.options),
|
||||||
true,
|
true,
|
||||||
|
Loading…
Reference in New Issue
Block a user