Skip to content

Commit e6adf05

Browse files
Fix answering questions (#2822)
- Fix answering questions, which was not working. - Flatten the body to PATCH questions. - Add the missing Agama::HTTP::Base#patch method. --------- Co-authored-by: José Iván López <[email protected]>
1 parent 526850c commit e6adf05

File tree

7 files changed

+49
-22
lines changed

7 files changed

+49
-22
lines changed

rust/agama-lib/src/questions/http_client.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use agama_utils::api::{
2424
config::Patch,
2525
question::{
2626
Answer, AnswerRule, Config as QuestionsConfig, Policy, Question, QuestionSpec,
27-
UpdateOperation,
27+
UpdateQuestion,
2828
},
2929
Config,
3030
};
@@ -128,7 +128,7 @@ impl HTTPClient {
128128
}
129129

130130
pub async fn delete_question(&self, id: u32) -> Result<(), QuestionsHTTPClientError> {
131-
let update = UpdateOperation::Delete { id };
131+
let update = UpdateQuestion::Delete { id };
132132
self.client.patch_void("/v2/questions", &update).await?;
133133
Ok(())
134134
}

rust/agama-server/src/server/web.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use agama_utils::{
2626
actor::Handler,
2727
api::{
2828
config, event,
29-
question::{Question, QuestionSpec, UpdateOperation},
29+
question::{Question, QuestionSpec, UpdateQuestion},
3030
Action, Config, IssueMap, Status, SystemInfo,
3131
},
3232
question,
@@ -287,24 +287,24 @@ async fn ask_question(
287287
patch,
288288
path = "/questions",
289289
context_path = "/api/v2",
290-
request_body = UpdateOperation,
290+
request_body = UpdateQuestion,
291291
responses(
292292
(status = 200, description = "The question was answered or deleted"),
293293
(status = 400, description = "It was not possible to update the question")
294294
)
295295
)]
296296
async fn update_question(
297297
State(state): State<ServerState>,
298-
Json(operation): Json<UpdateOperation>,
298+
Json(operation): Json<UpdateQuestion>,
299299
) -> ServerResult<()> {
300300
match operation {
301-
UpdateOperation::Answer { id, answer } => {
301+
UpdateQuestion::Answer { id, answer } => {
302302
state
303303
.questions
304304
.call(question::message::Answer { id, answer })
305305
.await?;
306306
}
307-
UpdateOperation::Delete { id } => {
307+
UpdateQuestion::Delete { id } => {
308308
state
309309
.questions
310310
.call(question::message::Delete { id })

rust/agama-server/src/web/docs/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ impl ApiDocBuilder for ConfigApiDocBuilder {
180180
.schema_from::<agama_utils::api::question::QuestionField>()
181181
.schema_from::<agama_utils::api::question::QuestionSpec>()
182182
.schema_from::<agama_utils::api::question::SelectionOption>()
183-
.schema_from::<agama_utils::api::question::UpdateOperation>()
183+
.schema_from::<agama_utils::api::question::UpdateQuestion>()
184184
.schema_from::<agama_utils::api::status::State>()
185185
.schema_from::<crate::software::web::SoftwareProposal>()
186186
.build()

rust/agama-utils/src/api/question.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,9 +319,14 @@ pub struct Answer {
319319
///
320320
/// It is used by the HTTP layer only.
321321
#[derive(Serialize, Deserialize, utoipa::ToSchema)]
322-
pub enum UpdateOperation {
322+
#[serde(rename_all = "camelCase")]
323+
pub enum UpdateQuestion {
323324
/// Answer the question with the given answer.
324-
Answer { id: u32, answer: Answer },
325+
Answer {
326+
id: u32,
327+
#[serde(flatten)]
328+
answer: Answer,
329+
},
325330
/// Remove the question.
326331
Delete { id: u32 },
327332
}

service/lib/agama/http/clients/base.rb

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ def initialize(logger)
3434
end
3535

3636
# send POST request with given data and path.
37-
# @param path[String] path relatived to `api`` endpoint.
38-
# @param data[#to_json] data to send in request
37+
# @param path [String] path relatived to `api`` endpoint.
38+
# @param data [#to_json] data to send in request
3939
def post(path, data)
4040
response = Net::HTTP.post(uri(path), data.to_json, headers)
4141
return response unless response.is_a?(Net::HTTPClientError)
@@ -44,7 +44,7 @@ def post(path, data)
4444
end
4545

4646
# send GET request with given path.
47-
# @param path[String] path relatived to `api`` endpoint.
47+
# @param path [String] path relatived to `api`` endpoint.
4848
# @return [Net::HTTPResponse, nil] Net::HTTPResponse if it is not an Net::HTTPClientError
4949
def get(path)
5050
response = Net::HTTP.get(uri(path), headers)
@@ -54,15 +54,27 @@ def get(path)
5454
end
5555

5656
# send PUT request with given data and path.
57-
# @param path[String] path relatived to `api`` endpoint.
58-
# @param data[#to_json] data to send in request
57+
# @param path [String] path relatived to `api`` endpoint.
58+
# @param data [#to_json] data to send in request
5959
def put(path, data)
6060
response = Net::HTTP.put(uri(path), data.to_json, headers)
6161
return unless response.is_a?(Net::HTTPClientError)
6262

6363
@logger.warn "server returned #{response.code} with body: #{response.body}"
6464
end
6565

66+
# send PATCH request with given data and path.
67+
# @param path [String] path relatived to `api`` endpoint.
68+
# @param data [#to_json] data to send in request
69+
def patch(path, data)
70+
url = uri(path)
71+
http = Net::HTTP.start(url.hostname, url.port, use_ssl: url.scheme == "https")
72+
response = http.patch(url, data.to_json, headers)
73+
return response unless response.is_a?(Net::HTTPClientError)
74+
75+
@logger.warn "server returned #{response.code} with body: #{response.body}"
76+
end
77+
6678
protected
6779

6880
def uri(path)

service/lib/agama/http/clients/questions.rb

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ module HTTP
2727
module Clients
2828
# HTTP client to interact with the files API.
2929
class Questions < Base
30+
class CouldNotAddQuestion < StandardError; end
31+
3032
# Adds a question
3133
#
3234
# @param question [Agama::Question]
@@ -46,7 +48,7 @@ def questions
4648
# @return [void]
4749
def delete(id)
4850
payload = { "delete" => { "id" => id } }
49-
patch("/v2/questions", payload)
51+
patch("v2/questions", payload)
5052
end
5153

5254
# Waits until specified question is answered
@@ -79,13 +81,18 @@ def wait_answer(id)
7981
# @return [Agama::Answer] The question answer, or the result of the block in case a block
8082
# is given.
8183
def ask(question)
82-
question_id = add(question)
83-
answer = wait_answer(question_id)
84+
added_question = add(question)
85+
if added_question.nil?
86+
@logger.error "Could not add a question with data: {question.inspect}"
87+
raise CouldNotAddQuestion
88+
end
89+
90+
answer = wait_answer(added_question.id)
8491

85-
logger.info("#{question.text} #{answer}")
92+
@logger.info("#{added_question.text} #{answer}")
8693

8794
result = block_given? ? yield(answer) : answer
88-
delete(question_id)
95+
delete(added_question.id)
8996

9097
result
9198
end

web/src/api/questions.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,11 @@ const fetchQuestions = async (): Promise<Question[]> => await get("/api/v2/quest
3434
* The answer is part of the Question object.
3535
*/
3636
const updateAnswer = async (question: Question): Promise<void> => {
37-
const { id, answer } = question;
38-
await patch(`/api/v2/questions`, { id, answer });
37+
const {
38+
id,
39+
answer: { action, value },
40+
} = question;
41+
await patch(`/api/v2/questions`, { answer: { id, action, value } });
3942
};
4043

4144
export { fetchQuestions, updateAnswer };

0 commit comments

Comments
 (0)