add memory cache for auth index

This commit is contained in:
yggverse 2024-11-16 17:04:43 +02:00
parent 9530c37c59
commit d9bf85884b
5 changed files with 96 additions and 10 deletions

View File

@ -41,13 +41,11 @@ impl Identity {
///
/// https://geminiprotocol.net/docs/protocol-specification.gmi#client-certificates
pub fn gemini(&self, request: &str) -> Option<String> {
if let Ok(auth_records) = self.gemini.auth.database.records(Some(request)) {
for auth_record in auth_records {
if let Ok(gemini_records) = self.gemini.database.records() {
for gemini_record in gemini_records {
if gemini_record.id == auth_record.profile_identity_gemini_id {
return Some(gemini_record.pem);
}
for profile_identity_gemini_id in self.gemini.auth.memory.starts_with(request) {
if let Ok(gemini_records) = self.gemini.database.records() {
for gemini_record in gemini_records {
if gemini_record.id == profile_identity_gemini_id {
return Some(gemini_record.pem);
}
}
}

View File

@ -1,13 +1,16 @@
mod database;
mod memory;
use database::Database;
use memory::Memory;
use sqlite::{Connection, Transaction};
use std::{rc::Rc, sync::RwLock};
/// API for `profile_identity_gemini_id` + `url` auth pairs operations
pub struct Auth {
pub database: Rc<Database>,
// pub database: Rc<Database>,
pub memory: Rc<Memory>,
}
impl Auth {
@ -15,8 +18,31 @@ impl Auth {
/// Create new `Self`
pub fn new(connection: Rc<RwLock<Connection>>) -> Self {
// Init children components
let database = Rc::new(Database::new(connection));
let memory = Rc::new(Memory::new());
// Build initial index
match database.records(None) {
Ok(records) => {
for record in records {
if record.is_active {
if memory
.add(record.url, record.profile_identity_gemini_id)
.is_err()
{
todo!()
}
}
}
}
Err(reason) => todo!("{reason}"),
}
// Return new `Self`
Self {
database: Rc::new(Database::new(connection)),
// database,
memory,
}
}
}

View File

@ -5,6 +5,8 @@ use sqlite::{Connection, Error, Transaction};
pub struct Table {
//pub id: i64,
pub profile_identity_gemini_id: i64,
pub is_active: bool,
pub url: String,
}
/// Storage for `profile_identity_gemini_id` + `url` auth pairs
@ -56,7 +58,9 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
pub fn select(tx: &Transaction, url: Option<&str>) -> Result<Vec<Table>, Error> {
let mut stmt = tx.prepare(
"SELECT `id`,
`profile_identity_gemini_id`
`profile_identity_gemini_id`,
`is_active`,
`url`
FROM `profile_identity_gemini_auth`
WHERE `url` LIKE ?",
@ -66,6 +70,8 @@ pub fn select(tx: &Transaction, url: Option<&str>) -> Result<Vec<Table>, Error>
Ok(Table {
//id: row.get(0)?,
profile_identity_gemini_id: row.get(1)?,
is_active: row.get(2)?,
url: row.get(3)?,
})
})?;

View File

@ -0,0 +1,52 @@
mod error;
use error::Error;
use std::{cell::RefCell, collections::HashMap};
/// Reduce disk usage by cache Auth index in memory
pub struct Memory {
index: RefCell<HashMap<String, i64>>,
}
impl Memory {
// Constructors
/// Create new `Self`
pub fn new() -> Self {
Self {
index: RefCell::new(HashMap::new()),
}
}
// Actions
/// Add new record with `url` as key and `profile_identity_gemini_id` as value
/// * validate record with same key does not exist yet
pub fn add(&self, url: String, profile_identity_gemini_id: i64) -> Result<(), Error> {
match self
.index
.borrow_mut()
.insert(url, profile_identity_gemini_id)
{
Some(_) => Err(Error::Overwrite), // @TODO prevent?
None => Ok(()),
}
}
/* @TODO update feature
/// Cleanup index
pub fn clear(&self, url: &str) {
self.index.borrow_mut().clear()
} */
/// Search for `profile_identity_gemini_id` by `url` starts with given substring
pub fn starts_with(&self, prefix: &str) -> Vec<i64> {
let mut result = Vec::new();
for (url, &profile_identity_gemini_id) in self.index.borrow().iter() {
if url.starts_with(prefix) {
result.push(profile_identity_gemini_id)
}
}
result
}
}

View File

@ -0,0 +1,4 @@
#[derive(Debug)]
pub enum Error {
Overwrite,
}