test(aws): the live idle stop holds a terminal open and polls in the background
The idle wait now keeps an attach open (silent) and runs the auth bridge's background exec every 2 s; the task must still stop itself and ECS must report it as an idle stop (exit 75 -> StopKind::Idle). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ce020f79a1
commit
8a3c552958
1 file changed
+39
-6
@@ -2326,8 +2326,29 @@ mod environment {
|
||||
let (check, _) = sh(&target2, "root", "TRIPLEC_IDLE_STOP_MINUTES=5 /usr/local/bin/triple-c-idle-watch --check; echo idle-check=$?").await;
|
||||
eprintln!("RESULT idle --check right after use: {}", check.trim());
|
||||
|
||||
// Leave it alone: close the tunnel and watch ECS.
|
||||
tunnels::close(&id).await;
|
||||
// Leave it alone, the way a user does (R11): a terminal tab stays
|
||||
// open but silent (an attach held through the tunnel), and the
|
||||
// auth bridge's background poll keeps running every 2 s. Neither
|
||||
// may keep the workspace up.
|
||||
let held = target2
|
||||
.attach(crate::host::ExecSpec::new(vec!["cat".into()]).tty(true))
|
||||
.await
|
||||
.expect("hold a terminal open");
|
||||
let poller = {
|
||||
let t = target2.clone();
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
let _ = t
|
||||
.exec_oneshot_background(
|
||||
"claude",
|
||||
vec!["/usr/bin/cat".into(), "/proc/net/tcp".into()],
|
||||
crate::host::PROC_NET_OUTPUT_LIMIT,
|
||||
)
|
||||
.await;
|
||||
tokio::time::sleep(Duration::from_secs(2)).await;
|
||||
}
|
||||
})
|
||||
};
|
||||
let idle_from = std::time::Instant::now();
|
||||
let stopped2 = poll(Duration::from_secs(15 * 60), Duration::from_secs(20), || async {
|
||||
let d = api.describe(&env.cluster_arn, std::slice::from_ref(&task2)).await.ok()?;
|
||||
@@ -2335,18 +2356,30 @@ mod environment {
|
||||
(t.desired_status == "STOPPED" || t.last_status == "STOPPED").then_some(t)
|
||||
})
|
||||
.await
|
||||
.expect("the idle task did not stop by itself within 15 minutes");
|
||||
.expect("the idle task did not stop by itself within 15 minutes (open tab + background poll)");
|
||||
poller.abort();
|
||||
drop(held);
|
||||
tunnels::close(&id).await;
|
||||
eprintln!(
|
||||
"RESULT idle stop: desired STOPPED {:?} after the last use; code {:?}, reason {:?}",
|
||||
idle_from.elapsed(),
|
||||
stopped2.stop_code,
|
||||
stopped2.stopped_reason
|
||||
);
|
||||
poll(Duration::from_secs(240), Duration::from_secs(10), || async {
|
||||
let final2 = poll(Duration::from_secs(240), Duration::from_secs(10), || async {
|
||||
let d = api.describe(&env.cluster_arn, std::slice::from_ref(&task2)).await.ok()?;
|
||||
(d.first()?.last_status == "STOPPED").then_some(())
|
||||
let t = d.into_iter().next()?;
|
||||
(t.last_status == "STOPPED").then_some(t)
|
||||
})
|
||||
.await;
|
||||
.await
|
||||
.expect("task 2 never reached STOPPED");
|
||||
eprintln!(
|
||||
"RESULT idle stop as ECS reports it: code {:?}, exit {:?}, kind {:?}",
|
||||
final2.stop_code,
|
||||
final2.exit_code,
|
||||
crate::aws::tasks::classify_stop(&final2)
|
||||
);
|
||||
assert_eq!(crate::aws::tasks::classify_stop(&final2), crate::aws::tasks::StopKind::Idle);
|
||||
tokio::time::sleep(Duration::from_secs(15)).await;
|
||||
let log2 = api.log_tail(&env.log_group, &task_log_stream(&stream_prefix, &task2), 60).await.unwrap();
|
||||
let tail2: Vec<&String> = log2.iter().filter(|l| l.contains("stopping") || l.contains("idle")).collect();
|
||||
|
||||
Reference in new issue
Block a user