next_swc_napi/next_api/
turbopack_ctx.rs1use std::{path::PathBuf, sync::Arc};
4
5use anyhow::Result;
6use either::Either;
7use serde::Serialize;
8use turbo_tasks::{
9 TurboTasks, TurboTasksApi,
10 message_queue::{CompilationEvent, Severity},
11};
12use turbo_tasks_backend::{
13 BackendOptions, DefaultBackingStorage, GitVersionInfo, NoopBackingStorage, StartupCacheState,
14 TurboTasksBackend, db_invalidation::invalidation_reasons, default_backing_storage,
15 noop_backing_storage,
16};
17
18pub type NextTurboTasks =
19 Arc<TurboTasks<TurboTasksBackend<Either<DefaultBackingStorage, NoopBackingStorage>>>>;
20
21#[derive(Clone)]
28pub struct NextTurbopackContext {
29 inner: Arc<NextTurboContextInner>,
30}
31
32struct NextTurboContextInner {
33 turbo_tasks: NextTurboTasks,
34}
35
36impl NextTurbopackContext {
37 pub fn new(turbo_tasks: NextTurboTasks) -> Self {
38 NextTurbopackContext {
39 inner: Arc::new(NextTurboContextInner { turbo_tasks }),
40 }
41 }
42
43 pub fn turbo_tasks(&self) -> &NextTurboTasks {
44 &self.inner.turbo_tasks
45 }
46}
47
48pub fn create_turbo_tasks(
49 output_path: PathBuf,
50 persistent_caching: bool,
51 _memory_limit: usize,
52 dependency_tracking: bool,
53 is_ci: bool,
54) -> Result<NextTurboTasks> {
55 Ok(if persistent_caching {
56 let version_info = GitVersionInfo {
57 describe: env!("VERGEN_GIT_DESCRIBE"),
58 dirty: option_env!("CI").is_none_or(|value| value.is_empty())
59 && env!("VERGEN_GIT_DIRTY") == "true",
60 };
61 let (backing_storage, cache_state) =
62 default_backing_storage(&output_path.join("cache/turbopack"), &version_info, is_ci)?;
63 let tt = TurboTasks::new(TurboTasksBackend::new(
64 BackendOptions {
65 storage_mode: Some(if std::env::var("TURBO_ENGINE_READ_ONLY").is_ok() {
66 turbo_tasks_backend::StorageMode::ReadOnly
67 } else {
68 turbo_tasks_backend::StorageMode::ReadWrite
69 }),
70 dependency_tracking,
71 ..Default::default()
72 },
73 Either::Left(backing_storage),
74 ));
75 if let StartupCacheState::Invalidated { reason_code } = cache_state {
76 tt.send_compilation_event(Arc::new(StartupCacheInvalidationEvent { reason_code }));
77 }
78 tt
79 } else {
80 TurboTasks::new(TurboTasksBackend::new(
81 BackendOptions {
82 storage_mode: None,
83 dependency_tracking,
84 ..Default::default()
85 },
86 Either::Right(noop_backing_storage()),
87 ))
88 })
89}
90
91#[derive(Serialize)]
92struct StartupCacheInvalidationEvent {
93 reason_code: Option<String>,
94}
95
96impl CompilationEvent for StartupCacheInvalidationEvent {
97 fn type_name(&self) -> &'static str {
98 "StartupCacheInvalidationEvent"
99 }
100
101 fn severity(&self) -> Severity {
102 Severity::Warning
103 }
104
105 fn message(&self) -> String {
106 let reason_msg = match self.reason_code.as_deref() {
107 Some(invalidation_reasons::PANIC) => {
108 " because we previously detected an internal error in Turbopack"
109 }
110 Some(invalidation_reasons::USER_REQUEST) => " as the result of a user request",
111 _ => "", };
113 format!(
114 "Turbopack's persistent cache has been deleted{reason_msg}. Builds or page loads may \
115 be slower as a result."
116 )
117 }
118
119 fn to_json(&self) -> String {
120 serde_json::to_string(self).unwrap()
121 }
122}