Skip to content

Commit

Permalink
fix: refactored logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Pratik Mishra authored and Pratik Mishra committed Nov 27, 2024
1 parent a31c1b7 commit 9ade762
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 139 deletions.
196 changes: 68 additions & 128 deletions crates/context_aware_config/src/api/dimension/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub fn endpoints() -> Scope {
.service(create)
.service(get)
.service(delete_dimension)
.service(temp_position_update)
}

#[put("")]
Expand All @@ -48,7 +49,7 @@ async fn create(

let create_req = req.into_inner();
let schema_value = create_req.schema;
let n_dimensions: i64 = dimensions.count().get_result(&mut conn)?;

validate_jsonschema(&state.meta_schema, &schema_value)?;

let schema_compile_result = JSONSchema::options()
Expand All @@ -73,34 +74,10 @@ async fn create(
}
};

let req_priority_val: i32 = create_req.priority.clone().into();
let dimension_name: String = create_req.dimension.clone().into();
let req_position_val = Into::<Option<i32>>::into(create_req.position.clone());

let mut results: Vec<(String, i32, i32)> = dimensions
.order(priority.asc())
.select((dimension, priority, position))
.load::<(String, i32, i32)>(&mut conn)
.map_err(|err| {
log::error!("failed to fetch dimensions with error: {}", err);
unexpected_error!("Something went wrong")
})?;
let prev_position_index = results
.iter()
.position(|(name, _, _)| name.to_owned() == dimension_name.clone());
results.push((dimension_name.clone(), req_priority_val, 0));
results.sort_by_key(|&(_, val, _)| val);
let new_position_index = results
.iter()
.position(|(name, _, _)| name.to_owned() == dimension_name);
let mut position_val = new_position_index.unwrap_or(1) as i32;
if let Some(val) = req_position_val.clone() {
position_val = val;
}
let mut new_dimension = Dimension {
let new_dimension = Dimension {
dimension: create_req.dimension.into(),
priority: create_req.priority.clone().into(),
position: position_val.clone(),
priority: create_req.priority.into(),
position: 0, // hard coded for now till we migrate
schema: schema_value,
created_by: user.get_email(),
created_at: Utc::now(),
Expand All @@ -109,107 +86,40 @@ async fn create(
last_modified_by: user.get_email(),
};

/*
Ongoing Migration logic
Position will be an optional argument during migration,
case 1 : Create request - position value not given
we will sort the dimension(including current one) based on priority
will calculate position value based on priority value and create dimension
case 2 : Create/update request position value given
we will use the request data and insert without calculating anything on our end
case 3: Update request - position not given
get dimension list , sort on priority
calculate prev position
put update dimension priority in list
then calculate new position
update all the row's position value according to it
In all cases we will adjust the position value for all other rows
*/

conn.transaction::<_, superposition::AppError, _>(|transaction_conn| {
match (
prev_position_index,
new_position_index.clone(),
req_position_val.clone(),
) {
(Some(prev_position_val), Some(new_position_val), None) => {
if prev_position_val < new_position_val {
new_dimension.position = new_position_val.clone() as i32 - 1;
// as it is calculated with 1 duplicate dimension so -1
} else {
new_dimension.position = new_position_val.clone() as i32
};
diesel::update(dimensions)
.filter(position.gt(prev_position_val as i32))
.filter(position.lt(new_position_val.clone() as i32))
.filter(position.gt(0))
.set(position.eq(position - 1))
.execute(transaction_conn)?;

diesel::update(dimensions)
.filter(position.ge(new_position_val as i32))
.set(position.eq(position + 1))
.execute(transaction_conn)?;
}
(None, Some(new_position_index), None) => {
new_dimension.position = new_position_index.clone() as i32;
diesel::update(dimensions)
.filter(position.ge(new_position_index as i32))
.set(position.eq(position + 1))
.execute(transaction_conn)?;
}
(_, _, Some(val)) => {
if val > n_dimensions.clone() as i32 {
return Err(bad_argument!(
"Expected psoition value less than {}",
n_dimensions
));
}
diesel::update(dimensions::dsl::dimensions)
.filter(dimensions::position.ge(val))
.set(dimensions::position.eq(dimensions::position + 1))
.execute(transaction_conn)?;
}
(_, _, _) => {}
};

let upsert = diesel::insert_into(dimensions)
.values(&new_dimension)
.on_conflict(dimensions::dimension)
.do_update()
.set(&new_dimension)
.get_result::<Dimension>(transaction_conn);

match upsert {
Ok(upserted_dimension) => {
let is_mandatory = tenant_config
.mandatory_dimensions
.contains(&upserted_dimension.dimension);
Ok(HttpResponse::Created().json(DimensionWithMandatory::new(
upserted_dimension,
is_mandatory,
)))
}
Err(diesel::result::Error::DatabaseError(
diesel::result::DatabaseErrorKind::ForeignKeyViolation,
e,
)) => {
log::error!("{fun_name:?} function not found with error: {e:?}");
Err(bad_argument!(
"Function {} doesn't exists",
fun_name.unwrap_or(String::new())
))
}
Err(e) => {
log::error!("Dimension upsert failed with error: {e}");
Err(unexpected_error!(
"Something went wrong, failed to create/update dimension"
))
}
let upsert = diesel::insert_into(dimensions)
.values(&new_dimension)
.on_conflict(dimensions::dimension)
.do_update()
.set(&new_dimension)
.get_result::<Dimension>(&mut conn);

match upsert {
Ok(upserted_dimension) => {
let is_mandatory = tenant_config
.mandatory_dimensions
.contains(&upserted_dimension.dimension);
Ok(HttpResponse::Created().json(DimensionWithMandatory::new(
upserted_dimension,
is_mandatory,
)))
}
})
Err(diesel::result::Error::DatabaseError(
diesel::result::DatabaseErrorKind::ForeignKeyViolation,
e,
)) => {
log::error!("{fun_name:?} function not found with error: {e:?}");
Err(bad_argument!(
"Function {} doesn't exists",
fun_name.unwrap_or(String::new())
))
}
Err(e) => {
log::error!("Dimension upsert failed with error: {e}");
Err(unexpected_error!(
"Something went wrong, failed to create/update dimension"
))
}
}
}

#[get("")]
Expand Down Expand Up @@ -304,3 +214,33 @@ async fn delete_dimension(
))
}
}

#[put("/position/update")]
async fn temp_position_update(
user: User,
db_conn: DbConnection,
) -> superposition::Result<HttpResponse> {
let DbConnection(mut conn) = db_conn;
let results: Vec<(String, i32, i32)> = dimensions
.order(priority.asc())
.select((dimension, priority, position))
.load::<(String, i32, i32)>(&mut conn)
.map_err(|err| {
log::error!("failed to fetch dimensions with error: {}", err);
unexpected_error!("Something went wrong")
})?;

let _ = for (index, (dim, pri, _)) in results.iter().enumerate() {
diesel::update(dimensions)
.filter(dimension.eq(dim))
.filter(priority.eq(*pri))
.set((
position.eq(index as i32),
last_modified_at.eq(Utc::now().naive_utc()),
last_modified_by.eq(user.get_email()),
))
.execute(&mut conn)?;
};
Ok(HttpResponse::Ok()
.json(serde_json::json!({"message": "Position updated sucessfully"})))
}
1 change: 0 additions & 1 deletion crates/context_aware_config/src/api/dimension/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use superposition_types::{cac::models::Dimension, RegexEnum};
pub struct CreateReq {
pub dimension: DimensionName,
pub priority: Priority,
pub position: Position,
pub schema: Value,
#[serde(default, deserialize_with = "deserialize_option")]
pub function_name: Option<Value>,
Expand Down
7 changes: 3 additions & 4 deletions postman/cac.postman_collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@
"language": "json"
}
},
"raw": "{\"dimension\":\"clientId\",\"priority\":100,\"position\":0,\"schema\":{\"type\":\"string\",\"pattern\":\"^[a-z0-9].*$\"}}"
"raw": "{\"dimension\":\"clientId\",\"priority\":100,\"schema\":{\"type\":\"string\",\"pattern\":\"^[a-z0-9].*$\"}}"
},
"url": {
"raw": "{{host}}/dimension",
Expand Down Expand Up @@ -483,7 +483,6 @@
" \"type\": \"string\",",
" \"pattern\": \".*\"",
" }",
" \"position\": 1,",
" })",
" }",
" };",
Expand Down Expand Up @@ -1237,7 +1236,7 @@
" \"type\": \"string\",",
" \"pattern\": \"^[a-z0-9].*$\"",
" }",
" \"position\": 2,",
" \"position\": 0,",
" })",
" }",
" };",
Expand Down Expand Up @@ -1281,7 +1280,7 @@
" throw error;",
" }",
" console.log(response.json())",
" pm.expect(response.json().weight).to.be.eq(\"4\");",
" pm.expect(response.json().weight).to.be.eq(\"1\");",
"",
" })",
" ",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ function update_dimension_position() {
"schema": {
"type": "string",
"pattern": "^[a-z0-9].*$"
},
"position": 2,
}
})
}
};
Expand Down
2 changes: 1 addition & 1 deletion postman/cac/Context/Recompute Weight Context/event.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function getContextAndTest() {
throw error;
}
console.log(response.json())
pm.expect(response.json().weight).to.be.eq("4");
pm.expect(response.json().weight).to.be.eq("1");

})

Expand Down
1 change: 0 additions & 1 deletion postman/cac/Dimension/Create Dimension/request.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
"raw_json_formatted": {
"dimension": "clientId",
"priority": 100,
"position": 0,
"schema": {
"type": "string",
"pattern": "^[a-z0-9].*$"
Expand Down
3 changes: 1 addition & 2 deletions postman/cac/Dimension/Delete Dimension/event.prerequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ function add_dimension() {
"schema": {
"type": "string",
"pattern": ".*"
},
"position":1
}
})
}
};
Expand Down

0 comments on commit 9ade762

Please sign in to comment.