好奇Deno存储在/tmp/deno_cache中的内容
大家好,我是无能。
在上一篇文章中,我们发现缓存存储在/tmp/deno_cache中,所以我很好奇它存储了什么,决定看一看。
存储在SQLite中
首先,我们先进入/tmp/deno_cache目录。
cd /tmp/deno_cache
ls
7b52928d182b91e3d058c899022fc32b63d560748054c3143d70a24863f0f2ba
cd 7b52928d182b91e3d058c899022fc32b63d560748054c3143d70a24863f0f2ba
ls -la
合计 120
drwxrwxr-x 3 haturatu haturatu 4096 10月 10 21:58 .
drwxrwxr-x 3 haturatu haturatu 4096 10月 10 21:58 ..
drwxrwxr-x 3 haturatu haturatu 4096 10月 10 21:58 1
-rw-r--r-- 1 haturatu haturatu 4096 10月 10 21:58 cache_metadata.db
-rw-r--r-- 1 haturatu haturatu 32768 10月 10 22:02 cache_metadata.db-shm
-rw-r--r-- 1 haturatu haturatu 70072 10月 10 22:02 cache_metadata.db-wal
看来这种结构是使用SQLite存储的。所以我们来连接一下。
sqlite> .tables
cache_storage request_response_list
sqlite> select * from cache_storage;
1|lume_remote_files
sqlite> select * from request_response_list;
1|1|https://cdn.jsdelivr.net/npm/svg2png-wasm@1.4.1/svg2png_wasm_bg.wasm||access-control-allow-origin
*
access-control-expose-headers
*
timing-allow-origin
*
cache-control
public, max-age=31536000, s-maxage=31536000, immutable
cross-origin-resource-policy
cross-origin
~~省略~~~
max-age=31536000; includeSubDomains; preload
x-content-type-options
nosniff
server
cloudflare
|200|OK|5f1e6f823db55b21ff1e048860bbbce7b104fe57fa3a4449ce36989784625f32|1728565376
sqlite>
那么我们从deno_cache/01_cache.js开始深入探究吧
alleycat:[haturatu]:~/git/deno/ext/cache$ ls -la
合计 60
drwxr-xr-x 2 haturatu haturatu 4096 10月 12 18:16 .
drwxr-xr-x 24 haturatu haturatu 4096 10月 12 18:16 ..
-rw-r--r-- 1 haturatu haturatu 9048 10月 12 18:16 01_cache.js
-rw-r--r-- 1 haturatu haturatu 491 10月 12 18:16 Cargo.toml
-rw-r--r-- 1 haturatu haturatu 1043 10月 12 18:16 README.md
-rw-r--r-- 1 haturatu haturatu 2042 10月 12 18:16 lib.deno_cache.d.ts
-rw-r--r-- 1 haturatu haturatu 9827 10月 12 18:16 lib.rs
-rw-r--r-- 1 haturatu haturatu 12666 10月 12 18:16 sqlite.rs
alleycat:[haturatu]:~/git/deno/ext/cache$ cat Cargo.toml
# Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
[package]
name = "deno_cache"
version = "0.103.0"
authors.workspace = true
edition.workspace = true
license.workspace = true
readme = "README.md"
repository.workspace = true
description = "Implementation of Cache API for Deno"
[lib]
path = "lib.rs"
[dependencies]
async-trait.workspace = true
deno_core.workspace = true
rusqlite.workspace = true
serde.workspace = true
sha2.workspace = true
tokio.workspace = true
alleycat:[haturatu]:~/git/deno/ext/cache$ grep "tmp" ./*
alleycat:[haturatu]:~/git/deno/ext/cache$ grep "deno_cache" ./*
./Cargo.toml:name = "deno_cache"
./README.md:# deno_cache
./lib.rs:deno_core::extension!(deno_cache,
alleycat:[haturatu]:~/git/deno/ext/cache$ cat lib.rs
~~~
deno_core::extension!(deno_cache,
deps = [ deno_webidl, deno_web, deno_url, deno_fetch ],
parameters=[CA: Cache],
ops = [
op_cache_storage_open<CA>,
op_cache_storage_has<CA>,
op_cache_storage_delete<CA>,
op_cache_put<CA>,
op_cache_match<CA>,
op_cache_delete<CA>,
],
esm = [ "01_cache.js" ],
options = {
maybe_create_cache: Option<CreateCache<CA>>,
},
state = |state, options| {
if let Some(create_cache) = options.maybe_create_cache {
state.put(create_cache);
}
},
);
~~~
alleycat:[haturatu]:~/git/deno/ext/cache$ grep " op_cache_storage" ./*
./01_cache.js: op_cache_storage_delete,
./01_cache.js: op_cache_storage_has,
./01_cache.js: op_cache_storage_open,
./01_cache.js: const cacheId = await op_cache_storage_open(cacheName);
./01_cache.js: async has(cacheName) {
./01_cache.js: return await op_cache_storage_has(cacheName);
./01_cache.js: async delete(cacheName) {
./01_cache.js: return await op_cache_storage_delete(cacheName);
./lib.rs: op_cache_storage_open<CA>,
./lib.rs: op_cache_storage_has<CA>,
./lib.rs: op_cache_storage_delete<CA>,
./lib.rs:pub async fn op_cache_storage_open<CA>(
./lib.rs:pub async fn op_cache_storage_has<CA>(
./lib.rs:pub async fn op_cache_storage_delete<CA>(
alleycat:[haturatu]:~/git/deno/ext/cache$ grep "cacheName" ./*
./01_cache.js: async open(cacheName) {
./01_cache.js: cacheName = webidl.converters["DOMString"](cacheName, prefix, "Argument 1");
./01_cache.js: const cacheId = await op_cache_storage_open(cacheName);
./01_cache.js: async has(cacheName) {
./01_cache.js: cacheName = webidl.converters["DOMString"](cacheName, prefix, "Argument 1");
./01_cache.js: return await op_cache_storage_has(cacheName);
./01_cache.js: async delete(cacheName) {
./01_cache.js: cacheName = webidl.converters["DOMString"](cacheName, prefix, "Argument 1");
./01_cache.js: return await op_cache_storage_delete(cacheName);
./lib.deno_cache.d.ts: open(cacheName: string): Promise<Cache>;
./lib.deno_cache.d.ts: has(cacheName: string): Promise<boolean>;
./lib.deno_cache.d.ts: delete(cacheName: string): Promise<boolean>;
我们来看看sqlite.rs。
alleycat:[haturatu]:~/git/deno/ext/cache$ grep "cache_storage_dir" ./*
./sqlite.rs: pub cache_storage_dir: PathBuf,
./sqlite.rs: pub fn new(cache_storage_dir: PathBuf) -> Self {
./sqlite.rs: std::fs::create_dir_all(&cache_storage_dir)
./sqlite.rs: let path = cache_storage_dir.join("cache_metadata.db");
./sqlite.rs: cache_storage_dir,
./sqlite.rs: let cache_storage_dir = self.cache_storage_dir.clone();
./sqlite.rs: let responses_dir = get_responses_dir(cache_storage_dir, cache_id);
./sqlite.rs: let cache_storage_dir = self.cache_storage_dir.clone();
./sqlite.rs: let cache_dir = cache_storage_dir.join(cache_id.to_string());
./sqlite.rs: let cache_storage_dir = self.cache_storage_dir.clone();
./sqlite.rs: get_responses_dir(cache_storage_dir, request_response.cache_id);
./sqlite.rs: let cache_storage_dir = self.cache_storage_dir.clone();
./sqlite.rs: get_responses_dir(cache_storage_dir, request.cache_id)
./sqlite.rs:fn get_responses_dir(cache_storage_dir: PathBuf, cache_id: i64) -> PathBuf {
./sqlite.rs: cache_storage_dir
alleycat:[haturatu]:~/git/deno/ext/cache$ head -5 sqlite.rs
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use std::borrow::Cow;
use std::path::PathBuf;
use std::pin::Pin;
use std::rc::Rc;
alleycat:[haturatu]:~/git/deno$ grep "PathBuf" ./*/* 2>/dev/null | grep -v use
./cli/build.rs: let op_crate_libs = state.borrow::<HashMap<&str, PathBuf>>();
./cli/build.rs: let path_dts = state.borrow::<PathBuf>();
./cli/build.rs: PathBuf::from(op_crate_lib).canonicalize()?
./cli/build.rs: op_crate_libs: HashMap<&'static str, PathBuf>,
./cli/build.rs: path_dts: PathBuf,
./cli/build.rs: pub fn create_compiler_snapshot(snapshot_path: PathBuf, cwd: &Path) {
./cli/build.rs: PathBuf::from(env::var_os("OUT_DIR").unwrap())
~~~
alleycat:[haturatu]:~/git/deno$ cd ./ext/cache/
alleycat:[haturatu]:~/git/deno/ext/cache$ grep let ./* | grep dir
./sqlite.rs: let path = cache_storage_dir.join("cache_metadata.db");
./sqlite.rs: let cache_storage_dir = self.cache_storage_dir.clone();
./sqlite.rs: let responses_dir = get_responses_dir(cache_storage_dir, cache_id);
./sqlite.rs: let cache_storage_dir = self.cache_storage_dir.clone();
./sqlite.rs: let cache_dir = cache_storage_dir.join(cache_id.to_string());
./sqlite.rs: let cache_storage_dir = self.cache_storage_dir.clone();
./sqlite.rs: let responses_dir =
./sqlite.rs: let response_path = responses_dir.join(&body_key);
./sqlite.rs: let cache_storage_dir = self.cache_storage_dir.clone();
alleycat:[haturatu]:~/git/deno/ext/cache$ vim ./sqlite.rs
alleycat:[haturatu]:~/git/deno/ext/cache$ cat ./sqlite.rs
~~~
use std::path::PathBuf;
~~~
#[derive(Clone)]
pub struct SqliteBackedCache {
pub connection: Arc<Mutex<Connection>>,
pub cache_storage_dir: PathBuf,
}
~~~
PathBuf
alleycat:[haturatu]:~/git/deno/ext/cache$ cd -
alleycat:[haturatu]:~/git/deno$ grep "let mut" ./*/*/* | grep "PathBuf"
grep: ./cli/bench/fs: 是目录
grep: ./cli/bench/http: 是目录
grep: ./cli/bench/napi: 是目录
grep: ./cli/bench/stdio: 是目录
grep: ./cli/bench/testdata: 是目录
./cli/cache/disk_cache.rs: let mut out = PathBuf::new();
哦!
alleycat:[haturatu]:~/git/deno/cli/cache$ ls -la
合计 136
drwxr-xr-x 2 haturatu haturatu 4096 10月 12 18:16 .
drwxr-xr-x 15 haturatu haturatu 4096 10月 12 18:16 ..
-rw-r--r-- 1 haturatu haturatu 17292 10月 12 18:16 cache_db.rs
-rw-r--r-- 1 haturatu haturatu 3643 10月 12 18:16 caches.rs
-rw-r--r-- 1 haturatu haturatu 5190 10月 12 18:16 check.rs
-rw-r--r-- 1 haturatu haturatu 5668 10月 12 18:16 code_cache.rs
-rw-r--r-- 1 haturatu haturatu 1090 10月 12 18:16 common.rs
-rw-r--r-- 1 haturatu haturatu 8449 10月 12 18:16 deno_dir.rs
-rw-r--r-- 1 haturatu haturatu 7647 10月 12 18:16 disk_cache.rs
-rw-r--r-- 1 haturatu haturatu 7195 10月 12 18:16 emit.rs
-rw-r--r-- 1 haturatu haturatu 4531 10月 12 18:16 fast_check.rs
-rw-r--r-- 1 haturatu haturatu 8367 10月 12 18:16 incremental.rs
-rw-r--r-- 1 haturatu haturatu 12142 10月 12 18:16 mod.rs
-rw-r--r-- 1 haturatu haturatu 7796 10月 12 18:16 module_info.rs
-rw-r--r-- 1 haturatu haturatu 4847 10月 12 18:16 node.rs
-rw-r--r-- 1 haturatu haturatu 4567 10月 12 18:16 parsed_source.rs
alleycat:[haturatu]:~/git/deno/cli/cache$ vim disk_cache.rs
~~~
impl DiskCache {
/// `location` must be an absolute path.
pub fn new(location: &Path) -> Self {
assert!(location.is_absolute());
Self {
location: location.to_owned(),
}
}
fn get_cache_filename(&self, url: &Url) -> Option<PathBuf> {
let mut out = PathBuf::new();
~~~
alleycat:[haturatu]:~/git/deno/cli/cache$ grep "get_cache_filename" ./* | grep "let"
./disk_cache.rs: let base = self.get_cache_filename(url)?;
我大致了解了调用发生在哪里。
顺便说一下,上次发生的错误可能不是一个bug,而是在改变所有权时的一种罕见情况,例如:
which deno
/home/haturatu/.deno/bin/deno
在这种情况下,deno的执行用户是haturatu。
如果特意以另一个用户的权限执行它,生成的/tmp/deno_cache就会与其他用户发生冲突。
不应该在多个用户之间执行deno命令(除非是必要的情况),我认为这是合理的。
如果严格执行,最好是创建一个专门的deno用户,并用该用户安装和执行。
但如果说有什么让我好奇的话
那就是执行deno info时,/tmp/deno_cache没有被输出。
alleycat:[haturatu]:~/git/deno/ext/cache$ deno info
DENO_DIR location: /home/haturatu/.cache/deno
Remote modules cache: /home/haturatu/.cache/deno/deps
npm modules cache: /home/haturatu/.cache/deno/npm
Emitted modules cache: /home/haturatu/.cache/deno/gen
Language server registries cache: /home/haturatu/.cache/deno/registries
Origin storage: /home/haturatu/.cache/deno/location_data
只是有点好奇,所以随便记一下。
那么。
下次再见。