diff options
Diffstat (limited to 'cli/cache/check.rs')
-rw-r--r-- | cli/cache/check.rs | 176 |
1 files changed, 47 insertions, 129 deletions
diff --git a/cli/cache/check.rs b/cli/cache/check.rs index 1bd410013..bf71380cb 100644 --- a/cli/cache/check.rs +++ b/cli/cache/check.rs @@ -1,68 +1,40 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -use std::path::Path; - +use super::cache_db::CacheDB; +use super::cache_db::CacheDBConfiguration; +use super::cache_db::CacheFailure; use deno_ast::ModuleSpecifier; use deno_core::error::AnyError; use deno_runtime::deno_webstorage::rusqlite::params; -use deno_runtime::deno_webstorage::rusqlite::Connection; -use super::common::INITIAL_PRAGMAS; +pub static TYPE_CHECK_CACHE_DB: CacheDBConfiguration = CacheDBConfiguration { + table_initializer: concat!( + "CREATE TABLE IF NOT EXISTS checkcache ( + check_hash TEXT PRIMARY KEY + );", + "CREATE TABLE IF NOT EXISTS tsbuildinfo ( + specifier TEXT PRIMARY KEY, + text TEXT NOT NULL + );", + ), + on_version_change: concat!( + "DELETE FROM checkcache;", + "DELETE FROM tsbuildinfo;" + ), + preheat_queries: &[], + // If the cache fails, just ignore all caching attempts + on_failure: CacheFailure::Blackhole, +}; /// The cache used to tell whether type checking should occur again. /// /// This simply stores a hash of the inputs of each successful type check /// and only clears them out when changing CLI versions. -pub struct TypeCheckCache(Option<Connection>); +pub struct TypeCheckCache(CacheDB); impl TypeCheckCache { - pub fn new(db_file_path: &Path) -> Self { - log::debug!("Loading type check cache."); - match Self::try_new(db_file_path) { - Ok(cache) => cache, - Err(err) => { - log::debug!( - concat!( - "Failed loading internal type checking cache. ", - "Recreating...\n\nError details:\n{:#}", - ), - err - ); - // Maybe the cache file is corrupt. Attempt to remove the cache file - // then attempt to recreate again. Otherwise, use null object pattern. - match std::fs::remove_file(db_file_path) { - Ok(_) => match Self::try_new(db_file_path) { - Ok(cache) => cache, - Err(err) => { - log::debug!( - concat!( - "Unable to load internal cache for type checking. ", - "This will reduce the performance of type checking.\n\n", - "Error details:\n{:#}", - ), - err - ); - Self(None) - } - }, - Err(_) => Self(None), - } - } - } - } - - fn try_new(db_file_path: &Path) -> Result<Self, AnyError> { - let conn = Connection::open(db_file_path)?; - Self::from_connection(conn, crate::version::deno()) - } - - fn from_connection( - conn: Connection, - cli_version: &'static str, - ) -> Result<Self, AnyError> { - initialize(&conn, cli_version)?; - - Ok(Self(Some(conn))) + pub fn new(db: CacheDB) -> Self { + Self(db) } pub fn has_check_hash(&self, hash: u64) -> bool { @@ -81,13 +53,10 @@ impl TypeCheckCache { } fn hash_check_hash_result(&self, hash: u64) -> Result<bool, AnyError> { - let conn = match &self.0 { - Some(conn) => conn, - None => return Ok(false), - }; - let query = "SELECT * FROM checkcache WHERE check_hash=?1 LIMIT 1"; - let mut stmt = conn.prepare_cached(query)?; - Ok(stmt.exists(params![hash.to_string()])?) + self.0.exists( + "SELECT * FROM checkcache WHERE check_hash=?1 LIMIT 1", + params![hash.to_string()], + ) } pub fn add_check_hash(&self, check_hash: u64) { @@ -101,32 +70,24 @@ impl TypeCheckCache { } fn add_check_hash_result(&self, check_hash: u64) -> Result<(), AnyError> { - let conn = match &self.0 { - Some(conn) => conn, - None => return Ok(()), - }; let sql = " INSERT OR REPLACE INTO checkcache (check_hash) VALUES (?1)"; - let mut stmt = conn.prepare_cached(sql)?; - stmt.execute(params![&check_hash.to_string(),])?; + self.0.execute(sql, params![&check_hash.to_string(),])?; Ok(()) } pub fn get_tsbuildinfo(&self, specifier: &ModuleSpecifier) -> Option<String> { - let conn = match &self.0 { - Some(conn) => conn, - None => return None, - }; - let mut stmt = conn - .prepare_cached("SELECT text FROM tsbuildinfo WHERE specifier=?1 LIMIT 1") - .ok()?; - let mut rows = stmt.query(params![specifier.to_string()]).ok()?; - let row = rows.next().ok().flatten()?; - - row.get(0).ok() + self + .0 + .query_row( + "SELECT text FROM tsbuildinfo WHERE specifier=?1 LIMIT 1", + params![specifier.to_string()], + |row| Ok(row.get::<_, String>(0)?), + ) + .ok()? } pub fn set_tsbuildinfo(&self, specifier: &ModuleSpecifier, text: &str) { @@ -145,67 +106,22 @@ impl TypeCheckCache { specifier: &ModuleSpecifier, text: &str, ) -> Result<(), AnyError> { - let conn = match &self.0 { - Some(conn) => conn, - None => return Ok(()), - }; - let mut stmt = conn.prepare_cached( + self.0.execute( "INSERT OR REPLACE INTO tsbuildinfo (specifier, text) VALUES (?1, ?2)", + params![specifier.to_string(), text], )?; - stmt.execute(params![specifier.to_string(), text])?; Ok(()) } } -fn initialize( - conn: &Connection, - cli_version: &'static str, -) -> Result<(), AnyError> { - // INT doesn't store up to u64, so use TEXT for check_hash - let query = format!( - "{INITIAL_PRAGMAS} - CREATE TABLE IF NOT EXISTS checkcache ( - check_hash TEXT PRIMARY KEY - ); - CREATE TABLE IF NOT EXISTS tsbuildinfo ( - specifier TEXT PRIMARY KEY, - text TEXT NOT NULL - ); - CREATE TABLE IF NOT EXISTS info ( - key TEXT PRIMARY KEY, - value TEXT NOT NULL - ); - ", - ); - conn.execute_batch(&query)?; - - // delete the cache when the CLI version changes - let data_cli_version: Option<String> = conn - .query_row( - "SELECT value FROM info WHERE key='CLI_VERSION' LIMIT 1", - [], - |row| row.get(0), - ) - .ok(); - if data_cli_version.as_deref() != Some(cli_version) { - conn.execute("DELETE FROM checkcache", params![])?; - conn.execute("DELETE FROM tsbuildinfo", params![])?; - let mut stmt = conn - .prepare("INSERT OR REPLACE INTO info (key, value) VALUES (?1, ?2)")?; - stmt.execute(params!["CLI_VERSION", cli_version])?; - } - - Ok(()) -} - #[cfg(test)] mod test { use super::*; #[test] pub fn check_cache_general_use() { - let conn = Connection::open_in_memory().unwrap(); - let cache = TypeCheckCache::from_connection(conn, "1.0.0").unwrap(); + let conn = CacheDB::in_memory(&TYPE_CHECK_CACHE_DB, "1.0.0"); + let cache = TypeCheckCache::new(conn); assert!(!cache.has_check_hash(1)); cache.add_check_hash(1); @@ -218,8 +134,9 @@ mod test { assert_eq!(cache.get_tsbuildinfo(&specifier1), Some("test".to_string())); // try changing the cli version (should clear) - let conn = cache.0.unwrap(); - let cache = TypeCheckCache::from_connection(conn, "2.0.0").unwrap(); + let conn = cache.0.recreate_with_version("2.0.0"); + let cache = TypeCheckCache::new(conn); + assert!(!cache.has_check_hash(1)); cache.add_check_hash(1); assert!(cache.has_check_hash(1)); @@ -228,8 +145,9 @@ mod test { assert_eq!(cache.get_tsbuildinfo(&specifier1), Some("test".to_string())); // recreating the cache should not remove the data because the CLI version is the same - let conn = cache.0.unwrap(); - let cache = TypeCheckCache::from_connection(conn, "2.0.0").unwrap(); + let conn = cache.0.recreate_with_version("2.0.0"); + let cache = TypeCheckCache::new(conn); + assert!(cache.has_check_hash(1)); assert!(!cache.has_check_hash(2)); assert_eq!(cache.get_tsbuildinfo(&specifier1), Some("test".to_string())); |