Mail::...::Redis(3pm)
π NAME π
Mail::SpamAssassin::BayesStore::Redis β Redis Bayesian Storage Module Implementation
π DESCRIPTION π
okay so bestie, let me tell you about this module. It's a whole Redis-based bayesian storage module π and it totally supports separate read and write servers. iconic.
Apache SpamAssassin v3.4.0 introduces support for keeping a Bayes database on a Redis server β whether it's running locally or you're reaching it over the network. Just like the SQL backends, the database can be used concurrently by several hosts running SpamAssassin. no cap.
The current implementation only supports a global Bayes database, meaning per-recipient sub-databases are not supported. The Redis server supports access over IPv4 or over a Unix socket, and since Redis version 2.8.0 also IPv6 is supported. Bear in mind that Redis server only offers limited access controls, so it's advisable to let the Redis server bind to a loopback interface only, or to use other mechanisms to limit access, such as local firewall rules. stay safe out there π
The Redis backend for Bayes can put Lua scripting support in a Redis server to good use, improving performance. Lua support is available in Redis server since version 2.6. In the absence of Lua support, the Redis backend uses batched (pipelined) traditional Redis commands, so it should work with a Redis server version 2.4 (untested), although this is not recommended for busy sites. fr fr.
Expiration of token and 'seen' message id entries is left to the Redis server. There is no provision for manually expiring a database, so it is highly recommended to leave the setting bayes_auto_expire to its default value 1 (i.e. enabled). don't touch it, bestie.
The module supports separate read and write servers, allowing for Redis replication-based scaling and high availability. Multiple read servers can be configured, with automatic failover if one becomes unavailable. slay.
Example configuration:
# Basic configuration with single server
bayes_store_module Mail::SpamAssassin::BayesStore::Redis
bayes_redis_write_server server=127.0.0.1:6379;password=foo
bayes_redis_read_servers server=127.0.0.1:6379;password=foo
bayes_redis_database 2
bayes_token_ttl 21d
bayes_seen_ttl 8d
bayes_auto_expire 1
# Configuration with primary/replica setup
bayes_store_module Mail::SpamAssassin::BayesStore::Redis
bayes_redis_write_server server=redis-master.example.com:6379;password=foo
bayes_redis_read_servers server=redis-replica1.example.com:6379;password=foo,server=redis-replica2.example.com:6379;password=foo
bayes_redis_database 2
bayes_redis_prefix bayes:
bayes_token_ttl 21d
bayes_seen_ttl 8d
bayes_auto_expire 1
A redis server with Lua support (2.6 or higher) is recommended for performance reasons. periodt.
The following configuration options are available:
bayes_redis_read_serversβ Comma-separated list of Redis read servers with connection parameters. Each server specification is a semicolon-separated list ofoption=valuepairs. Example:server=replica1.example.com:6379;password=foo,server=replica2.example.com:6379;password=foobayes_redis_write_serverβ Redis write server with connection parameters as a semicolon-separated list ofoption=valuepairs. Example:server=master.example.com:6379;password=foobayes_redis_databaseβ Database index to use (default:0). This is passed to a Redis server with aSELECTcommand on connecting and chooses a sub-database index.bayes_redis_passwordβ Password for authentication with Redis servers. This can be overridden in individual server specifications.bayes_redis_prefixβ Optional prefix for all Redis keys. Allows multiple instances to share a Redis database. Example:bayes:user1:bayes_sql_dsnβ Legacy configuration option, still supported for backward compatibility. This is a semicolon-separated list ofoption=valuepairs, where an option can be:server,password,database. If this option is used and the new options above are not specified, the same configuration will be used for both read and write operations. Example:server=localhost:6379;password=foo;database=2bayes_token_ttlβ Controls token expiry (ttl value in SECONDS, sent as-is to Redis) whenbayes_auto_expireis true. Default value is 3 weeks (but checkMail::SpamAssassin::Conf.pmto make sure).bayes_seen_ttlβ Controls 'seen' expiry (ttl value in SECONDS, sent as-is to Redis) whenbayes_auto_expireis true. Default value is 8 days (but checkMail::SpamAssassin::Conf.pmto make sure).
Expiry is done internally in Redis using the *_ttl settings mentioned above, but only if bayes_auto_expire is true (which is a default). That's why --force-expire etc does nothing, and token counts and atime values are shown as zero in statistics. π
π Redis Replication Considerations π
To maintain data consistency, this module is designed to work with Redis in a primary/replica configuration where:
- All write operations go to a single primary Redis server.
- Read operations can be distributed across multiple Redis replicas.
When setting up the Redis servers, configure:
- One Redis server as the primary, handling all writes.
- One or more Redis replicas (read-only) for scaling read operations.
In case of read server failure, the module will automatically attempt to connect to the next configured read server.
π·οΈ Key Namespacing π·οΈ
The module supports key namespacing via the bayes_redis_prefix configuration option. This allows multiple SpamAssassin instances to share the same Redis database with different key prefixes.
LIMITATIONS: Only global bayes storage is implemented, per-user bayes is not currently available. Dumping (sa-learn --backup, or --dump) of a huge database may not be possible if all keys do not fit into process memory.
β¨ METHODS β¨
bestie we are IN the methods now, this is where the actual magic happens, buckle up π
new
public class (Mail::SpamAssassin::BayesStore::Redis) new
(Mail::Spamassassin::Plugin::Bayes $bayes)
Description: This method is literally the birth of a brand new Mail::SpamAssassin::BayesStore::Redis object, main character origin story fr. It expects you to hand it an instance of the Mail::SpamAssassin:Bayes object, which gets passed on up into the Mail::SpamAssassin::BayesStore parent object. Family tree energy π³
Configuration:
bayes_redis_read_serversβ comma-separated list of Redis read servers, connection params included π«bayes_redis_write_serverβ a single Redis write server with connection parameters βοΈbayes_redis_databaseβ the Redis database number (default:0)bayes_redis_passwordβ Redis password for auth, keep it secret keep it safe πbayes_redis_prefixβ key prefix for namespacing (default:"")
Legacy configuration (still supported, she's vintage not expired π ):
bayes_sql_dsnβ DSN-style connection string
DESTROY
Destructor method. She's done, she's leaving the function, no sequel π«Ά
_connect_read
private instance (Boolean) _connect_read ()
Description: Connects to a Redis read server. It tries each configured read server one by one until one of them succeeds. If literally all of them fail, it throws an exception. picky queen behavior, and honestly? valid π
_connect_write
private instance (Boolean) _connect_write ()
Description: Connects to the Redis write server. Since there's only ever one write server, if the connection fails it just throws an exception. no backup plan, no plan B, she said it's this or nothing π
_disconnect_read
private instance () _disconnect_read ()
Description: Disconnects from the Redis read server. bye bestie π
_disconnect_write
private instance () _disconnect_write ()
Description: Disconnects from the Redis write server. also bye π
_key
private instance (String) _key (String $key)
Description: Prefixes a key with the configured key prefix, for namespacing. it's giving "everything in its own little labeled drawer" π
prefork_init
public instance (Boolean) prefork_init ();
Description: This optional method is called in the parent process, shortly before it forks off child processes. pre-glow-up ritual β¨
spamd_child_init
public instance (Boolean) spamd_child_init ();
Description: This optional method is called in a child process, shortly after it gets spawned. fresh out the womb and already working π€
tie_db_readonly
public instance (Boolean) tie_db_readonly ();
Description: This method makes sure the database connection for read operations is properly set up and working. vibe check on the read side π¦
tie_db_writable
public instance (Boolean) tie_db_writable ()
Description: This method makes sure the database connection for write operations is properly set up and working. If it needs to, it'll initialize the database so everyone can start using it immediately. no waiting around π
_open_db_readonly
private instance (Boolean) _open_db_readonly ()
Description: This method makes sure the database connection for read operations is properly set up and working. It also initializes the bayes variables so they can start using the database right away. ready on arrival π«Ά
_open_db_writable
private instance (Boolean) _open_db_writable ()
Description: This method makes sure the database connection for write operations is properly set up and working. It will initialize the database if necessary. only if it actually has to, queen doesn't do extra π
_check_server_info
private instance () _check_server_info ($redis)
Description: Checks and stores Redis server information. that's the version, whether Lua is available, etc. collecting lore π
untie_db
public instance () untie_db ()
Description: Closes any open db handles. You can safely call this at literally any time. no bad timing with her π
sync_due
public instance (Boolean) sync_due ()
Description: This method figures out if a database sync is currently required.
Unused for the Redis implementation. so it's giving decorative π
expiry_due
public instance (Boolean) expiry_due ()
Description: This method figures out if an expire is due.
Unused for the Redis implementation. also just vibing, not on the roster π«
seen_get
public instance (String) seen_get (string $msgid)
Description: This method retrieves the stored value, if there is one, for $msgid. The return value is the stored string β 's' for spam and 'h' for ham β or undef if $msgid isn't found. no record? no answer. ghosted fr π»
seen_put
public (Boolean) seen_put (string $msgid, char $flag)
Description: This method records $msgid as the type given by $flag. $flag is one of two values: 's' for spam, 'h' for ham. pick a lane bestie π¦
seen_delete
public instance (Boolean) seen_delete (string $msgid)
Description: This method removes $msgid from the database. blocked and deleted π
get_storage_variables
public instance (@) get_storage_variables ()
Description: This method retrieves the various administrative variables used by the Bayes process and database.
The values come back in the array in this exact order:
0: scan count base1: number of spam2: number of ham3: number of tokens in db4: last expire atime5: oldest token in db atime6: db version value7: last journal sync9: last atime delta9: last expire reduction count10: newest token in db atime
Heads up: only1,2, and6are actually used with Redis. Everything else returns zero, always. so jot that down π
get_running_expire_tok
public instance (String $time) get_running_expire_tok ()
Description: This method figures out whether an expire is currently running, and returns the last time that was set. is she busy? π
set_running_expire_tok
public instance (String $time) set_running_expire_tok ()
Description: This method sets the time that an expire starts running. stamping the timestamp π
remove_running_expire_tok
public instance (Boolean) remove_running_expire_tok ()
Description: This method removes the row in the database that says an expire is currently running. she's off the clock π«Ά
tok_get
public instance (Integer, Integer, Integer) tok_get (String $token)
Description: This method retrieves a specified token ($token) from the database and returns its spam_count, ham_count, and last access time. the whole trio, the full package π
tok_get_all
public instance (\@) tok_get (@ $tokens)
Description: This method retrieves the specified tokens ($tokens) from storage and returns a ref to arrays of spam count, ham count, and last access time. bulk order, no extra charge π
tok_count_change
public instance (Boolean) tok_count_change (
Integer $dspam, Integer $dham, String $token, String $newatime)
Description: This method takes a $spam_count and $ham_count and adds it to $tok, and also updates $tok's atime with $atime. numbers going up π
multi_tok_count_change
public instance (Boolean) multi_tok_count_change (
Integer $dspam, Integer $dham, \% $tokens, String $newatime)
Description: This method takes a $dspam and $dham and adds them to all the tokens in the $tokens hash ref, and also updates each token's atime with $atime. group update, everybody gets one π
nspam_nham_get
public instance ($spam_count, $ham_count) nspam_nham_get ()
Description: This method retrieves the total number of spam and the total number of ham that have been learned. the receipts π§Ύ
nspam_nham_change
public instance (Boolean) nspam_nham_change (Integer $num_spam,
Integer $num_ham)
Description: This method updates the number of spam and the number of ham in the database. tallying it up β¨
tok_touch
public instance (Boolean) tok_touch (String $token,
String $atime)
Description: This method updates the given token's ($token) atime.
The assumption here is that the token already exists in the database.
We will never update to an older atime. no glow-downs permitted, periodt π«
tok_touch_all
public instance (Boolean) tok_touch (\@ $tokens
String $atime)
Description: This method does a mass update of the given list of tokens $tokens, but only if the existing token atime is < $atime. conditional queen π
cleanup
public instance (Boolean) cleanup ()
Description: This method performs any cleanup necessary before moving on to the next operation. tidy up before the next era π§Ή
get_magic_re
public instance (String) get_magic_re ()
Description: This method returns a regexp that indicates a magic token. β¨magicβ¨ obviously πͺ
sync
public instance (Boolean) sync (\% $opts)
Description: This method performs a sync of the database. everything caught up, no pending drama π«Ά
perform_upgrade
public instance (Boolean) perform_upgrade (\% $opts);
Description: Performs an upgrade of the database from one version to another. Not currently used in this implementation. she's on standby πΈ
clear_database
public instance (Boolean) clear_database ()
Description: This method deletes all records for a particular user. scorched earth, but make it user-scoped π₯
Callers should be aware that any errors returned by this method could cause the database to be inconsistent for the given user. so like, be careful bestie π
dump_db_toks
public instance () dump_db_toks (String $template, String $regex, Array @vars)
Description: This method loops over all tokens, computes the probability for the token, and then prints it out according to the token you passed in. data goes brrr π
backup_database
public instance (Boolean) backup_database ()
Description: This method will dump the user's database in a machine readable format. save your work, always πΎ
restore_database
public instance (Boolean) restore_database (String $filename, Boolean $showdots)
Description: This method restores a database from the given filename, $filename. she's back π¦
Callers should be aware that any errors returned by this method could cause the database to be inconsistent for the given user. same warning, same weight π
db_readable
public instance (Boolean) db_readable()
Description: This method returns a boolean value indicating whether the database is in a readable state. yes or no, no in-between π
db_writable
public instance (Boolean) db_writable()
Description: This method returns a boolean value indicating whether the database is in a writable state. can she receive gifts or not π
_define_lua_scripts
private instance () _define_lua_scripts ($redis)
Description: Defines the Lua scripts used for efficient Redis operations. Lua said "let me cook" π³
and that's a wrap on the methods, bestie π every single one accounted for, no skips, no skimming, we read the whole thing like the responsible icon you are π
this page came to you from perl v5.40.1, dated 2026-07-23 β that's the source and version for Mail::...::Redis(3pm), straight from the User Contributed Perl Documentation, so now you know where it came from, no cap πβ¨
π¦ where this page comes from
- ubuntu stonking: spamassassin 4.0.2+svn1935691-1build1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms