Skip to content

Commit 99778b3

Browse files
authored
Add AllStopped command and endpoint for downstairs status (#1718)
Closes #1660 This PR introduces the `dsc cmd all-stopped` command to reliably check if all "downstairs" services are stopped. This replaces previous `sleep`-based checks in tests, reducing potential flakiness. ### Changes * Added `AllStopped` command to `dsc/src/client.rs` and corresponding handling. * Implemented the `/allstopped` GET endpoint in `dsc/src/control.rs`. * Added the `all_stopped` logic to `DscInfo` in `dsc/src/main.rs`, considering `Running`, `Starting`, or `Stopping` states as not stopped. * Updated `openapi/dsc-control.json` with the new endpoint definition. * Modified `tools/test_dsc.sh` to utilize the new `all-stopped` command. All tests pass with these changes.
1 parent 73844e1 commit 99778b3

5 files changed

Lines changed: 68 additions & 20 deletions

File tree

dsc/src/client.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use anyhow::Result;
1010
pub enum ClientCommand {
1111
/// Returns true if all downstairs are running
1212
AllRunning,
13+
/// Returns true if all downstairs are stopped
14+
AllStopped,
1315
/// Disable random stopping of downstairs
1416
DisableRandomStop,
1517
/// Disable auto restart on the given downstairs client ID
@@ -91,6 +93,10 @@ pub async fn client_main(server: String, cmd: ClientCommand) -> Result<()> {
9193
let res = dsc.dsc_all_running().await.unwrap();
9294
println!("{:?}", res);
9395
}
96+
ClientCommand::AllStopped => {
97+
let res = dsc.dsc_all_stopped().await.unwrap();
98+
println!("{:?}", res);
99+
}
94100
ClientCommand::DisableRandomStop => {
95101
let _ = dsc.dsc_disable_random_stop().await.unwrap();
96102
}

dsc/src/control.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use super::*;
1919
pub(crate) fn build_api() -> ApiDescription<Arc<DownstairsControl>> {
2020
let mut api = ApiDescription::new();
2121
api.register(dsc_all_running).unwrap();
22+
api.register(dsc_all_stopped).unwrap();
2223
api.register(dsc_get_ds_state).unwrap();
2324
api.register(dsc_get_pid).unwrap();
2425
api.register(dsc_get_port).unwrap();
@@ -205,6 +206,22 @@ async fn dsc_all_running(
205206
Ok(HttpResponseOk(all_state))
206207
}
207208

209+
/**
210+
* Return true if all downstairs are stopped
211+
*/
212+
#[endpoint {
213+
method = GET,
214+
path = "/allstopped",
215+
}]
216+
async fn dsc_all_stopped(
217+
rqctx: RequestContext<Arc<DownstairsControl>>,
218+
) -> Result<HttpResponseOk<bool>, HttpError> {
219+
let api_context = rqctx.context();
220+
221+
let all_state = api_context.dsci.all_stopped().await;
222+
Ok(HttpResponseOk(all_state))
223+
}
224+
208225
/**
209226
* Fetch the current state for the requested client_id
210227
*/

dsc/src/main.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,19 @@ impl DscInfo {
715715
true
716716
}
717717

718+
async fn all_stopped(&self) -> bool {
719+
let rs = self.rs.lock().await;
720+
for state in rs.ds_state.iter() {
721+
if *state == DownstairsState::Running
722+
|| *state == DownstairsState::Starting
723+
|| *state == DownstairsState::Stopping
724+
{
725+
return false;
726+
}
727+
}
728+
true
729+
}
730+
718731
async fn get_ds_state(&self, client_id: usize) -> Result<DownstairsState> {
719732
let rs = self.rs.lock().await;
720733
if rs.ds_state.len() <= client_id {

openapi/dsc-control.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,31 @@
3030
}
3131
}
3232
},
33+
"/allstopped": {
34+
"get": {
35+
"summary": "Return true if all downstairs are stopped",
36+
"operationId": "dsc_all_stopped",
37+
"responses": {
38+
"200": {
39+
"description": "successful operation",
40+
"content": {
41+
"application/json": {
42+
"schema": {
43+
"title": "Boolean",
44+
"type": "boolean"
45+
}
46+
}
47+
}
48+
},
49+
"4XX": {
50+
"$ref": "#/components/responses/Error"
51+
},
52+
"5XX": {
53+
"$ref": "#/components/responses/Error"
54+
}
55+
}
56+
}
57+
},
3358
"/disablerestart/all": {
3459
"post": {
3560
"summary": "Disable automatic restart on all downstairs",

tools/test_dsc.sh

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -266,26 +266,13 @@ fi
266266
# downstairs should automatically restart.
267267
sleep 4
268268
echo "Verify all ds are stopped"
269-
for cid in {0..2}; do
270-
retry=1
271-
# Loop until we find exit, or have exhausted our retry count
272-
while :; do
273-
state=$(curl -s "${dsc_url}"state/cid/0 | tr -d \")
274-
if [[ "$state" == "exit" ]]; then
275-
echo "cid $cid in $state after $retry attempt(s)"
276-
break;
277-
fi
278-
echo "cid $cid Failed to stop: $state, try:$retry" | tee -a "$fail_log"
279-
if [[ "$retry" -ge 10 ]]; then
280-
echo "cid $cid Failed to stop: $state, abort" | tee -a "$fail_log"
281-
(( res += 1 ))
282-
exit 1
283-
break;
284-
fi
285-
(( retry += 1 ))
286-
sleep 3
287-
done
288-
done
269+
all_stopped_check=$("${dsc}" cmd all-stopped)
270+
if [[ "$all_stopped_check" != "true" ]]; then
271+
echo "Failed: all-stopped returned $all_stopped_check" | tee -a "$fail_log"
272+
(( res += 1 ))
273+
else
274+
echo "All downstairs are stopped"
275+
fi
289276

290277
echo "Start up ds 1 manually"
291278
hc=$(curl ${curl_flags} -X POST -H "Content-Type: application/json" -w "%{http_code}\n" "${dsc_url}"start/cid/1)

0 commit comments

Comments
 (0)