Public release release-e7c2b3ac175d
Source commit: e7c2b3ac175db426791c02779841c5df1d0ffdff Public tree identity: sha256:4f0b7cd828932c06d56f2406788f89b2050ef56c1e1a4f76f55341d387d78e46
This commit is contained in:
parent
9f43c6276a
commit
cfd4f19da2
16 changed files with 1386 additions and 313 deletions
|
|
@ -66,6 +66,8 @@ pub(super) struct CoordinatorControlledProcessRunner {
|
|||
pub(super) node_private_key: String,
|
||||
pub(super) debug_control: Arc<WasmDebugControl>,
|
||||
pub(super) command_status: Arc<Mutex<Option<String>>>,
|
||||
pub(super) stdout_source_bytes: Arc<AtomicU64>,
|
||||
pub(super) stderr_source_bytes: Arc<AtomicU64>,
|
||||
pub(super) timeout: Duration,
|
||||
pub(super) configured_secrets: Vec<String>,
|
||||
}
|
||||
|
|
@ -85,6 +87,8 @@ impl CoordinatorControlledProcessRunner {
|
|||
node_private_key: host.node_private_key.clone(),
|
||||
debug_control: Arc::clone(&host.debug_control),
|
||||
command_status: Arc::clone(&host.command_status),
|
||||
stdout_source_bytes: Arc::clone(&host.command_stdout_source_bytes),
|
||||
stderr_source_bytes: Arc::clone(&host.command_stderr_source_bytes),
|
||||
timeout,
|
||||
configured_secrets,
|
||||
}
|
||||
|
|
@ -269,12 +273,13 @@ impl CoordinatorControlledProcessRunner {
|
|||
stream: &'static str,
|
||||
sender: SyncSender<LiveLogChunk>,
|
||||
configured_secrets: Vec<String>,
|
||||
source_bytes_total: Arc<AtomicU64>,
|
||||
) -> thread::JoinHandle<Result<Vec<u8>, String>> {
|
||||
thread::spawn(move || {
|
||||
let mut captured = Vec::new();
|
||||
let mut buffer = [0_u8; 16 * 1024];
|
||||
let mut source_offset = 0_u64;
|
||||
let mut pending_offset = 0_u64;
|
||||
let stream_base = source_bytes_total.load(Ordering::Relaxed);
|
||||
let mut pending_offset = stream_base;
|
||||
let mut pending = Vec::new();
|
||||
let mut discarded = false;
|
||||
loop {
|
||||
|
|
@ -284,6 +289,11 @@ impl CoordinatorControlledProcessRunner {
|
|||
if count == 0 {
|
||||
break;
|
||||
}
|
||||
let _ = source_bytes_total.fetch_update(
|
||||
Ordering::Relaxed,
|
||||
Ordering::Relaxed,
|
||||
|current| Some(current.saturating_add(count as u64)),
|
||||
);
|
||||
let remaining = maximum.saturating_sub(captured.len());
|
||||
let retained = count.min(remaining);
|
||||
if retained > 0 {
|
||||
|
|
@ -306,7 +316,6 @@ impl CoordinatorControlledProcessRunner {
|
|||
if retained < count {
|
||||
discarded = true;
|
||||
}
|
||||
source_offset = source_offset.saturating_add(count as u64);
|
||||
}
|
||||
if let Some((consumed, text)) =
|
||||
redact_safe_live_log_prefix(&pending, &configured_secrets, true)
|
||||
|
|
@ -322,7 +331,7 @@ impl CoordinatorControlledProcessRunner {
|
|||
if discarded {
|
||||
let _ = sender.try_send(LiveLogChunk {
|
||||
stream,
|
||||
offset: maximum as u64,
|
||||
offset: stream_base.saturating_add(maximum as u64),
|
||||
source_bytes: 0,
|
||||
bytes: b"[log output truncated at node capture limit]".to_vec(),
|
||||
truncated: true,
|
||||
|
|
@ -445,6 +454,7 @@ impl ProcessRunner for CoordinatorControlledProcessRunner {
|
|||
"stdout",
|
||||
live_log_sender.clone(),
|
||||
self.configured_secrets.clone(),
|
||||
Arc::clone(&self.stdout_source_bytes),
|
||||
);
|
||||
let stderr = Self::drain_bounded(
|
||||
child
|
||||
|
|
@ -455,6 +465,7 @@ impl ProcessRunner for CoordinatorControlledProcessRunner {
|
|||
"stderr",
|
||||
live_log_sender,
|
||||
self.configured_secrets.clone(),
|
||||
Arc::clone(&self.stderr_source_bytes),
|
||||
);
|
||||
let live_log_reporter = self.spawn_live_log_reporter(live_log_receiver);
|
||||
let mut session = match CoordinatorSession::connect(&self.args.coordinator) {
|
||||
|
|
@ -584,7 +595,10 @@ impl ProcessRunner for CoordinatorControlledProcessRunner {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::redact_safe_live_log_prefix;
|
||||
use super::{redact_safe_live_log_prefix, CoordinatorControlledProcessRunner};
|
||||
use std::io::Cursor;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use std::sync::{mpsc, Arc};
|
||||
|
||||
#[test]
|
||||
fn live_log_redaction_holds_boundaries_until_split_secrets_are_complete() {
|
||||
|
|
@ -600,4 +614,30 @@ mod tests {
|
|||
assert!(!combined.contains("correct-"));
|
||||
assert!(!combined.contains("horse"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bounded_capture_retains_the_complete_source_byte_count() {
|
||||
let source_bytes = Arc::new(AtomicU64::new(5));
|
||||
let (sender, receiver) = mpsc::sync_channel(8);
|
||||
let reader = CoordinatorControlledProcessRunner::drain_bounded(
|
||||
Cursor::new(vec![b'x'; 32]),
|
||||
8,
|
||||
"stdout",
|
||||
sender,
|
||||
Vec::new(),
|
||||
Arc::clone(&source_bytes),
|
||||
);
|
||||
let captured = reader.join().unwrap().unwrap();
|
||||
let chunks = receiver.into_iter().collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(captured, vec![b'x'; 8]);
|
||||
assert_eq!(source_bytes.load(Ordering::Relaxed), 37);
|
||||
assert_eq!(
|
||||
chunks.iter().map(|chunk| chunk.source_bytes).sum::<u64>(),
|
||||
8
|
||||
);
|
||||
assert_eq!(chunks[0].offset, 5);
|
||||
assert_eq!(chunks.last().unwrap().offset, 13);
|
||||
assert!(chunks.iter().any(|chunk| chunk.truncated));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue