import threading
from typing import Dict, Optional, List
import logging
from olc.config.properties_loader import OlcConfigManager
from olc.bean.olc_config_rule import FlowPolicy, AdmissionPolicy, BasePolicy
from olc.bean.tag_group import TagGroup, SubGroup
from olc.cache.safe__ttl_cache import SafeTTLCache
from olc.utils.str_utils import StrUtils
logger = logging.getLogger(__name__)
class OlcRuleCache:
def __init__(self, domain: str = ""):
self.domain = domain
self.lock = threading.RLock()
self.tag_groups: Dict[str, TagGroup] = {}
self.bind_flow_relation: Dict[str, FlowPolicy] = {}
self.bind_admission_relation: Dict[str, AdmissionPolicy] = {}
max_size = OlcConfigManager.get_instance().get_sdk_config().sub_group_cache_size
self.sub_groups: SafeTTLCache[SubGroup] = SafeTTLCache(maxsize=max_size, ttl=3600)
def __repr__(self):
return (f"OlcRuleCache(domain={self.domain}, "
f"tag_groups={dict(self.tag_groups)}, "
f"flow_policies={dict(self.bind_flow_relation)}, "
f"admission_policies={dict(self.bind_admission_relation)})")
def __str__(self):
return self.__repr__()
def update_all(self, new_olc_rule_cache: Optional["OlcRuleCache"]):
if new_olc_rule_cache is None:
return
try:
with self.lock:
self.tag_groups = dict(new_olc_rule_cache.tag_groups)
self.bind_flow_relation = dict(new_olc_rule_cache.bind_flow_relation)
self.bind_admission_relation = dict(
new_olc_rule_cache.bind_admission_relation
)
except Exception as e:
logging.warning(f"Olc rule cache update failed: {e}")
def add_tag_group(self, tag_groups: Optional[list[TagGroup]]):
if tag_groups is None:
return
with self.lock:
for tag_group in tag_groups:
self.tag_groups[tag_group.name] = tag_group
def add_policy(
self, tag_groups: Optional[list[TagGroup]], policy: Optional[BasePolicy]
):
if tag_groups is None or policy is None:
return
with self.lock:
for tag_group in tag_groups:
if isinstance(policy, FlowPolicy):
self.bind_flow_relation[tag_group.name] = policy
if isinstance(policy, AdmissionPolicy):
self.bind_admission_relation[tag_group.name] = policy
def add_flow_policy(
self, tag_groups: Optional[list[TagGroup]], policy: Optional[FlowPolicy]
):
"""
添加流策略
"""
self.add_policy(tag_groups, policy)
def add_admission_policy(
self, tag_groups: Optional[list[TagGroup]], policy: Optional[AdmissionPolicy]
):
"""
添加准入策略
"""
self.add_policy(tag_groups, policy)
def query_tag_group(self, tag_group_name: str) -> Optional[TagGroup]:
if tag_group_name is None:
return None
with self.lock:
group = self.tag_groups.get(tag_group_name)
if group is None:
group = self.sub_groups.get(tag_group_name)
return group
def add_sub_group(self, sub_group: SubGroup):
if sub_group is None:
return
with self.lock:
self.sub_groups.put(sub_group.name, sub_group)
class OlcRuleManager:
"""
规则管理器
"""
_instance = None
_lock = threading.RLock()
def __init__(self, domain: str = ""):
self.rule_cache: Optional[OlcRuleCache] = OlcRuleCache(domain=domain)
@classmethod
def get_instance(cls) -> "OlcRuleManager":
"""
获取单例实例
"""
if cls._instance is None:
with cls._lock:
if cls._instance is None:
cls._instance = cls()
return cls._instance
def get_rule_cache(self) -> Optional[OlcRuleCache]:
return self.rule_cache
def config_update(self, olc_rule_cache: Optional[OlcRuleCache]):
self.rule_cache.update_all(olc_rule_cache)
def get_group_exclude_sub_group(self) -> Optional[list[TagGroup]]:
if self.rule_cache is not None:
return list(self.rule_cache.tag_groups.values())
return None
def get_flow_policy_by_group_name(self, name: str) -> Optional[FlowPolicy]:
if StrUtils.is_empty(name) or self.rule_cache is None:
return None
return self.rule_cache.bind_flow_relation.get(name, None)
def get_admission_policy_by_group_name(self, name: str) -> Optional[AdmissionPolicy]:
if StrUtils.is_empty(name) or self.rule_cache is None:
return None
return self.rule_cache.bind_admission_relation.get(name, None)
def get_group_from_cache(self, name: str) -> Optional[TagGroup]:
if StrUtils.is_empty(name) or self.rule_cache is None:
return None
return self.rule_cache.query_tag_group(name)
def is_group_policy_dup(self, sub_group: SubGroup) -> bool:
if self.rule_cache is None:
return False
cache = self.get_group_from_cache(sub_group.name)
return cache is not None
def add_sub_group(self, group: SubGroup):
if self.rule_cache is not None:
self.rule_cache.add_sub_group(group)
def refresh_sub_group(self, groups: List[TagGroup]):
"""
刷新子组过期时间,防止过期
"""
if self.rule_cache is not None:
for group in groups:
self.rule_cache.sub_groups.refresh(group.name)