Skip to content

Commit afe8d61

Browse files
committed
Merge branch 'unstable' into stable
2 parents 80ff36b + 6c15195 commit afe8d61

File tree

12 files changed

+389
-151
lines changed

12 files changed

+389
-151
lines changed

.depl/config.yaml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,66 @@ pipelines:
245245
to: cc-static-server
246246
- from: cc-static-server/static-server.yaml
247247
to: static-server.yaml
248+
- title: build-static-server-debug
249+
desc: Build `cc-static-server` (debug) and update content storage
250+
info: cc-services-static-server-debug@0.1.0
251+
tags:
252+
- cargo
253+
- clippy
254+
- lint
255+
default: true
256+
artifacts:
257+
- from: target/x86_64-unknown-linux-gnu/debug/cc-static-server
258+
to: static-server/cc-static-server-debug
259+
- from: cc-static-server/static-server.yaml
260+
to: static-server/static-server.yaml
261+
actions:
262+
- title: Sync script to know Rust package version
263+
info: sync-rust-crate-ver@0.1.0
264+
tags: []
265+
exec_in_project_dir: false
266+
action:
267+
type: use_from_storage
268+
content_info: get-know-rust-package-version@latest
269+
- title: Cargo Build (Debug)
270+
info: cargo-debug@0.1.0
271+
tags:
272+
- rust
273+
- cargo
274+
requirements:
275+
- type: exists
276+
path: /bin/cargo
277+
action:
278+
type: build
279+
supported_langs:
280+
- rust
281+
commands:
282+
- bash_c: cargo build --package cc-static-server --target x86_64-unknown-linux-gnu
283+
ignore_fails: false
284+
show_success_output: false
285+
show_bash_c: true
286+
- title: Auto-upload CC Static Server to Deployer's Storage
287+
info: auto-upload-static-server@0.1.0
288+
tags: []
289+
exec_in_project_dir: false
290+
action:
291+
type: add_to_storage
292+
short_name: static-server-debug
293+
auto_version_rule:
294+
type: cmd_stdout
295+
cmd:
296+
bash_c: python .depl/rust-crate-ver.py
297+
ignore_fails: true
298+
show_success_output: true
299+
show_bash_c: false
300+
only_when_fresh: false
301+
content:
302+
type: fixed_files
303+
placements:
304+
- from: target/x86_64-unknown-linux-gnu/debug/cc-static-server
305+
to: cc-static-server
306+
- from: cc-static-server/static-server.yaml
307+
to: static-server.yaml
248308
- title: build-error-pages
249309
desc: Build `cc-error-pages`
250310
info: cc-ui-kit-frontend-app-build@0.1.0

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ members = [
1010
resolver = "2"
1111

1212
[workspace.package]
13-
version = "0.11.0-1"
13+
version = "0.11.1"
1414
edition = "2024"
1515
license = "MIT"
1616
authors = ["Klimenty Titov <aclo.create@gmail.com>"]
@@ -27,11 +27,11 @@ bytes = "1"
2727
clap = { version = "4", features = ["derive"] }
2828
console_error_panic_hook = "0.1.7"
2929
console_log = "1"
30-
dashmap = "6.1"
3130
encoding_rs = "0.8"
3231
flate2 = { version = "1", default-features = false }
3332
fs-change-notifier = "0.1.3"
3433
headers = "0.4"
34+
http = "1"
3535
http-body-util = "0.1"
3636
icondata = { version = "0.5", default-features = false }
3737
leptos = { version = "0.7", default-features = false }
@@ -65,7 +65,7 @@ zstd = { version = "0.13", default-features = false }
6565
web-sys = { version = "0.3", default-features = false }
6666

6767
[profile.release]
68-
opt-level = "z"
68+
opt-level = 3
6969
debug = false
7070
lto = true
7171
codegen-units = 1

cc-static-server/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ authors = { workspace = true }
88

99
[dependencies]
1010
cc-server-kit = { workspace = true, features = ["http3", "cors", "acme", "oapi", "otel", "force-https"] }
11-
dashmap = { workspace = true }
1211
fs-change-notifier = { workspace = true }
1312
headers = { workspace = true }
1413
mime = { workspace = true }
1514
serde = { workspace = true, features = ["derive"] }
16-
tokio = { workspace = true, features = ["macros"] }
15+
tokio = { workspace = true, features = ["macros", "sync"] }
1716
tracing = { workspace = true }

cc-static-server/src/caching.rs

Lines changed: 106 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use cc_server_kit::prelude::*;
22
use cc_server_kit::salvo::http::HttpRange;
3-
use dashmap::DashMap;
43
use fs_change_notifier::*;
54
use headers::{
65
AcceptRanges, ContentLength, ContentRange, ContentType, ETag, HeaderMapExt, IfMatch, IfModifiedSince, IfNoneMatch,
@@ -10,8 +9,10 @@ use salvo::fs::NamedFile;
109
use salvo::http::header::{CONTENT_DISPOSITION, CONTENT_ENCODING, CONTENT_TYPE, IF_NONE_MATCH, RANGE};
1110
use salvo::http::{HeaderMap, HeaderValue};
1211
use std::cmp;
12+
use std::collections::HashMap;
1313
use std::path::{Path, PathBuf};
1414
use std::sync::Arc;
15+
use tokio::sync::Mutex;
1516

1617
const CHUNK_SIZE: u64 = 1024 * 1024;
1718

@@ -196,22 +197,113 @@ impl CachedFile {
196197
}
197198
}
198199

200+
/// Request given file either from in-memory cacher or from disk.
201+
pub async fn send_file(
202+
cacher: &Option<Arc<Mutex<CacheMap>>>,
203+
req: &mut Request,
204+
depot: &mut Depot,
205+
res: &mut Response,
206+
filename: &str,
207+
path: &Path,
208+
) -> MResult<()> {
209+
use salvo::Writer;
210+
211+
if let Some(cacher) = cacher.as_ref() {
212+
{
213+
let guard = cacher.lock().await;
214+
if let Ok(Some(cached)) = guard.fetch(path) {
215+
cached.send(req.headers(), res).await;
216+
return Ok(());
217+
}
218+
}
219+
let length = tokio::fs::metadata(path)
220+
.await
221+
.map_err(|e| ServerError::from_private(e).with_404())?
222+
.len();
223+
if length > 16 * 1024 * 1024 {
224+
file_upload!(path.to_path_buf(), filename.to_string())
225+
.write(req, depot, res)
226+
.await;
227+
} else {
228+
let cached = CachedFile::construct_from(filename, path, length).await?;
229+
{
230+
let mut guard = cacher.lock().await;
231+
guard.upsert(path, cached.clone())?;
232+
}
233+
cached.send(req.headers(), res).await;
234+
}
235+
} else {
236+
file_upload!(path.to_path_buf(), filename.to_string())
237+
.write(req, depot, res)
238+
.await;
239+
}
240+
Ok(())
241+
}
242+
243+
/// Request given HTML page either from in-memory cacher or from disk.
244+
pub async fn send_html(
245+
cacher: &Option<Arc<Mutex<CacheMap>>>,
246+
req: &mut Request,
247+
depot: &mut Depot,
248+
res: &mut Response,
249+
filename: &str,
250+
path: &Path,
251+
) -> MResult<()> {
252+
use salvo::Writer;
253+
254+
if let Some(cacher) = cacher.as_ref() {
255+
let cached = {
256+
let guard = cacher.lock().await;
257+
guard.fetch(path)
258+
};
259+
if let Ok(Some(cached)) = cached {
260+
let site = String::from_utf8_lossy_owned(cached.bytes);
261+
html!(site).unwrap().write(req, depot, res).await;
262+
return Ok(());
263+
}
264+
let length = tokio::fs::metadata(path)
265+
.await
266+
.map_err(|e| ServerError::from_private(e).with_404())?
267+
.len();
268+
if length > 16 * 1024 * 1024 {
269+
let site = tokio::fs::read_to_string(path)
270+
.await
271+
.map_err(|e| ServerError::from_private(e).with_404())?;
272+
html!(site).unwrap().write(req, depot, res).await;
273+
} else {
274+
let cached = CachedFile::construct_from(filename, path, length).await?;
275+
{
276+
let mut guard = cacher.lock().await;
277+
guard.upsert(path, cached.clone())?;
278+
}
279+
let site = String::from_utf8_lossy_owned(cached.bytes);
280+
html!(site).unwrap().write(req, depot, res).await;
281+
}
282+
} else {
283+
let site = tokio::fs::read_to_string(path)
284+
.await
285+
.map_err(|e| ServerError::from_private(e).with_404())?;
286+
html!(site).unwrap().write(req, depot, res).await;
287+
}
288+
Ok(())
289+
}
290+
199291
/// In-memory cache implementation for files based on `DashMap`.
200-
pub struct CacheMap(DashMap<PathBuf, CachedFile>);
292+
pub struct CacheMap(HashMap<PathBuf, CachedFile>);
201293

202294
impl CacheMap {
203295
/// Create in-memory cache.
204-
pub fn new() -> Arc<Self> {
205-
Arc::new(Self(DashMap::new()))
296+
pub fn new() -> Arc<Mutex<Self>> {
297+
Arc::new(Mutex::new(Self(HashMap::new())))
206298
}
207299

208300
/// Clear cache.
209-
pub fn clear(&self) {
301+
pub fn clear(&mut self) {
210302
self.0.clear();
211303
}
212304

213305
/// Insert or update content by its path.
214-
pub fn upsert(&self, path: impl AsRef<Path>, content: CachedFile) -> MResult<()> {
306+
pub fn upsert(&mut self, path: impl AsRef<Path>, content: CachedFile) -> MResult<()> {
215307
let path = std::fs::canonicalize(path.as_ref()).map_err(ServerError::from_private)?;
216308
self.0.insert(path, content);
217309
Ok(())
@@ -220,19 +312,19 @@ impl CacheMap {
220312
/// Fetch content.
221313
pub fn fetch(&self, path: impl AsRef<Path>) -> MResult<Option<CachedFile>> {
222314
let path = std::fs::canonicalize(path.as_ref()).map_err(ServerError::from_private)?;
223-
Ok(self.0.get(&path).map(|r#ref| r#ref.value().clone()))
315+
Ok(self.0.get(&path).cloned())
224316
}
225317

226318
/// Remove content due to invalidation.
227-
pub fn invalidate(&self, path: impl AsRef<Path>) -> MResult<()> {
319+
pub fn invalidate(&mut self, path: impl AsRef<Path>) -> MResult<()> {
228320
let path = std::fs::canonicalize(path.as_ref()).map_err(ServerError::from_private)?;
229321
self.0.remove(&path);
230322
Ok(())
231323
}
232324
}
233325

234326
/// Cache invalidator runner.
235-
pub async fn cache_runner(path: impl AsRef<Path>, cache_map: Arc<CacheMap>) -> MResult<()> {
327+
pub async fn cache_runner(path: impl AsRef<Path>, cache_map: Arc<Mutex<CacheMap>>) -> MResult<()> {
236328
let empty = std::collections::HashSet::new();
237329
loop {
238330
let (mut wr, rx) = create_watcher(|e| tracing::error!("{e:?}")).map_err(|e| {
@@ -244,8 +336,11 @@ pub async fn cache_runner(path: impl AsRef<Path>, cache_map: Arc<CacheMap>) -> M
244336
.map_err(ServerError::from_private)?;
245337

246338
let files = fetch_changed(path.as_ref(), rx, &empty).await;
247-
for file in files {
248-
cache_map.invalidate(file)?;
339+
{
340+
let mut guard = cache_map.lock().await;
341+
for file in files {
342+
guard.invalidate(file)?;
343+
}
249344
}
250345
}
251346
}

cc-static-server/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,6 @@ mod caching;
1111
mod static_routes;
1212

1313
pub use caching::CacheMap;
14-
pub use static_routes::{CustomStaticRouter, frontend_router, frontend_router_from_given_dist};
14+
pub use static_routes::{
15+
NoRedirectStaticRouter, ProvidedRoutesStaticRouter, StaticRouter, frontend_router, frontend_router_from_given_dist,
16+
};

cc-static-server/src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ impl GenericSetup for Setup {
2323
async fn main() {
2424
let setup = load_generic_config::<Setup>("static-server").await.unwrap();
2525
let state = load_generic_state(&setup, true).await.unwrap();
26+
27+
tracing::info!("Static Server (v{})", env!("CARGO_PKG_VERSION"));
28+
2629
let router = get_root_router(&state).push(frontend_router().unwrap());
2730
let (server, _handler) = start(state, &setup, router).await.unwrap();
2831
server.await

0 commit comments

Comments
 (0)