diff options
| author | Fuwn <[email protected]> | 2022-03-24 00:06:59 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2022-03-24 00:06:59 -0700 |
| commit | 0ae95f06ed05a774137aab654857e3e26614c16e (patch) | |
| tree | d06942db46df80474b77de6bfc993cd99d6af1bf | |
| parent | feat(api): /me route (diff) | |
| download | api-worker-0ae95f06ed05a774137aab654857e3e26614c16e.tar.xz api-worker-0ae95f06ed05a774137aab654857e3e26614c16e.zip | |
feat: cache github api
This commit allows The Senpy Club API to cache GitHub's API response,
refreshing the cache every fifty accesses.
This commit also gets rid of a few dependencies which were replaced by
their standard library counterparts.
| -rw-r--r-- | Cargo.toml | 7 | ||||
| -rw-r--r-- | src/constants.rs | 44 | ||||
| -rw-r--r-- | src/lib.rs | 1 | ||||
| -rw-r--r-- | src/structures.rs | 4 | ||||
| -rw-r--r-- | src/utils.rs | 58 |
5 files changed, 64 insertions, 50 deletions
@@ -2,7 +2,7 @@ [package] name = "api-worker" -version = "0.1.0" +version = "0.2.0" authors = ["Fuwn <[email protected]>"] edition = "2021" description = "API (as a Cloudflare Worker!)" @@ -38,11 +38,6 @@ dotenv = "0.15.0" # Worker worker = "0.0.9" -# Utility -cfg-if = "1.0.0" -const_format = "0.2.22" -lazy_static = "1.4.0" - # Web reqwest = { version = "0.11.10", features = ["json"] } diff --git a/src/constants.rs b/src/constants.rs index 6f3e6e4..ad46dfd 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -16,27 +16,29 @@ // Copyright (C) 2022-2022 Fuwn <[email protected]> // SPDX-License-Identifier: GPL-3.0-only -use const_format::formatcp; - -lazy_static::lazy_static! { - pub static ref INDEX: String = { - format!( - include_str!("index.rst"), - format_args!( - "https://github.com/senpy-club/api-worker/tree/{}", - env!("VERGEN_GIT_SHA"), - ) - ) - }; -} +use std::lazy::SyncLazy; const GITHUB_REPOSITORY: &str = "cat-milk/Anime-Girls-Holding-Programming-Books"; -pub const GITHUB_USER_CONTENT: &str = formatcp!( - "https://raw.githubusercontent.com/{}/master/", - GITHUB_REPOSITORY -); -pub const GITHUB_API_ENDPOINT: &str = formatcp!( - "https://api.github.com/repos/{}/git/trees/master?recursive=1", - GITHUB_REPOSITORY, -); + +pub static INDEX: SyncLazy<String> = SyncLazy::new(|| { + format!( + include_str!("index.rst"), + format_args!( + "https://github.com/senpy-club/api-worker/tree/{}", + env!("VERGEN_GIT_SHA"), + ) + ) +}); +pub static GITHUB_USER_CONTENT: SyncLazy<String> = SyncLazy::new(|| { + format!( + "https://raw.githubusercontent.com/{}/master/", + GITHUB_REPOSITORY + ) +}); +pub static GITHUB_API_ENDPOINT: SyncLazy<String> = SyncLazy::new(|| { + format!( + "https://api.github.com/repos/{}/git/trees/master?recursive=1", + GITHUB_REPOSITORY, + ) +}); @@ -16,6 +16,7 @@ // Copyright (C) 2022-2022 Fuwn <[email protected]> // SPDX-License-Identifier: GPL-3.0-only +#![feature(once_cell)] #![deny( warnings, nonstandard_style, diff --git a/src/structures.rs b/src/structures.rs index 3e9b7bc..4c59d51 100644 --- a/src/structures.rs +++ b/src/structures.rs @@ -20,7 +20,7 @@ use serde_derive::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone)] pub struct GitHubAPIResponse { pub sha: String, pub url: String, @@ -38,7 +38,7 @@ impl Default for GitHubAPIResponse { } } -#[derive(Serialize, Deserialize, Default)] +#[derive(Serialize, Deserialize, Default, Clone)] pub struct GitHubAPIResponseTree { pub path: String, pub mode: String, diff --git a/src/utils.rs b/src/utils.rs index 8bb70da..333a1c0 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -16,39 +16,55 @@ // Copyright (C) 2022-2022 Fuwn <[email protected]> // SPDX-License-Identifier: GPL-3.0-only +use std::{lazy::SyncLazy, sync::Mutex}; + use worker::Cors; use crate::{constants, structures::GitHubAPIResponse}; +static CACHE_UNSET: SyncLazy<Mutex<bool>> = SyncLazy::new(|| Mutex::new(true)); +static CACHE_ACCESS_COUNT: SyncLazy<Mutex<usize>> = + SyncLazy::new(|| Mutex::new(0)); +static GITHUB_API_CACHE: SyncLazy<Mutex<GitHubAPIResponse>> = + SyncLazy::new(|| Mutex::new(GitHubAPIResponse::default())); + /// # Errors /// if GitHub API is unresponsive pub async fn github_api( ) -> Result<GitHubAPIResponse, Box<dyn std::error::Error>> { - let mut client = reqwest::Client::new() - .get(constants::GITHUB_API_ENDPOINT) - .header( - "User-Agent", - format!("senpy-club/api-worker - {}", env!("VERGEN_GIT_SHA")), - ); - - if std::env::var("GITHUB_TOKEN").is_ok() { - client = client.header( - "Authorization", - format!( - "token {}", - std::env::var("GITHUB_TOKEN").unwrap_or_else(|_| "Null".to_string()) - ), - ); - } + if *CACHE_UNSET.lock().unwrap() + || *CACHE_ACCESS_COUNT.lock().unwrap() % 50 == 0 + { + *CACHE_UNSET.lock().unwrap() = false; - Ok( - client + let mut client = reqwest::Client::new() + .get(&*constants::GITHUB_API_ENDPOINT) + .header( + "User-Agent", + format!("senpy-club/api-worker - {}", env!("VERGEN_GIT_SHA")), + ); + + if std::env::var("GITHUB_TOKEN").is_ok() { + client = client.header( + "Authorization", + format!( + "token {}", + std::env::var("GITHUB_TOKEN").unwrap_or_else(|_| "Null".to_string()) + ), + ); + } + + *GITHUB_API_CACHE.lock().unwrap() = client .send() .await? .json::<GitHubAPIResponse>() .await - .unwrap_or_default(), - ) + .unwrap_or_default(); + } + + *CACHE_ACCESS_COUNT.lock().unwrap() += 1; + + Ok((*GITHUB_API_CACHE.lock().unwrap()).clone()) } /// # Panics @@ -79,7 +95,7 @@ pub async fn filter_images_by_language(language: &str) -> Vec<String> { { images.push(format!( "{}{}", - constants::GITHUB_USER_CONTENT, + *constants::GITHUB_USER_CONTENT, // Pound symbols to URL (percent) encoding of pound symbol because we // are pushing a URL, not a string item.path.replace('#', "%23") |