Skip to content

Commit

Permalink
feat: get config-versions api (#248)
Browse files Browse the repository at this point in the history
* feat: get config-versions api

* feat: change endpoint to config/versions
  • Loading branch information
mahatoankitkumar authored Sep 30, 2024
1 parent d6adef2 commit 260392c
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 20 deletions.
71 changes: 52 additions & 19 deletions crates/context_aware_config/src/api/config/handlers.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
use std::{collections::HashMap, str::FromStr};

use super::helpers::{
filter_config_by_dimensions, filter_config_by_prefix, get_query_params_map,
};
use super::types::{Config, Context};
use crate::api::context::{
delete_context_api, hash, put, validate_dimensions_and_calculate_priority, PutReq,
};
use crate::api::dimension::get_all_dimension_schema_map;
use crate::db::models::ConfigVersion;
use crate::{
db::schema::{config_versions::dsl as config_versions, event_log::dsl as event_log},
helpers::generate_cac,
};
use actix_http::header::HeaderValue;
use actix_web::web::{Json, Query};
use actix_web::{get, put, web, HttpRequest, HttpResponse, HttpResponseBuilder, Scope};
use cac_client::{eval_cac, eval_cac_with_reasoning, MergeStrategy};
use chrono::{DateTime, NaiveDateTime, TimeZone, Timelike, Utc};
Expand All @@ -9,38 +23,27 @@ use diesel::{
r2d2::{ConnectionManager, PooledConnection},
ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl,
};
use serde_json::{json, Map, Value};
use superposition_macros::{bad_argument, db_error, unexpected_error};
use superposition_types::{
result as superposition, Cac, Condition, Overrides, PaginatedResponse, QueryFilters,
TenantConfig, User,
};

use itertools::Itertools;
use jsonschema::JSONSchema;
use serde_json::{json, Map, Value};
use service_utils::{
helpers::extract_dimensions,
service::types::{AppHeader, DbConnection},
};
use superposition_macros::{bad_argument, db_error, unexpected_error};
use superposition_types::{
result as superposition, Cac, Condition, Overrides, TenantConfig, User,
};
use uuid::Uuid;

use crate::api::context::{
delete_context_api, hash, put, validate_dimensions_and_calculate_priority, PutReq,
};
use crate::api::dimension::get_all_dimension_schema_map;
use crate::{
db::schema::{config_versions::dsl as config_versions, event_log::dsl as event_log},
helpers::generate_cac,
};

use super::helpers::{
filter_config_by_dimensions, filter_config_by_prefix, get_query_params_map,
};
use super::types::{Config, Context};

pub fn endpoints() -> Scope {
Scope::new("")
.service(get)
.service(get_resolved_config)
.service(reduce_config)
.service(get_config_versions)
}

fn validate_version_in_params(
Expand Down Expand Up @@ -654,3 +657,33 @@ async fn get_resolved_config(

Ok(resp.json(response))
}

#[get("/versions")]
async fn get_config_versions(
db_conn: DbConnection,
filters: Query<QueryFilters>,
) -> superposition::Result<Json<PaginatedResponse<ConfigVersion>>> {
let DbConnection(mut conn) = db_conn;

let n_version: i64 = config_versions::config_versions
.count()
.get_result(&mut conn)?;
let mut builder = config_versions::config_versions
.into_boxed()
.order(config_versions::created_at.desc());
if let Some(limit) = filters.count {
builder = builder.limit(limit);
}
if let Some(page) = filters.page {
let offset = (page - 1) * filters.count.unwrap_or(10);
builder = builder.offset(offset);
}
let limit = filters.count.unwrap_or(10);
let config_versions: Vec<ConfigVersion> = builder.load(&mut conn)?;
let total_pages = (n_version as f64 / limit as f64).ceil() as i64;
Ok(Json(PaginatedResponse {
total_pages,
total_items: n_version,
data: config_versions,
}))
}
47 changes: 46 additions & 1 deletion crates/superposition_types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use actix_web::{dev::Payload, error, FromRequest, HttpMessage, HttpRequest};
use derive_more::{AsRef, Deref, DerefMut, Into};
use log::error;
use regex::Regex;
use serde::{Deserialize, Deserializer, Serialize};
use serde::{de, Deserialize, Deserializer, Serialize};
use serde_json::{json, Map, Value};

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down Expand Up @@ -441,3 +441,48 @@ mod tests {
);
}
}

#[derive(Debug, Clone)]
pub struct QueryFilters {
pub count: Option<i64>,
pub page: Option<i64>,
}

impl<'de> Deserialize<'de> for QueryFilters {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
struct Helper {
count: Option<i64>,
page: Option<i64>,
}

let helper = Helper::deserialize(deserializer)?;

if let Some(count) = helper.count {
if count <= 0 {
return Err(de::Error::custom("Count should be greater than 0."));
}
}

if let Some(page) = helper.page {
if page <= 0 {
return Err(de::Error::custom("Page should be greater than 0."));
}
}

Ok(QueryFilters {
count: helper.count,
page: helper.page,
})
}
}

#[derive(Serialize, Debug, Clone, Deserialize)]
pub struct PaginatedResponse<T> {
pub total_pages: i64,
pub total_items: i64,
pub data: Vec<T>,
}

0 comments on commit 260392c

Please sign in to comment.