diff --git a/Cargo.toml b/Cargo.toml --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,7 @@ tower = { version = "0.5.1", features = ["limit", "timeout", "tokio", "tracing"] } tracing-subscriber = { version = "0.3.18", features = ["env-filter", "chrono", "json"] } tracing = { version = "0.1.40", features = ["async-await", "log", "valuable"] } zstd = "0.13.2" +regex = "1.11.1" reqwest = { version = "0.12.9", features = ["json", "zstd", "rustls-tls"] } rhai = { version = "1.20.0", features = ["serde", "std", "sync"]} duration-str = "0.11.2" diff --git a/src/matcher.rs b/src/matcher.rs --- a/src/matcher.rs +++ b/src/matcher.rs @@ -6,7 +6,13 @@ use rhai::{ serde::to_dynamic, Array, CustomType, Dynamic, Engine, ImmutableString, Scope, TypeBuilder, AST, }; -use std::{collections::HashMap, path::PathBuf, str::FromStr}; +use regex::Regex; +use std::{ + collections::HashMap, + path::PathBuf, + str::FromStr, + sync::{Mutex, OnceLock}, +}; use crate::config; @@ -315,6 +321,33 @@ .collect::>(); sequence_matches(sequence.as_ref(), &text) } +pub fn matcher_matches(text: ImmutableString, pattern: ImmutableString) -> bool { + static CACHE: OnceLock>> = OnceLock::new(); + let cache = CACHE.get_or_init(|| Mutex::new(HashMap::new())); + + let mut cache = match cache.lock() { + Ok(cache) => cache, + Err(err) => { + tracing::warn!(error = ?err, "regex cache lock poisoned"); + return false; + } + }; + + if !cache.contains_key(pattern.as_str()) { + match Regex::new(&pattern) { + Ok(regex) => { + cache.insert(pattern.to_string(), regex); + } + Err(err) => { + tracing::warn!(error = ?err, pattern = %pattern, "error compiling regex"); + return false; + } + } + } + + cache[pattern.as_str()].is_match(&text) +} + fn sequence_matches(sequence: &[String], text: &str) -> bool { let mut last_found: i32 = -1; @@ -419,6 +452,7 @@ engine .build_type::() .register_fn("build_aturi", build_aturi) .register_fn("sequence_matches", matcher_sequence_matches) + .register_fn("matches", matcher_matches) .register_fn("matcher_before_duration", matcher_before_duration) .register_fn("update_match", Match::update) .register_fn("upsert_match", Match::upsert);