1use super::{Error, get_str_conf};
16use dashmap::DashMap;
17use pingap_config::PluginConf;
18use pingap_core::Plugin;
19use std::sync::Arc;
20use std::sync::LazyLock;
21
22type Result<T, E = Error> = std::result::Result<T, E>;
23
24type NewPlugin = dyn Fn(&PluginConf) -> Result<Arc<dyn Plugin>> + Send + Sync;
25
26pub struct PluginFactory {
28 plugins: DashMap<String, Arc<NewPlugin>>,
29}
30
31impl PluginFactory {
32 pub fn new() -> Self {
33 Self {
34 plugins: DashMap::new(),
35 }
36 }
37
38 pub fn supported_plugins(&self) -> Vec<String> {
39 let mut plugins = self
40 .plugins
41 .iter()
42 .map(|item| item.key().clone())
43 .collect::<Vec<String>>();
44 plugins.sort();
45 plugins
46 }
47
48 pub fn register<F>(&self, category: &str, creator: F)
50 where
51 F: Fn(&PluginConf) -> Result<Arc<dyn Plugin>> + Send + Sync + 'static,
52 {
53 self.plugins.insert(category.to_string(), Arc::new(creator));
54 }
55
56 pub fn create(&self, conf: &PluginConf) -> Result<Arc<dyn Plugin>> {
58 let category = get_str_conf(conf, "category");
59 if category.is_empty() {
60 return Err(Error::NotFound {
61 category: "unknown".to_string(),
62 });
63 }
64
65 self.plugins
66 .get(&category)
67 .ok_or(Error::NotFound {
68 category: category.to_string(),
69 })
70 .and_then(|creator| creator(conf))
71 }
72}
73
74impl Default for PluginFactory {
75 fn default() -> Self {
76 Self::new()
77 }
78}
79
80static PLUGIN_FACTORY: LazyLock<PluginFactory> =
81 LazyLock::new(PluginFactory::new);
82
83pub fn get_plugin_factory() -> &'static PluginFactory {
84 &PLUGIN_FACTORY
85}