Skip to content

Commit

Permalink
♻️ Backend data access has been implemented based on tairitsu.
Browse files Browse the repository at this point in the history
  • Loading branch information
langyo committed Oct 10, 2024
1 parent 032a972 commit 53d1adc
Show file tree
Hide file tree
Showing 57 changed files with 1,009 additions and 543 deletions.
9 changes: 8 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,14 @@ wasm-bindgen = "0.2.92"
wasm-bindgen-futures = "^0.4"
gloo = "^0.11"

sea-orm = "^1"
sea-orm = { version = "^1", default-features = false, features = [
"macros",
"proxy",
"with-uuid",
"with-chrono",
"with-json",
"debug-print",
] }
worker = "^0.3"

image = { version = "^0.25", features = ["gif", "jpeg", "png", "webp"] }
Expand Down
1 change: 0 additions & 1 deletion Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,4 @@ script = '''
#!@duckscript
exec cargo clean
rm -r ./cache
'''
8 changes: 4 additions & 4 deletions packages/client/src/pages/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,14 +244,14 @@ pub fn Register() -> HtmlResult {
let name = (*name_raw).clone();
let password_raw = (*password_raw).clone();
let email = (*email_raw).clone();
let permission = permission_raw.to_string();
let permission = (*permission_raw).clone();

wasm_bindgen_futures::spawn_local(async move {
match register(&RegisterParams {
name,
password_raw,
name: Some(name),
password_raw: Some(password_raw),
email,
permission,
permission: Some(permission),
}).await {
Ok(_) => {
info!("Register success");
Expand Down
14 changes: 11 additions & 3 deletions packages/database/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ edition.workspace = true
_types = { path = "../types" }
_functions = { path = "../functions" }

tairitsu-database = { workspace = true }

anyhow = { workspace = true }
async-trait = { workspace = true }
derive_more = { workspace = true }
once_cell = { workspace = true }
cfg-if = { workspace = true }

base64 = { workspace = true }
bytes = { workspace = true }
Expand All @@ -27,13 +30,18 @@ log = { workspace = true }
tokio = { version = "^1", features = ["full"] }
tracing = { workspace = true }

worker = { workspace = true }
sea-orm = { workspace = true }

jsonwebtoken = "^9"
bcrypt = "^0.15"
sha3 = "^0.10"

sled = { workspace = true }
postcard = { workspace = true }

image = { workspace = true }
webp = { workspace = true }
webp-animation = { workspace = true }

[features]
cloudflare = ["tairitsu-database/cloudflare"]
native = ["tairitsu-database/native"]
wasi = ["tairitsu-database/wasi"]
86 changes: 50 additions & 36 deletions packages/database/src/functions/backend/media.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,13 @@ use chrono::Utc;
use image::{EncodableLayout as _, GenericImageView, ImageFormat};
use sha3::{Digest as _, Sha3_256};

use crate::functions::backend::media_insert_log::list as list_log;
use crate::init::RouteEnv;
use _types::{
config::load_config,
consts::{DATABASE_DIR, MEDIA_CACHE_DIR, MEDIA_DIR},
consts::{MEDIA_CACHE_DIR, MEDIA_DIR},
models::media::*,
};

pub static DB: Lazy<sled::Db> = Lazy::new(|| {
sled::open({
let mut path = (*DATABASE_DIR).clone();
path.push("media");
path
})
.unwrap()
});
use tairitsu_database::prelude::*;

pub static IS_ENABLE_WEBP_AUTO_CONVERT: Lazy<bool> = Lazy::new(|| {
let config = load_config().unwrap();
Expand All @@ -32,27 +24,52 @@ pub static IS_USE_SOURCE_FILE_NAME: Lazy<bool> = Lazy::new(|| {
config.upload.use_source_file_name
});

pub async fn count() -> Result<usize> {
Ok(DB.len())
pub const GLOBAL_CONFIG_MEDIA_COUNT_KEY: &str = "media_count";

pub async fn get(env: RouteEnv, id: String) -> Result<Option<Model>> {
if let Some(ret) = env.kv.images.get(id).await? {
Ok(serde_json::from_str(&ret)?)
} else {
Ok(None)
}
}

pub async fn count(env: RouteEnv) -> Result<u64> {
let count = env
.kv
.global_config
.get(GLOBAL_CONFIG_MEDIA_COUNT_KEY.to_string())
.await?
.map(|x| x.parse::<u64>().unwrap_or(0))
.unwrap_or(0);

Ok(count)
}

pub async fn list(offset: usize, limit: usize) -> Result<Vec<Model>> {
let ret = list_log(offset, limit)
pub async fn list(env: RouteEnv, offset: usize, limit: usize) -> Result<Vec<Model>> {
let ret = env
.kv
.images
.list_by_prefix("".to_string(), Some(limit), Some(offset.to_string()))
.await?
.into_iter()
.map(|(_time, hash)| {
let raw = DB
.get(hash.clone())?
.ok_or(anyhow!("Image not found: {}", hash))?;
let value = postcard::from_bytes(raw.as_ref()).unwrap();
Ok(value)
.map(|x| {
serde_json::from_str(&x)
.map_err(|err| anyhow!("Failed to parse JSON from string: {}", err))
})
.collect::<Result<Vec<_>>>()?;
.collect::<Vec<Result<Model>>>()
.into_iter()
.collect::<Result<Vec<Model>>>()?;

Ok(ret)
}

pub async fn set(uploader: String, data: Bytes, file_name_raw: Option<String>) -> Result<String> {
pub async fn set(
env: RouteEnv,
uploader: String,
data: Bytes,
file_name_raw: Option<String>,
) -> Result<String> {
let now = Utc::now();
let hash = Sha3_256::digest(&data).to_vec();
let hash = BASE64_URL_SAFE_NO_PAD.encode(&hash);
Expand All @@ -69,7 +86,10 @@ pub async fn set(uploader: String, data: Bytes, file_name_raw: Option<String>) -
};

// Check if the image is already uploaded
ensure!(!DB.contains_key(db_key.as_str())?, "Image already uploaded");
ensure!(
env.kv.images.get(db_key.clone()).await?.is_some(),
"Image already uploaded"
);

let data = if *IS_ENABLE_WEBP_AUTO_CONVERT {
use image::{codecs::gif::GifDecoder, AnimationDecoder};
Expand Down Expand Up @@ -133,8 +153,10 @@ pub async fn set(uploader: String, data: Bytes, file_name_raw: Option<String>) -
size,
mime: mime.to_mime_type().to_string(),
};
let raw = postcard::to_allocvec(&value)?;
DB.insert(db_key.as_str(), raw)?;
env.kv
.images
.set(db_key.clone(), serde_json::to_string(&value)?)
.await?;

std::thread::spawn({
let db_key = db_key.clone();
Expand Down Expand Up @@ -190,16 +212,8 @@ pub fn generate_thumbnail(hash: impl ToString, data: Bytes) -> Result<Bytes> {
Ok(image)
}

pub async fn get(key: impl ToString) -> Result<Option<Model>> {
let ret = DB
.get(key.to_string().as_bytes())?
.map(|r| postcard::from_bytes(r.to_vec().as_slice()).unwrap());

Ok(ret)
}

pub async fn delete(id: impl ToString) -> Result<()> {
DB.remove(id.to_string().as_bytes())?;
pub async fn delete(env: RouteEnv, id: String) -> Result<()> {
env.kv.images.delete(id).await?;

Ok(())
}
58 changes: 0 additions & 58 deletions packages/database/src/functions/backend/media_insert_log.rs

This file was deleted.

1 change: 0 additions & 1 deletion packages/database/src/functions/backend/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
pub mod media;
pub mod media_insert_log;
pub mod user;
Loading

0 comments on commit 53d1adc

Please sign in to comment.