ratchjob 0.2.1

一个rust实现的分布式任务调度平台服务。计划完全兼容xxl-job协议,然后再增强一些任务调度平台能力。
Documentation
use crate::app::model::AppKey;
use crate::common::model::privilege::PrivilegeGroup;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet};
use std::sync::Arc;

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct AppQueryParam {
    pub namespace: Option<Arc<String>>,
    pub app_name: Option<Arc<String>>,
    pub like_name: Option<String>,
    pub namespace_privilege: PrivilegeGroup<Arc<String>>,
    pub app_privilege: PrivilegeGroup<Arc<String>>,
    pub offset: usize,
    pub limit: usize,
}

impl AppQueryParam {
    pub fn match_namespace(&self, value: &Arc<String>) -> bool {
        if !self.namespace_privilege.check_permission(&value) {
            return false;
        }
        if let Some(namespace) = &self.namespace {
            namespace.is_empty() || namespace == value
        } else {
            true
        }
    }

    pub fn match_app_name(&self, value: &Arc<String>) -> bool {
        if !self.app_privilege.check_permission(&value) {
            return false;
        }
        if let Some(app_name) = &self.app_name {
            app_name.is_empty() || app_name == value
        } else if let Some(like_name) = &self.like_name {
            like_name.is_empty() || value.contains(like_name)
        } else {
            true
        }
    }
}

#[derive(Debug, Clone, Default)]
pub struct AppIndex {
    pub(crate) group_data: BTreeMap<Arc<String>, BTreeSet<Arc<String>>>,
}

impl AppIndex {
    pub(crate) fn new() -> Self {
        Default::default()
    }

    pub(crate) fn insert(&mut self, namespace: Arc<String>, app_name: Arc<String>) -> bool {
        if let Some(group_set) = self.group_data.get_mut(&namespace) {
            group_set.insert(app_name)
        } else {
            let mut group_set = BTreeSet::new();
            group_set.insert(app_name);
            self.group_data.insert(namespace, group_set);
            true
        }
    }

    #[allow(dead_code)]
    pub(crate) fn remove(
        &mut self,
        namespace: &Arc<String>,
        app_name: &Arc<String>,
    ) -> (bool, usize) {
        if let Some(group_set) = self.group_data.get_mut(namespace) {
            let b = group_set.remove(app_name);
            if b && group_set.is_empty() {
                self.group_data.remove(namespace);
            }
            (b, self.group_data.len())
        } else {
            (false, self.group_data.len())
        }
    }

    pub fn query(&self, param: &AppQueryParam) -> (usize, Vec<AppKey>) {
        let mut rlist = Vec::new();
        let end_index = param.offset + param.limit;
        let mut index = 0;
        for (namespace, group_set) in self.group_data.iter() {
            if param.match_namespace(namespace) {
                for app_name in group_set.iter() {
                    if param.match_app_name(app_name) {
                        if index >= param.offset && index < end_index {
                            rlist.push(AppKey::new(app_name.clone(), namespace.clone()));
                        }
                        index += 1;
                    }
                }
            }
        }
        (index, rlist)
    }

    pub fn get_namespace_count(&self) -> usize {
        self.group_data.len()
    }

    pub fn get_item_count(&self) -> usize {
        self.group_data.values().map(|set| set.len()).sum()
    }
}