Skip to content

Instantly share code, notes, and snippets.

@DrJackilD
Last active October 10, 2023 20:17
Show Gist options
  • Save DrJackilD/99bbea0c66332aadd8c13b1bf61a6a7f to your computer and use it in GitHub Desktop.
Save DrJackilD/99bbea0c66332aadd8c13b1bf61a6a7f to your computer and use it in GitHub Desktop.
use anyhow::Result;
use redis::Commands;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::fmt::Formatter;
use std::str::FromStr;
const COORDINATE_PRECISION: usize = 4;
const CACHE_TTL: usize = 2628000;
#[derive(Debug, Default, Serialize, Deserialize)]
struct Address {
street: Option<String>,
street_number: Option<String>,
postal_code: Option<String>,
city: Option<String>,
country: Option<String>,
venue_name: Option<String>,
formatted_address: Option<String>,
}
#[derive(strum_macros::EnumString, strum_macros::Display)]
enum Locale {
#[strum(serialize = "de-DE")]
DeDe,
#[strum(serialize = "en-GB")]
EnGb,
#[strum(serialize = "en-US")]
EnUs,
#[strum(serialize = "fr-FR")]
FrFr,
}
impl Default for Locale {
fn default() -> Self {
Self::DeDe
}
}
struct Latitude(f64);
struct Longitude(f64);
struct AddressKey {
lat: Latitude,
lng: Longitude,
locale: Locale,
}
impl fmt::Display for AddressKey {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"{:.COORDINATE_PRECISION$},{:.COORDINATE_PRECISION$},{},opencage",
self.lat.0, self.lng.0, self.locale
)
}
}
trait AddressCache {
fn get(&mut self, key: &AddressKey) -> Result<Option<Address>>;
fn store(&mut self, key: &AddressKey, address: Address) -> Result<()>;
fn remove(&mut self, key: &AddressKey) -> Result<()>;
}
struct RedisCache {
conn: redis::Connection,
}
impl RedisCache {
fn new(address: &str) -> Result<Self> {
let client = redis::Client::open(address)?;
let connection = client.get_connection()?;
Ok(Self { conn: connection })
}
}
impl AddressCache for RedisCache {
fn get(&mut self, key: &AddressKey) -> Result<Option<Address>> {
let result: Option<String> = self.conn.get(key.to_string())?;
Ok(result.map(|addr| serde_json::from_str::<Address>(&addr).unwrap()))
}
fn store(&mut self, key: &AddressKey, address: Address) -> Result<()> {
self.conn.set_ex(
key.to_string(),
serde_json::to_string(&address).unwrap(),
CACHE_TTL,
)?;
Ok(())
}
fn remove(&mut self, key: &AddressKey) -> Result<()> {
self.conn.del(key.to_string())?;
Ok(())
}
}
fn main() -> Result<()> {
// Output:
// de-DE
// 53.4970,10.0998,de-DE,opencage
// {
// "street": "Street",
// "street_number": null,
// "postal_code": null,
// "city": null,
// "country": null,
// "venue_name": null,
// "formatted_address": null
// }
// None
let locale = Locale::from_str("un-KN").unwrap_or_default();
let key = AddressKey {
lat: Latitude(53.49703),
lng: Longitude(10.09985),
locale: Default::default(),
};
let address = Address {
street: Some(String::from_str("Street")?),
..Default::default()
};
let mut cache = RedisCache::new("redis://localhost:6379/2")?;
println!("{}", locale);
println!("{}", key);
cache.store(&key, address)?;
let address_from_cache = cache.get(&key);
println!(
"{}",
serde_json::to_string_pretty(&address_from_cache?.unwrap_or(Address::default()))?
);
cache.remove(&key)?;
println!("{:?}", cache.get(&key)?);
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment