[Feature] Add inverted index for composites optimization
Build an inverted index mapping symbol names to composites that contain
those symbols as positive (non-negated) atoms. This allows filtering out
composites that cannot possibly match during the first pass evaluation.
- Add rspamd_expression_atom_foreach_ex() to traverse expression atoms
with access to AST nodes (needed to detect negated atoms)
- Add rspamd_expression_node_is_op() to check if a node is an operator
- Build inverted index in composites_manager during config processing
- Track composites with only negated atoms separately (they must always
be evaluated)
- Use inverted index in composites_metric_callback for first pass to
evaluate only potentially matching composites
For configurations with many composites (4000+), this reduces the number
of composites evaluated per message from all to only those that have at
least one matching symbol present.