Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

74 рядки
2.2 KiB

  1. use std::collections::HashMap;
  2. use parking_lot::RwLock;
  3. use r2d2::{Pool, PooledConnection};
  4. use redis::Client;
  5. use crate::models::{TrackerInfo, TrackerRedisInfo};
  6. fn pool_from_redisinfo(info: &TrackerRedisInfo) -> color_eyre::Result<Pool<Client>> {
  7. let url = if let Some(pass) = &info.pass {
  8. format!("redis://:{}@{}:{}", pass, info.host, info.port)
  9. } else {
  10. format!("redis://{}:{}", info.host, info.port)
  11. };
  12. let new_client = Client::open(url)?;
  13. let max_pool_size = std::env::var("MAX_REDIS_POOL_SIZE")
  14. .unwrap_or_else(|_| "32".to_string())
  15. .parse()
  16. .unwrap_or(32);
  17. let pool = Pool::builder()
  18. .max_size(max_pool_size)
  19. .build(new_client)?;
  20. Ok(pool)
  21. }
  22. pub type RedisConnection = PooledConnection<Client>;
  23. pub struct ClientManager {
  24. client_map: RwLock<HashMap<TrackerRedisInfo, Pool<Client>>>,
  25. master_redis_info: TrackerRedisInfo,
  26. }
  27. impl ClientManager {
  28. pub fn new(master_redis_info: TrackerRedisInfo) -> Self {
  29. Self {
  30. client_map: RwLock::new(HashMap::new()),
  31. master_redis_info,
  32. }
  33. }
  34. pub fn get_connection_from_tracker(&self, info: &TrackerInfo) -> color_eyre::Result<RedisConnection> {
  35. if let Some(redis) = &info.redis {
  36. self.get_connection(redis)
  37. } else {
  38. self.get_master_connection()
  39. }
  40. }
  41. pub fn get_master_connection(&self) -> color_eyre::Result<RedisConnection> {
  42. self.get_connection(&self.master_redis_info)
  43. }
  44. pub fn get_connection(&self, info: &TrackerRedisInfo) -> color_eyre::Result<RedisConnection> {
  45. let d = self.client_map.read();
  46. if let Some(client) = d.get(info) {
  47. let con = client.get()?;
  48. Ok(con)
  49. } else {
  50. drop(d);
  51. let mut d = self.client_map.write();
  52. if let Some(client) = d.get(info) {
  53. let con = client.get()?;
  54. Ok(con)
  55. } else {
  56. let new_client = pool_from_redisinfo(info)?;
  57. let con = new_client.get()?;
  58. d.insert(info.clone(), new_client);
  59. Ok(con)
  60. }
  61. }
  62. }
  63. }