Skip to content

Commit 5970f7e

Browse files
authored
Merge pull request #971 from rust-lang/push-laziness-down
2 parents 7145c2f + 541c59d commit 5970f7e

File tree

4 files changed

+114
-96
lines changed

4 files changed

+114
-96
lines changed

compiler/base/orchestrator/src/coordinator.rs

Lines changed: 82 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use futures::{future::BoxFuture, Future, FutureExt};
1+
use futures::{
2+
future::{BoxFuture, OptionFuture},
3+
Future, FutureExt,
4+
};
25
use snafu::prelude::*;
36
use std::{
47
collections::HashMap,
@@ -14,7 +17,7 @@ use tokio::{
1417
join,
1518
process::{Child, ChildStdin, ChildStdout, Command},
1619
select,
17-
sync::{mpsc, oneshot},
20+
sync::{mpsc, oneshot, OnceCell},
1821
task::{JoinHandle, JoinSet},
1922
time::{self, MissedTickBehavior},
2023
};
@@ -67,8 +70,6 @@ pub enum Channel {
6770
}
6871

6972
impl Channel {
70-
pub(crate) const ALL: [Self; 3] = [Self::Stable, Self::Beta, Self::Nightly];
71-
7273
#[cfg(test)]
7374
pub(crate) fn to_str(self) -> &'static str {
7475
match self {
@@ -401,49 +402,50 @@ enum DemultiplexCommand {
401402
pub struct Coordinator<B> {
402403
backend: B,
403404
// Consider making these lazily-created and/or idly time out
404-
stable: Container,
405-
beta: Container,
406-
nightly: Container,
405+
stable: OnceCell<Container>,
406+
beta: OnceCell<Container>,
407+
nightly: OnceCell<Container>,
407408
token: CancellationToken,
408409
}
409410

410411
impl<B> Coordinator<B>
411412
where
412413
B: Backend,
413414
{
414-
pub async fn new(backend: B) -> Result<Self, Error> {
415+
pub async fn new(backend: B) -> Self {
415416
let token = CancellationToken::new();
416417

417-
let [stable, beta, nightly] =
418-
Channel::ALL.map(|channel| Container::new(channel, token.clone(), &backend));
419-
420-
let (stable, beta, nightly) = join!(stable, beta, nightly);
421-
422-
let stable = stable?;
423-
let beta = beta?;
424-
let nightly = nightly?;
425-
426-
Ok(Self {
418+
Self {
427419
backend,
428-
stable,
429-
beta,
430-
nightly,
420+
stable: OnceCell::new(),
421+
beta: OnceCell::new(),
422+
nightly: OnceCell::new(),
431423
token,
432-
})
424+
}
433425
}
434426

435427
pub async fn execute(
436428
&self,
437429
request: ExecuteRequest,
438430
) -> Result<WithOutput<ExecuteResponse>, ExecuteError> {
439-
self.select_channel(request.channel).execute(request).await
431+
use execute_error::*;
432+
433+
self.select_channel(request.channel)
434+
.await
435+
.context(CouldNotStartContainerSnafu)?
436+
.execute(request)
437+
.await
440438
}
441439

442440
pub async fn begin_execute(
443441
&self,
444442
request: ExecuteRequest,
445443
) -> Result<ActiveExecution, ExecuteError> {
444+
use execute_error::*;
445+
446446
self.select_channel(request.channel)
447+
.await
448+
.context(CouldNotStartContainerSnafu)?
447449
.begin_execute(request)
448450
.await
449451
}
@@ -452,48 +454,72 @@ where
452454
&self,
453455
request: CompileRequest,
454456
) -> Result<WithOutput<CompileResponse>, CompileError> {
455-
self.select_channel(request.channel).compile(request).await
457+
use compile_error::*;
458+
459+
self.select_channel(request.channel)
460+
.await
461+
.context(CouldNotStartContainerSnafu)?
462+
.compile(request)
463+
.await
456464
}
457465

458466
pub async fn begin_compile(
459467
&self,
460468
request: CompileRequest,
461469
) -> Result<ActiveCompilation, CompileError> {
470+
use compile_error::*;
471+
462472
self.select_channel(request.channel)
473+
.await
474+
.context(CouldNotStartContainerSnafu)?
463475
.begin_compile(request)
464476
.await
465477
}
466478

467-
pub async fn shutdown(self) -> Result<B> {
479+
pub async fn idle(&mut self) -> Result<()> {
468480
let Self {
469-
backend,
470481
stable,
471482
beta,
472483
nightly,
473484
token,
485+
..
474486
} = self;
475487
token.cancel();
476488

477-
let (stable, beta, nightly) = join!(stable.shutdown(), beta.shutdown(), nightly.shutdown());
489+
let channels =
490+
[stable, beta, nightly].map(|c| OptionFuture::from(c.take().map(|c| c.shutdown())));
491+
492+
let [stable, beta, nightly] = channels;
493+
494+
let (stable, beta, nightly) = join!(stable, beta, nightly);
478495

479-
stable?;
480-
beta?;
481-
nightly?;
496+
stable.transpose()?;
497+
beta.transpose()?;
498+
nightly.transpose()?;
482499

483-
Ok(backend)
500+
Ok(())
484501
}
485502

486-
fn select_channel(&self, channel: Channel) -> &Container {
487-
match channel {
503+
pub async fn shutdown(mut self) -> Result<B> {
504+
self.idle().await?;
505+
Ok(self.backend)
506+
}
507+
508+
async fn select_channel(&self, channel: Channel) -> Result<&Container, Error> {
509+
let container = match channel {
488510
Channel::Stable => &self.stable,
489511
Channel::Beta => &self.beta,
490512
Channel::Nightly => &self.nightly,
491-
}
513+
};
514+
515+
container
516+
.get_or_try_init(|| Container::new(channel, self.token.clone(), &self.backend))
517+
.await
492518
}
493519
}
494520

495521
impl Coordinator<DockerBackend> {
496-
pub async fn new_docker() -> Result<Self, Error> {
522+
pub async fn new_docker() -> Self {
497523
Self::new(DockerBackend(())).await
498524
}
499525
}
@@ -771,6 +797,9 @@ impl fmt::Debug for ActiveExecution {
771797
#[derive(Debug, Snafu)]
772798
#[snafu(module)]
773799
pub enum ExecuteError {
800+
#[snafu(display("Could not start the container"))]
801+
CouldNotStartContainer { source: Error },
802+
774803
#[snafu(display("Could not modify Cargo.toml"))]
775804
CouldNotModifyCargoToml { source: ModifyCargoTomlError },
776805

@@ -809,6 +838,9 @@ impl fmt::Debug for ActiveCompilation {
809838
#[derive(Debug, Snafu)]
810839
#[snafu(module)]
811840
pub enum CompileError {
841+
#[snafu(display("Could not start the container"))]
842+
CouldNotStartContainer { source: Error },
843+
812844
#[snafu(display("Could not modify Cargo.toml"))]
813845
CouldNotModifyCargoToml { source: ModifyCargoTomlError },
814846

@@ -1376,7 +1408,7 @@ mod tests {
13761408
}
13771409
}
13781410

1379-
async fn new_coordinator() -> Result<Coordinator<impl Backend>> {
1411+
async fn new_coordinator() -> Coordinator<impl Backend> {
13801412
Coordinator::new(TestBackend::new()).await
13811413
//Coordinator::new_docker().await
13821414
}
@@ -1396,7 +1428,7 @@ mod tests {
13961428
#[tokio::test]
13971429
#[snafu::report]
13981430
async fn test_execute_response() -> Result<()> {
1399-
let coordinator = new_coordinator().await?;
1431+
let coordinator = new_coordinator().await;
14001432

14011433
let response = coordinator
14021434
.execute(new_execute_request())
@@ -1424,7 +1456,7 @@ mod tests {
14241456
];
14251457

14261458
let tests = params.into_iter().map(|(mode, expected)| async move {
1427-
let coordinator = new_coordinator().await?;
1459+
let coordinator = new_coordinator().await;
14281460

14291461
let request = ExecuteRequest {
14301462
mode,
@@ -1456,7 +1488,7 @@ mod tests {
14561488
let tests = params.into_iter().flat_map(|(code, works_in)| {
14571489
Edition::ALL.into_iter().zip(works_in).map(
14581490
move |(edition, expected_to_work)| async move {
1459-
let coordinator = new_coordinator().await?;
1491+
let coordinator = new_coordinator().await;
14601492

14611493
let request = ExecuteRequest {
14621494
code: code.into(),
@@ -1496,7 +1528,7 @@ mod tests {
14961528
];
14971529

14981530
let tests = params.into_iter().map(|(crate_type, expected)| async move {
1499-
let coordinator = new_coordinator().await?;
1531+
let coordinator = new_coordinator().await;
15001532

15011533
let request = ExecuteRequest {
15021534
crate_type,
@@ -1529,7 +1561,7 @@ mod tests {
15291561
let params = [(false, "Running `"), (true, "Running unittests")];
15301562

15311563
let tests = params.into_iter().map(|(tests, expected)| async move {
1532-
let coordinator = new_coordinator().await?;
1564+
let coordinator = new_coordinator().await;
15331565

15341566
let request = ExecuteRequest {
15351567
code: code.into(),
@@ -1562,7 +1594,7 @@ mod tests {
15621594
];
15631595

15641596
let tests = params.into_iter().map(|(backtrace, expected)| async move {
1565-
let coordinator = new_coordinator().await?;
1597+
let coordinator = new_coordinator().await;
15661598

15671599
let request = ExecuteRequest {
15681600
code: code.into(),
@@ -1668,7 +1700,7 @@ mod tests {
16681700
#[tokio::test]
16691701
#[snafu::report]
16701702
async fn test_compile_response() -> Result<()> {
1671-
let coordinator = new_coordinator().await?;
1703+
let coordinator = new_coordinator().await;
16721704

16731705
let response = coordinator
16741706
.compile(new_compile_request())
@@ -1688,7 +1720,7 @@ mod tests {
16881720
#[tokio::test]
16891721
#[snafu::report]
16901722
async fn test_compile_streaming() -> Result<()> {
1691-
let coordinator = new_coordinator().await?;
1723+
let coordinator = new_coordinator().await;
16921724

16931725
let ActiveCompilation {
16941726
task,
@@ -1723,7 +1755,7 @@ mod tests {
17231755
#[snafu::report]
17241756
async fn test_compile_edition() -> Result<()> {
17251757
for edition in Edition::ALL {
1726-
let coordinator = new_coordinator().await?;
1758+
let coordinator = new_coordinator().await;
17271759

17281760
let response = coordinator
17291761
.compile(new_compile_hir_request_for(edition))
@@ -1745,7 +1777,7 @@ mod tests {
17451777
#[tokio::test]
17461778
#[snafu::report]
17471779
async fn test_compile_assembly() -> Result<()> {
1748-
let coordinator = new_coordinator().await?;
1780+
let coordinator = new_coordinator().await;
17491781

17501782
let response = coordinator
17511783
.compile(new_compile_assembly_request())
@@ -1770,7 +1802,7 @@ mod tests {
17701802
#[tokio::test]
17711803
#[snafu::report]
17721804
async fn test_compile_hir() -> Result<()> {
1773-
let coordinator = new_coordinator().await?;
1805+
let coordinator = new_coordinator().await;
17741806

17751807
let response = coordinator
17761808
.compile(new_compile_hir_request())
@@ -1789,7 +1821,7 @@ mod tests {
17891821
#[tokio::test]
17901822
#[snafu::report]
17911823
async fn test_compile_llvm_ir() -> Result<()> {
1792-
let coordinator = new_coordinator().await?;
1824+
let coordinator = new_coordinator().await;
17931825

17941826
let response = coordinator
17951827
.compile(new_compile_llvm_ir_request())
@@ -1809,7 +1841,7 @@ mod tests {
18091841
#[snafu::report]
18101842
async fn test_compile_wasm() -> Result<()> {
18111843
// cargo-wasm only exists inside the container
1812-
let coordinator = Coordinator::new_docker().await?;
1844+
let coordinator = Coordinator::new_docker().await;
18131845

18141846
let response = coordinator
18151847
.compile(new_compile_wasm_request())
@@ -1831,7 +1863,7 @@ mod tests {
18311863
#[tokio::test]
18321864
#[snafu::report]
18331865
async fn test_compile_clears_old_main_rs() -> Result<()> {
1834-
let coordinator = new_coordinator().await?;
1866+
let coordinator = new_coordinator().await;
18351867

18361868
// Create a main.rs file
18371869
let req = ExecuteRequest {

ui/src/main.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,6 @@ enum Error {
249249
#[snafu(display("The WebSocket worker panicked: {}", text))]
250250
WebSocketTaskPanic { text: String },
251251

252-
#[snafu(display("Unable to create the coordinator"))]
253-
CreateCoordinator {
254-
source: orchestrator::coordinator::Error,
255-
},
256-
257252
#[snafu(display("Unable to shutdown the coordinator"))]
258253
ShutdownCoordinator {
259254
source: orchestrator::coordinator::Error,

ui/src/server_axum.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ use crate::{
77
},
88
sandbox::{self, Channel, Sandbox, DOCKER_PROCESS_TIMEOUT_SOFT},
99
CachingSnafu, ClippyRequest, ClippyResponse, CompilationSnafu, CompileRequest, CompileResponse,
10-
CompileSnafu, Config, CreateCoordinatorSnafu, Error, ErrorJson, EvaluateRequest,
11-
EvaluateResponse, EvaluateSnafu, EvaluationSnafu, ExecuteRequest, ExecuteResponse,
12-
ExecuteSnafu, ExecutionSnafu, ExpansionSnafu, FormatRequest, FormatResponse, FormattingSnafu,
13-
GhToken, GistCreationSnafu, GistLoadingSnafu, InterpretingSnafu, LintingSnafu,
14-
MacroExpansionRequest, MacroExpansionResponse, MetaCratesResponse, MetaGistCreateRequest,
15-
MetaGistResponse, MetaVersionResponse, MetricsToken, MiriRequest, MiriResponse, Result,
16-
SandboxCreationSnafu, ShutdownCoordinatorSnafu, TimeoutSnafu,
10+
CompileSnafu, Config, Error, ErrorJson, EvaluateRequest, EvaluateResponse, EvaluateSnafu,
11+
EvaluationSnafu, ExecuteRequest, ExecuteResponse, ExecuteSnafu, ExecutionSnafu, ExpansionSnafu,
12+
FormatRequest, FormatResponse, FormattingSnafu, GhToken, GistCreationSnafu, GistLoadingSnafu,
13+
InterpretingSnafu, LintingSnafu, MacroExpansionRequest, MacroExpansionResponse,
14+
MetaCratesResponse, MetaGistCreateRequest, MetaGistResponse, MetaVersionResponse, MetricsToken,
15+
MiriRequest, MiriResponse, Result, SandboxCreationSnafu, ShutdownCoordinatorSnafu,
16+
TimeoutSnafu,
1717
};
1818
use async_trait::async_trait;
1919
use axum::{
@@ -331,9 +331,7 @@ where
331331
for<'f> F:
332332
FnOnce(&'f coordinator::Coordinator<DockerBackend>, Req) -> BoxFuture<'f, Result<Resp>>,
333333
{
334-
let coordinator = orchestrator::coordinator::Coordinator::new_docker()
335-
.await
336-
.context(CreateCoordinatorSnafu)?;
334+
let coordinator = orchestrator::coordinator::Coordinator::new_docker().await;
337335

338336
let job = async {
339337
let req = req.try_into()?;

0 commit comments

Comments
 (0)