mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-08 06:09:58 +00:00
RequestServer: Add a time parameter to the clear cache endpoint
This allows removing cache entries last accessed since a provided timestamp.
This commit is contained in:
parent
ba49942b6d
commit
3f61f0f189
Notes:
github-actions[bot]
2025-11-12 14:08:53 +00:00
Author: https://github.com/trflynn89
Commit: 3f61f0f189
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6675
Reviewed-by: https://github.com/gmta
Reviewed-by: https://github.com/konradekk
11 changed files with 35 additions and 38 deletions
|
|
@ -831,7 +831,7 @@ void Application::initialize_actions()
|
||||||
|
|
||||||
m_debug_menu->add_action(Action::create("Collect Garbage"sv, ActionID::CollectGarbage, debug_request("collect-garbage"sv)));
|
m_debug_menu->add_action(Action::create("Collect Garbage"sv, ActionID::CollectGarbage, debug_request("collect-garbage"sv)));
|
||||||
m_debug_menu->add_action(Action::create("Clear Cache"sv, ActionID::ClearCache, [this, clear_memory_cache = debug_request("clear-cache")]() {
|
m_debug_menu->add_action(Action::create("Clear Cache"sv, ActionID::ClearCache, [this, clear_memory_cache = debug_request("clear-cache")]() {
|
||||||
m_request_server_client->async_clear_cache();
|
m_request_server_client->async_remove_cache_entries_accessed_since({});
|
||||||
clear_memory_cache();
|
clear_memory_cache();
|
||||||
}));
|
}));
|
||||||
m_debug_menu->add_action(Action::create("Clear All Cookies"sv, ActionID::ClearCookies, [this]() { m_cookie_jar->clear_all_cookies(); }));
|
m_debug_menu->add_action(Action::create("Clear All Cookies"sv, ActionID::ClearCookies, [this]() { m_cookie_jar->clear_all_cookies(); }));
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,6 @@
|
||||||
|
|
||||||
namespace RequestServer {
|
namespace RequestServer {
|
||||||
|
|
||||||
static LexicalPath path_for_cache_key(LexicalPath const& cache_directory, u64 cache_key)
|
|
||||||
{
|
|
||||||
return cache_directory.append(MUST(String::formatted("{:016x}", cache_key)));
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorOr<CacheHeader> CacheHeader::read_from_stream(Stream& stream)
|
ErrorOr<CacheHeader> CacheHeader::read_from_stream(Stream& stream)
|
||||||
{
|
{
|
||||||
CacheHeader header;
|
CacheHeader header;
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ ErrorOr<CacheIndex> CacheIndex::create(Database::Database& database)
|
||||||
Statements statements {};
|
Statements statements {};
|
||||||
statements.insert_entry = TRY(database.prepare_statement("INSERT OR REPLACE INTO CacheIndex VALUES (?, ?, ?, ?, ?, ?, ?);"sv));
|
statements.insert_entry = TRY(database.prepare_statement("INSERT OR REPLACE INTO CacheIndex VALUES (?, ?, ?, ?, ?, ?, ?);"sv));
|
||||||
statements.remove_entry = TRY(database.prepare_statement("DELETE FROM CacheIndex WHERE cache_key = ?;"sv));
|
statements.remove_entry = TRY(database.prepare_statement("DELETE FROM CacheIndex WHERE cache_key = ?;"sv));
|
||||||
statements.remove_all_entries = TRY(database.prepare_statement("DELETE FROM CacheIndex;"sv));
|
statements.remove_entries_accessed_since = TRY(database.prepare_statement("DELETE FROM CacheIndex WHERE last_access_time >= ? RETURNING cache_key;"sv));
|
||||||
statements.select_entry = TRY(database.prepare_statement("SELECT * FROM CacheIndex WHERE cache_key = ?;"sv));
|
statements.select_entry = TRY(database.prepare_statement("SELECT * FROM CacheIndex WHERE cache_key = ?;"sv));
|
||||||
statements.update_response_headers = TRY(database.prepare_statement("UPDATE CacheIndex SET response_headers = ? WHERE cache_key = ?;"sv));
|
statements.update_response_headers = TRY(database.prepare_statement("UPDATE CacheIndex SET response_headers = ? WHERE cache_key = ?;"sv));
|
||||||
statements.update_last_access_time = TRY(database.prepare_statement("UPDATE CacheIndex SET last_access_time = ? WHERE cache_key = ?;"sv));
|
statements.update_last_access_time = TRY(database.prepare_statement("UPDATE CacheIndex SET last_access_time = ? WHERE cache_key = ?;"sv));
|
||||||
|
|
@ -136,10 +136,17 @@ void CacheIndex::remove_entry(u64 cache_key)
|
||||||
m_entries.remove(cache_key);
|
m_entries.remove(cache_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CacheIndex::remove_all_entries()
|
void CacheIndex::remove_entries_accessed_since(UnixDateTime since, Function<void(u64 cache_key)> on_entry_removed)
|
||||||
{
|
{
|
||||||
m_database.execute_statement(m_statements.remove_all_entries, {});
|
m_database.execute_statement(
|
||||||
m_entries.clear();
|
m_statements.remove_entries_accessed_since,
|
||||||
|
[&](auto statement_id) {
|
||||||
|
auto cache_key = m_database.result_column<u64>(statement_id, 0);
|
||||||
|
m_entries.remove(cache_key);
|
||||||
|
|
||||||
|
on_entry_removed(cache_key);
|
||||||
|
},
|
||||||
|
since);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CacheIndex::update_response_headers(u64 cache_key, HTTP::HeaderMap response_headers)
|
void CacheIndex::update_response_headers(u64 cache_key, HTTP::HeaderMap response_headers)
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ public:
|
||||||
|
|
||||||
void create_entry(u64 cache_key, String url, HTTP::HeaderMap, u64 data_size, UnixDateTime request_time, UnixDateTime response_time);
|
void create_entry(u64 cache_key, String url, HTTP::HeaderMap, u64 data_size, UnixDateTime request_time, UnixDateTime response_time);
|
||||||
void remove_entry(u64 cache_key);
|
void remove_entry(u64 cache_key);
|
||||||
void remove_all_entries();
|
void remove_entries_accessed_since(UnixDateTime, Function<void(u64 cache_key)> on_entry_removed);
|
||||||
|
|
||||||
Optional<Entry&> find_entry(u64 cache_key);
|
Optional<Entry&> find_entry(u64 cache_key);
|
||||||
|
|
||||||
|
|
@ -49,7 +49,7 @@ private:
|
||||||
struct Statements {
|
struct Statements {
|
||||||
Database::StatementID insert_entry { 0 };
|
Database::StatementID insert_entry { 0 };
|
||||||
Database::StatementID remove_entry { 0 };
|
Database::StatementID remove_entry { 0 };
|
||||||
Database::StatementID remove_all_entries { 0 };
|
Database::StatementID remove_entries_accessed_since { 0 };
|
||||||
Database::StatementID select_entry { 0 };
|
Database::StatementID select_entry { 0 };
|
||||||
Database::StatementID update_response_headers { 0 };
|
Database::StatementID update_response_headers { 0 };
|
||||||
Database::StatementID update_last_access_time { 0 };
|
Database::StatementID update_last_access_time { 0 };
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <LibCore/DirIterator.h>
|
|
||||||
#include <LibCore/StandardPaths.h>
|
#include <LibCore/StandardPaths.h>
|
||||||
#include <LibFileSystem/FileSystem.h>
|
#include <LibFileSystem/FileSystem.h>
|
||||||
#include <LibURL/URL.h>
|
#include <LibURL/URL.h>
|
||||||
|
|
@ -144,28 +143,17 @@ Requests::CacheSizes DiskCache::estimate_cache_size_accessed_since(UnixDateTime
|
||||||
return m_index.estimate_cache_size_accessed_since(since);
|
return m_index.estimate_cache_size_accessed_since(since);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiskCache::clear_cache()
|
void DiskCache::remove_entries_accessed_since(UnixDateTime since)
|
||||||
{
|
{
|
||||||
for (auto const& [_, open_entries] : m_open_cache_entries) {
|
m_index.remove_entries_accessed_since(since, [&](auto cache_key) {
|
||||||
for (auto const& open_entry : open_entries)
|
if (auto open_entries = m_open_cache_entries.get(cache_key); open_entries.has_value()) {
|
||||||
open_entry->mark_for_deletion({});
|
for (auto const& open_entry : *open_entries)
|
||||||
}
|
open_entry->mark_for_deletion({});
|
||||||
|
}
|
||||||
|
|
||||||
m_index.remove_all_entries();
|
auto cache_path = path_for_cache_key(m_cache_directory, cache_key);
|
||||||
|
(void)FileSystem::remove(cache_path.string(), FileSystem::RecursionMode::Disallowed);
|
||||||
Core::DirIterator it { m_cache_directory.string(), Core::DirIterator::SkipDots };
|
});
|
||||||
size_t cache_entries { 0 };
|
|
||||||
|
|
||||||
while (it.has_next()) {
|
|
||||||
auto entry = it.next_full_path();
|
|
||||||
if (LexicalPath { entry }.title() == INDEX_DATABASE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
(void)FileSystem::remove(entry, FileSystem::RecursionMode::Disallowed);
|
|
||||||
++cache_entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbgln("Cleared {} disk cache entries", cache_entries);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiskCache::cache_entry_closed(Badge<CacheEntry>, CacheEntry const& cache_entry)
|
void DiskCache::cache_entry_closed(Badge<CacheEntry>, CacheEntry const& cache_entry)
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ public:
|
||||||
Variant<Optional<CacheEntryReader&>, CacheHasOpenEntry> open_entry(Request&);
|
Variant<Optional<CacheEntryReader&>, CacheHasOpenEntry> open_entry(Request&);
|
||||||
|
|
||||||
Requests::CacheSizes estimate_cache_size_accessed_since(UnixDateTime since) const;
|
Requests::CacheSizes estimate_cache_size_accessed_since(UnixDateTime since) const;
|
||||||
void clear_cache();
|
void remove_entries_accessed_since(UnixDateTime since);
|
||||||
|
|
||||||
LexicalPath const& cache_directory() { return m_cache_directory; }
|
LexicalPath const& cache_directory() { return m_cache_directory; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,11 @@ u64 create_cache_key(StringView url, StringView method)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LexicalPath path_for_cache_key(LexicalPath const& cache_directory, u64 cache_key)
|
||||||
|
{
|
||||||
|
return cache_directory.append(MUST(String::formatted("{:016x}", cache_key)));
|
||||||
|
}
|
||||||
|
|
||||||
// https://httpwg.org/specs/rfc9111.html#response.cacheability
|
// https://httpwg.org/specs/rfc9111.html#response.cacheability
|
||||||
bool is_cacheable(StringView method)
|
bool is_cacheable(StringView method)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/LexicalPath.h>
|
||||||
#include <AK/StringView.h>
|
#include <AK/StringView.h>
|
||||||
#include <AK/Time.h>
|
#include <AK/Time.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
|
@ -16,6 +17,7 @@ namespace RequestServer {
|
||||||
|
|
||||||
String serialize_url_for_cache_storage(URL::URL const&);
|
String serialize_url_for_cache_storage(URL::URL const&);
|
||||||
u64 create_cache_key(StringView url, StringView method);
|
u64 create_cache_key(StringView url, StringView method);
|
||||||
|
LexicalPath path_for_cache_key(LexicalPath const& cache_directory, u64 cache_key);
|
||||||
|
|
||||||
bool is_cacheable(StringView method);
|
bool is_cacheable(StringView method);
|
||||||
bool is_cacheable(u32 status_code, HTTP::HeaderMap const&);
|
bool is_cacheable(u32 status_code, HTTP::HeaderMap const&);
|
||||||
|
|
|
||||||
|
|
@ -312,10 +312,10 @@ void ConnectionFromClient::estimate_cache_size_accessed_since(u64 cache_size_est
|
||||||
async_estimated_cache_size(cache_size_estimation_id, sizes);
|
async_estimated_cache_size(cache_size_estimation_id, sizes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionFromClient::clear_cache()
|
void ConnectionFromClient::remove_cache_entries_accessed_since(UnixDateTime since)
|
||||||
{
|
{
|
||||||
if (g_disk_cache.has_value())
|
if (g_disk_cache.has_value())
|
||||||
g_disk_cache->clear_cache();
|
g_disk_cache->remove_entries_accessed_since(since);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionFromClient::websocket_connect(i64 websocket_id, URL::URL url, ByteString origin, Vector<ByteString> protocols, Vector<ByteString> extensions, HTTP::HeaderMap additional_request_headers)
|
void ConnectionFromClient::websocket_connect(i64 websocket_id, URL::URL url, ByteString origin, Vector<ByteString> protocols, Vector<ByteString> extensions, HTTP::HeaderMap additional_request_headers)
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ private:
|
||||||
virtual void ensure_connection(URL::URL url, ::RequestServer::CacheLevel cache_level) override;
|
virtual void ensure_connection(URL::URL url, ::RequestServer::CacheLevel cache_level) override;
|
||||||
|
|
||||||
virtual void estimate_cache_size_accessed_since(u64 cache_size_estimation_id, UnixDateTime since) override;
|
virtual void estimate_cache_size_accessed_since(u64 cache_size_estimation_id, UnixDateTime since) override;
|
||||||
virtual void clear_cache() override;
|
virtual void remove_cache_entries_accessed_since(UnixDateTime since) override;
|
||||||
|
|
||||||
virtual void websocket_connect(i64 websocket_id, URL::URL, ByteString, Vector<ByteString>, Vector<ByteString>, HTTP::HeaderMap) override;
|
virtual void websocket_connect(i64 websocket_id, URL::URL, ByteString, Vector<ByteString>, Vector<ByteString>, HTTP::HeaderMap) override;
|
||||||
virtual void websocket_send(i64 websocket_id, bool, ByteBuffer) override;
|
virtual void websocket_send(i64 websocket_id, bool, ByteBuffer) override;
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ endpoint RequestServer
|
||||||
ensure_connection(URL::URL url, ::RequestServer::CacheLevel cache_level) =|
|
ensure_connection(URL::URL url, ::RequestServer::CacheLevel cache_level) =|
|
||||||
|
|
||||||
estimate_cache_size_accessed_since(u64 cache_size_estimation_id, UnixDateTime since) =|
|
estimate_cache_size_accessed_since(u64 cache_size_estimation_id, UnixDateTime since) =|
|
||||||
clear_cache() =|
|
remove_cache_entries_accessed_since(UnixDateTime since) =|
|
||||||
|
|
||||||
// Websocket Connection API
|
// Websocket Connection API
|
||||||
websocket_connect(i64 websocket_id, URL::URL url, ByteString origin, Vector<ByteString> protocols, Vector<ByteString> extensions, HTTP::HeaderMap additional_request_headers) =|
|
websocket_connect(i64 websocket_id, URL::URL url, ByteString origin, Vector<ByteString> protocols, Vector<ByteString> extensions, HTTP::HeaderMap additional_request_headers) =|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue