Skip to content

Commit

Permalink
feat: get state of a instance
Browse files Browse the repository at this point in the history
  • Loading branch information
lauti7 committed Jun 7, 2024
1 parent 9e2d0b5 commit c9bcce6
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 9 deletions.
2 changes: 1 addition & 1 deletion crates/protocol/src/quests/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl From<&QuestGraph> for QuestState {
}
}

pub fn get_state(quest: &Quest, events: Vec<Event>) -> QuestState {
pub fn get_state(quest: &Quest, events: &[Event]) -> QuestState {
let quest_graph = QuestGraph::from(quest);
let initial_state = (&quest_graph).into();
events.iter().fold(initial_state, |state, event| {
Expand Down
7 changes: 6 additions & 1 deletion crates/server/src/api/routes/quest_instances/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
pub mod reset;
pub mod state;

use actix_web::Scope;
pub use reset::*;
pub use state::*;

pub fn services(api_scope: Scope) -> Scope {
api_scope.service(reset::reset_quest_instance)
api_scope
.service(reset_quest_instance)
.service(get_quest_instance_state)
}
54 changes: 54 additions & 0 deletions crates/server/src/api/routes/quest_instances/state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use crate::{api::middlewares::RequiredAuthUser, domain::quests::QuestError};
use actix_web::{get, web, HttpResponse};
use quests_db::{
core::definitions::{Event, QuestsDatabase},
Database,
};
use quests_protocol::definitions::QuestState;
use quests_system::get_instance_state;
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

#[derive(Serialize, Deserialize, ToSchema)]
pub struct GetInstanceStateResponse {
pub state: QuestState,
pub events: Vec<Event>,
}

/// Get Quest Instance's state. Allowed for the Quest Creator
#[utoipa::path(
params(
("quest_instance" = String, description = "Quest Instance UUID")
),
responses(
(status = 200, description = "Quest Instance state", body = GetInstanceStateResponse),
(status = 401, description = "Unauthorized"),
(status = 403, description = "Forbidden"),
(status = 404, description = "Quest Instance not found"),
(status = 500, description = "Internal Server Error")
)
)]
#[get("/instances/{quest_instance}/state")]
pub async fn get_quest_instance_state(
data: web::Data<Database>,
quest_instance: web::Path<String>,
auth_user: RequiredAuthUser,
) -> HttpResponse {
let db = data.into_inner();

let RequiredAuthUser { address } = auth_user;

match db.get_quest_instance(&quest_instance).await {
Ok(instance) => match db.is_quest_creator(&instance.quest_id, &address).await {
Ok(is_creator) if !is_creator => HttpResponse::from_error(QuestError::NotQuestCreator),
Ok(_) => match get_instance_state(db.clone(), &instance.quest_id, &instance.id).await {
Ok((_, state, events)) => {
HttpResponse::Ok().json(GetInstanceStateResponse { state, events })
}
Err(err) => HttpResponse::from_error(QuestError::from(err)),
},
Err(err) => HttpResponse::from_error(QuestError::from(err)),
},
Err(err) => HttpResponse::from_error(QuestError::from(err)),
}
}
2 changes: 1 addition & 1 deletion crates/server/src/domain/quests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub async fn abandon_quest(
return Err(QuestError::NotInstanceOwner);
}

let (_, quest_state) =
let (_, quest_state, _) =
get_instance_state(db.clone(), &quest_instance.quest_id, &quest_instance.id).await?;
if quest_state.is_completed() {
return Err(QuestError::QuestAlreadyCompleted);
Expand Down
2 changes: 1 addition & 1 deletion crates/server/src/rpc/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl QuestsServiceServer<QuestsRpcServerContext, ServiceError> for QuestsService
)
.await
{
Ok((quest, quest_state)) => {
Ok((quest, quest_state, _)) => {
transport_context
.quest_instance_ids
.lock()
Expand Down
13 changes: 8 additions & 5 deletions crates/system/src/quests.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use std::sync::Arc;

use futures_util::future::join_all;
use quests_db::core::{definitions::QuestsDatabase, errors::DBError};
use quests_db::core::{
definitions::{Event as StoredEvent, QuestsDatabase},
errors::DBError,
};
use quests_protocol::{
definitions::{Event, ProtocolMessage, Quest, QuestDefinition, QuestState},
quests::get_state,
Expand Down Expand Up @@ -64,7 +67,7 @@ pub async fn get_all_quest_states_by_user_address(
for join_result in join_results {
match join_result {
Ok((id, state_result)) => match state_result {
Ok(state) => states.push((id, state)),
Ok((quest, state, _)) => states.push((id, (quest, state))),
Err(quest_error) => return Err(quest_error),
},
Err(_) => return Err(QuestStateCalculationError::StateError),
Expand All @@ -77,7 +80,7 @@ pub async fn get_instance_state(
database: Arc<impl QuestsDatabase>,
quest_id: &str,
quest_instance: &str,
) -> Result<(Quest, QuestState), QuestStateCalculationError> {
) -> Result<(Quest, QuestState, Vec<StoredEvent>), QuestStateCalculationError> {
let quest = get_quest_with_decoded_definition(database.clone(), quest_id).await?;
let stored_events = database
.get_events(quest_instance)
Expand All @@ -90,7 +93,7 @@ pub async fn get_instance_state(
.collect::<Result<Vec<_>, _>>()
.map_err(|_| QuestStateCalculationError::DefinitionError)?;

let state = get_state(&quest, events);
let state = get_state(&quest, &events);

Ok((quest, state))
Ok((quest, state, stored_events))
}

0 comments on commit c9bcce6

Please sign in to comment.