mirror of
https://github.com/denoland/deno.git
synced 2025-09-26 20:29:11 +00:00
refactor(ext/cache): Remove custom shutdown and use fast async ops (#20107)
The original implementation of `Cache` used a custom `shutdown` method on the resource, but to simplify fast streams work we're going to move this to an op of its own. While we're in here, we're going to replace `opAsync` with `ensureFastOps`. `op2` work will have to wait because of some limitations to our async support, however.
This commit is contained in:
parent
ddfcf1add4
commit
2ed85c7dd6
3 changed files with 68 additions and 31 deletions
28
ext/cache/01_cache.js
vendored
28
ext/cache/01_cache.js
vendored
|
@ -1,5 +1,5 @@
|
||||||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
// deno-lint-ignore-file camelcase
|
||||||
const core = globalThis.Deno.core;
|
const core = globalThis.Deno.core;
|
||||||
import * as webidl from "ext:deno_webidl/00_webidl.js";
|
import * as webidl from "ext:deno_webidl/00_webidl.js";
|
||||||
const primordials = globalThis.__bootstrap.primordials;
|
const primordials = globalThis.__bootstrap.primordials;
|
||||||
|
@ -20,7 +20,15 @@ import { toInnerResponse } from "ext:deno_fetch/23_response.js";
|
||||||
import { URLPrototype } from "ext:deno_url/00_url.js";
|
import { URLPrototype } from "ext:deno_url/00_url.js";
|
||||||
import { getHeader } from "ext:deno_fetch/20_headers.js";
|
import { getHeader } from "ext:deno_fetch/20_headers.js";
|
||||||
import { readableStreamForRid } from "ext:deno_web/06_streams.js";
|
import { readableStreamForRid } from "ext:deno_web/06_streams.js";
|
||||||
|
const {
|
||||||
|
op_cache_delete,
|
||||||
|
op_cache_match,
|
||||||
|
op_cache_put,
|
||||||
|
op_cache_put_finish,
|
||||||
|
op_cache_storage_delete,
|
||||||
|
op_cache_storage_has,
|
||||||
|
op_cache_storage_open,
|
||||||
|
} = core.ensureFastOps();
|
||||||
class CacheStorage {
|
class CacheStorage {
|
||||||
constructor() {
|
constructor() {
|
||||||
webidl.illegalConstructor();
|
webidl.illegalConstructor();
|
||||||
|
@ -31,7 +39,7 @@ class CacheStorage {
|
||||||
const prefix = "Failed to execute 'open' on 'CacheStorage'";
|
const prefix = "Failed to execute 'open' on 'CacheStorage'";
|
||||||
webidl.requiredArguments(arguments.length, 1, prefix);
|
webidl.requiredArguments(arguments.length, 1, prefix);
|
||||||
cacheName = webidl.converters["DOMString"](cacheName, prefix, "Argument 1");
|
cacheName = webidl.converters["DOMString"](cacheName, prefix, "Argument 1");
|
||||||
const cacheId = await core.opAsync("op_cache_storage_open", cacheName);
|
const cacheId = await op_cache_storage_open(cacheName);
|
||||||
const cache = webidl.createBranded(Cache);
|
const cache = webidl.createBranded(Cache);
|
||||||
cache[_id] = cacheId;
|
cache[_id] = cacheId;
|
||||||
return cache;
|
return cache;
|
||||||
|
@ -42,7 +50,7 @@ class CacheStorage {
|
||||||
const prefix = "Failed to execute 'has' on 'CacheStorage'";
|
const prefix = "Failed to execute 'has' on 'CacheStorage'";
|
||||||
webidl.requiredArguments(arguments.length, 1, prefix);
|
webidl.requiredArguments(arguments.length, 1, prefix);
|
||||||
cacheName = webidl.converters["DOMString"](cacheName, prefix, "Argument 1");
|
cacheName = webidl.converters["DOMString"](cacheName, prefix, "Argument 1");
|
||||||
return await core.opAsync("op_cache_storage_has", cacheName);
|
return await op_cache_storage_has(cacheName);
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(cacheName) {
|
async delete(cacheName) {
|
||||||
|
@ -50,7 +58,7 @@ class CacheStorage {
|
||||||
const prefix = "Failed to execute 'delete' on 'CacheStorage'";
|
const prefix = "Failed to execute 'delete' on 'CacheStorage'";
|
||||||
webidl.requiredArguments(arguments.length, 1, prefix);
|
webidl.requiredArguments(arguments.length, 1, prefix);
|
||||||
cacheName = webidl.converters["DOMString"](cacheName, prefix, "Argument 1");
|
cacheName = webidl.converters["DOMString"](cacheName, prefix, "Argument 1");
|
||||||
return await core.opAsync("op_cache_storage_delete", cacheName);
|
return await op_cache_storage_delete(cacheName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,8 +132,7 @@ class Cache {
|
||||||
reqUrl.hash = "";
|
reqUrl.hash = "";
|
||||||
|
|
||||||
// Step 9-11.
|
// Step 9-11.
|
||||||
const rid = await core.opAsync(
|
const rid = await op_cache_put(
|
||||||
"op_cache_put",
|
|
||||||
{
|
{
|
||||||
cacheId: this[_id],
|
cacheId: this[_id],
|
||||||
// deno-lint-ignore prefer-primordials
|
// deno-lint-ignore prefer-primordials
|
||||||
|
@ -142,7 +149,7 @@ class Cache {
|
||||||
while (true) {
|
while (true) {
|
||||||
const { value, done } = await reader.read();
|
const { value, done } = await reader.read();
|
||||||
if (done) {
|
if (done) {
|
||||||
await core.shutdown(rid);
|
await op_cache_put_finish(rid);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
await core.writeAll(rid, value);
|
await core.writeAll(rid, value);
|
||||||
|
@ -196,7 +203,7 @@ class Cache {
|
||||||
) {
|
) {
|
||||||
r = new Request(request);
|
r = new Request(request);
|
||||||
}
|
}
|
||||||
return await core.opAsync("op_cache_delete", {
|
return await op_cache_delete({
|
||||||
cacheId: this[_id],
|
cacheId: this[_id],
|
||||||
requestUrl: r.url,
|
requestUrl: r.url,
|
||||||
});
|
});
|
||||||
|
@ -240,8 +247,7 @@ class Cache {
|
||||||
const url = new URL(r.url);
|
const url = new URL(r.url);
|
||||||
url.hash = "";
|
url.hash = "";
|
||||||
const innerRequest = toInnerRequest(r);
|
const innerRequest = toInnerRequest(r);
|
||||||
const matchResult = await core.opAsync(
|
const matchResult = await op_cache_match(
|
||||||
"op_cache_match",
|
|
||||||
{
|
{
|
||||||
cacheId: this[_id],
|
cacheId: this[_id],
|
||||||
// deno-lint-ignore prefer-primordials
|
// deno-lint-ignore prefer-primordials
|
||||||
|
|
50
ext/cache/lib.rs
vendored
50
ext/cache/lib.rs
vendored
|
@ -14,6 +14,7 @@ use deno_core::ByteString;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_core::Resource;
|
use deno_core::Resource;
|
||||||
use deno_core::ResourceId;
|
use deno_core::ResourceId;
|
||||||
|
|
||||||
mod sqlite;
|
mod sqlite;
|
||||||
pub use sqlite::SqliteBackedCache;
|
pub use sqlite::SqliteBackedCache;
|
||||||
|
|
||||||
|
@ -28,6 +29,7 @@ deno_core::extension!(deno_cache,
|
||||||
op_cache_storage_has<CA>,
|
op_cache_storage_has<CA>,
|
||||||
op_cache_storage_delete<CA>,
|
op_cache_storage_delete<CA>,
|
||||||
op_cache_put<CA>,
|
op_cache_put<CA>,
|
||||||
|
op_cache_put_finish<CA>,
|
||||||
op_cache_match<CA>,
|
op_cache_match<CA>,
|
||||||
op_cache_delete<CA>,
|
op_cache_delete<CA>,
|
||||||
],
|
],
|
||||||
|
@ -86,16 +88,24 @@ pub struct CacheDeleteRequest {
|
||||||
pub request_url: String,
|
pub request_url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait(?Send)]
|
||||||
pub trait Cache: Clone {
|
pub trait Cache: Clone + 'static {
|
||||||
|
type CachePutResourceType: Resource;
|
||||||
|
|
||||||
async fn storage_open(&self, cache_name: String) -> Result<i64, AnyError>;
|
async fn storage_open(&self, cache_name: String) -> Result<i64, AnyError>;
|
||||||
async fn storage_has(&self, cache_name: String) -> Result<bool, AnyError>;
|
async fn storage_has(&self, cache_name: String) -> Result<bool, AnyError>;
|
||||||
async fn storage_delete(&self, cache_name: String) -> Result<bool, AnyError>;
|
async fn storage_delete(&self, cache_name: String) -> Result<bool, AnyError>;
|
||||||
|
|
||||||
async fn put(
|
/// Create a put request.
|
||||||
|
async fn put_create(
|
||||||
&self,
|
&self,
|
||||||
request_response: CachePutRequest,
|
request_response: CachePutRequest,
|
||||||
) -> Result<Option<Rc<dyn Resource>>, AnyError>;
|
) -> Result<Option<Rc<Self::CachePutResourceType>>, AnyError>;
|
||||||
|
/// Complete a put request.
|
||||||
|
async fn put_finish(
|
||||||
|
&self,
|
||||||
|
resource: Rc<Self::CachePutResourceType>,
|
||||||
|
) -> Result<(), AnyError>;
|
||||||
async fn r#match(
|
async fn r#match(
|
||||||
&self,
|
&self,
|
||||||
request: CacheMatchRequest,
|
request: CacheMatchRequest,
|
||||||
|
@ -113,7 +123,7 @@ pub async fn op_cache_storage_open<CA>(
|
||||||
cache_name: String,
|
cache_name: String,
|
||||||
) -> Result<i64, AnyError>
|
) -> Result<i64, AnyError>
|
||||||
where
|
where
|
||||||
CA: Cache + 'static,
|
CA: Cache,
|
||||||
{
|
{
|
||||||
let cache = get_cache::<CA>(&state)?;
|
let cache = get_cache::<CA>(&state)?;
|
||||||
cache.storage_open(cache_name).await
|
cache.storage_open(cache_name).await
|
||||||
|
@ -125,7 +135,7 @@ pub async fn op_cache_storage_has<CA>(
|
||||||
cache_name: String,
|
cache_name: String,
|
||||||
) -> Result<bool, AnyError>
|
) -> Result<bool, AnyError>
|
||||||
where
|
where
|
||||||
CA: Cache + 'static,
|
CA: Cache,
|
||||||
{
|
{
|
||||||
let cache = get_cache::<CA>(&state)?;
|
let cache = get_cache::<CA>(&state)?;
|
||||||
cache.storage_has(cache_name).await
|
cache.storage_has(cache_name).await
|
||||||
|
@ -137,7 +147,7 @@ pub async fn op_cache_storage_delete<CA>(
|
||||||
cache_name: String,
|
cache_name: String,
|
||||||
) -> Result<bool, AnyError>
|
) -> Result<bool, AnyError>
|
||||||
where
|
where
|
||||||
CA: Cache + 'static,
|
CA: Cache,
|
||||||
{
|
{
|
||||||
let cache = get_cache::<CA>(&state)?;
|
let cache = get_cache::<CA>(&state)?;
|
||||||
cache.storage_delete(cache_name).await
|
cache.storage_delete(cache_name).await
|
||||||
|
@ -149,10 +159,10 @@ pub async fn op_cache_put<CA>(
|
||||||
request_response: CachePutRequest,
|
request_response: CachePutRequest,
|
||||||
) -> Result<Option<ResourceId>, AnyError>
|
) -> Result<Option<ResourceId>, AnyError>
|
||||||
where
|
where
|
||||||
CA: Cache + 'static,
|
CA: Cache,
|
||||||
{
|
{
|
||||||
let cache = get_cache::<CA>(&state)?;
|
let cache = get_cache::<CA>(&state)?;
|
||||||
match cache.put(request_response).await? {
|
match cache.put_create(request_response).await? {
|
||||||
Some(resource) => {
|
Some(resource) => {
|
||||||
let rid = state.borrow_mut().resource_table.add_rc_dyn(resource);
|
let rid = state.borrow_mut().resource_table.add_rc_dyn(resource);
|
||||||
Ok(Some(rid))
|
Ok(Some(rid))
|
||||||
|
@ -161,13 +171,29 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[op]
|
||||||
|
pub async fn op_cache_put_finish<CA>(
|
||||||
|
state: Rc<RefCell<OpState>>,
|
||||||
|
rid: ResourceId,
|
||||||
|
) -> Result<(), AnyError>
|
||||||
|
where
|
||||||
|
CA: Cache,
|
||||||
|
{
|
||||||
|
let cache = get_cache::<CA>(&state)?;
|
||||||
|
let resource = state
|
||||||
|
.borrow_mut()
|
||||||
|
.resource_table
|
||||||
|
.get::<CA::CachePutResourceType>(rid)?;
|
||||||
|
cache.put_finish(resource).await
|
||||||
|
}
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
pub async fn op_cache_match<CA>(
|
pub async fn op_cache_match<CA>(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
request: CacheMatchRequest,
|
request: CacheMatchRequest,
|
||||||
) -> Result<Option<CacheMatchResponse>, AnyError>
|
) -> Result<Option<CacheMatchResponse>, AnyError>
|
||||||
where
|
where
|
||||||
CA: Cache + 'static,
|
CA: Cache,
|
||||||
{
|
{
|
||||||
let cache = get_cache::<CA>(&state)?;
|
let cache = get_cache::<CA>(&state)?;
|
||||||
match cache.r#match(request).await? {
|
match cache.r#match(request).await? {
|
||||||
|
@ -186,7 +212,7 @@ pub async fn op_cache_delete<CA>(
|
||||||
request: CacheDeleteRequest,
|
request: CacheDeleteRequest,
|
||||||
) -> Result<bool, AnyError>
|
) -> Result<bool, AnyError>
|
||||||
where
|
where
|
||||||
CA: Cache + 'static,
|
CA: Cache,
|
||||||
{
|
{
|
||||||
let cache = get_cache::<CA>(&state)?;
|
let cache = get_cache::<CA>(&state)?;
|
||||||
cache.delete(request).await
|
cache.delete(request).await
|
||||||
|
@ -194,7 +220,7 @@ where
|
||||||
|
|
||||||
pub fn get_cache<CA>(state: &Rc<RefCell<OpState>>) -> Result<CA, AnyError>
|
pub fn get_cache<CA>(state: &Rc<RefCell<OpState>>) -> Result<CA, AnyError>
|
||||||
where
|
where
|
||||||
CA: Cache + 'static,
|
CA: Cache,
|
||||||
{
|
{
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
if let Some(cache) = state.try_borrow::<CA>() {
|
if let Some(cache) = state.try_borrow::<CA>() {
|
||||||
|
|
21
ext/cache/sqlite.rs
vendored
21
ext/cache/sqlite.rs
vendored
|
@ -92,8 +92,10 @@ impl SqliteBackedCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait(?Send)]
|
||||||
impl Cache for SqliteBackedCache {
|
impl Cache for SqliteBackedCache {
|
||||||
|
type CachePutResourceType = CachePutResource;
|
||||||
|
|
||||||
/// Open a cache storage. Internally, this creates a row in the
|
/// Open a cache storage. Internally, this creates a row in the
|
||||||
/// sqlite db if the cache doesn't exist and returns the internal id
|
/// sqlite db if the cache doesn't exist and returns the internal id
|
||||||
/// of the cache.
|
/// of the cache.
|
||||||
|
@ -167,10 +169,10 @@ impl Cache for SqliteBackedCache {
|
||||||
.await?
|
.await?
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn put(
|
async fn put_create(
|
||||||
&self,
|
&self,
|
||||||
request_response: CachePutRequest,
|
request_response: CachePutRequest,
|
||||||
) -> Result<Option<Rc<dyn Resource>>, AnyError> {
|
) -> Result<Option<Rc<CachePutResource>>, AnyError> {
|
||||||
let db = self.connection.clone();
|
let db = self.connection.clone();
|
||||||
let cache_storage_dir = self.cache_storage_dir.clone();
|
let cache_storage_dir = self.cache_storage_dir.clone();
|
||||||
let now = SystemTime::now().duration_since(UNIX_EPOCH)?;
|
let now = SystemTime::now().duration_since(UNIX_EPOCH)?;
|
||||||
|
@ -202,6 +204,13 @@ impl Cache for SqliteBackedCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn put_finish(
|
||||||
|
&self,
|
||||||
|
resource: Rc<CachePutResource>,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
resource.write_to_cache().await
|
||||||
|
}
|
||||||
|
|
||||||
async fn r#match(
|
async fn r#match(
|
||||||
&self,
|
&self,
|
||||||
request: CacheMatchRequest,
|
request: CacheMatchRequest,
|
||||||
|
@ -346,7 +355,7 @@ impl CachePutResource {
|
||||||
Ok(data.len())
|
Ok(data.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn shutdown(self: Rc<Self>) -> Result<(), AnyError> {
|
async fn write_to_cache(self: Rc<Self>) -> Result<(), AnyError> {
|
||||||
let resource = deno_core::RcRef::map(&self, |r| &r.file);
|
let resource = deno_core::RcRef::map(&self, |r| &r.file);
|
||||||
let mut file = resource.borrow_mut().await;
|
let mut file = resource.borrow_mut().await;
|
||||||
file.flush().await?;
|
file.flush().await?;
|
||||||
|
@ -377,10 +386,6 @@ impl Resource for CachePutResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
deno_core::impl_writable!();
|
deno_core::impl_writable!();
|
||||||
|
|
||||||
fn shutdown(self: Rc<Self>) -> AsyncResult<()> {
|
|
||||||
Box::pin(self.shutdown())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CacheResponseResource {
|
pub struct CacheResponseResource {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue