Algorithm-EventsPerSecond
view release on metacpan or search on metacpan
src_bin/iqbi-damiq view on Meta::CPAN
#!/usr/bin/env perl
#
# iqbi-damiq - launcher for Algorithm::EventsPerSecond::Sukkal
use 5.006;
use strict;
use warnings;
use Getopt::Long qw(GetOptions);
use Pod::Usage qw(pod2usage);
use Algorithm::EventsPerSecond;
use Algorithm::EventsPerSecond::Sukkal;
my (
$socket, $window, $max_keys, $max_key_length, $idle_timeout, $sweep_interval,
$max_clients, $mode, $daemonize, $pidfile, $require_xs,
);
GetOptions(
'socket|s=s' => \$socket,
'require-xs|x' => \$require_xs,
'window|w=i' => \$window,
'max-keys=i' => \$max_keys,
'max-key-length=i' => \$max_key_length,
'idle-timeout=i' => \$idle_timeout,
'sweep-interval=i' => \$sweep_interval,
'max-clients=i' => \$max_clients,
'mode|m=s' => \$mode,
'daemonize|d' => \$daemonize,
'pidfile|p=s' => \$pidfile,
'help|h' => sub { pod2usage( -exitval => 0, -verbose => 1 ) },
'version|v' => sub {
print "iqbi-damiq (Algorithm::EventsPerSecond::Sukkal) " . "$Algorithm::EventsPerSecond::Sukkal::VERSION\n";
exit 0;
},
) or pod2usage( -exitval => 2 );
pod2usage( -exitval => 2, -message => "iqbi-damiq: --socket is required\n" )
unless defined $socket;
die "iqbi-damiq: --require-xs given but the " . Algorithm::EventsPerSecond->backend . " backend is loaded, not XS\n"
if $require_xs && Algorithm::EventsPerSecond->backend ne 'XS';
my $sukkal = Algorithm::EventsPerSecond::Sukkal->new(
socket => $socket,
( defined $window ? ( window => $window ) : () ),
( defined $max_keys ? ( max_keys => $max_keys ) : () ),
( defined $max_key_length ? ( max_key_length => $max_key_length ) : () ),
( defined $idle_timeout ? ( idle_timeout => $idle_timeout ) : () ),
( defined $sweep_interval ? ( sweep_interval => $sweep_interval ) : () ),
( defined $max_clients ? ( max_clients => $max_clients ) : () ),
( defined $mode ? ( socket_mode => $mode ) : () ),
);
if ($daemonize) {
require POSIX;
defined( my $pid = fork ) or die "iqbi-damiq: cannot fork: $!\n";
exit 0 if $pid;
POSIX::setsid() != -1 or die "iqbi-damiq: setsid failed: $!\n";
defined( $pid = fork ) or die "iqbi-damiq: cannot fork: $!\n";
exit 0 if $pid;
chdir '/';
open STDIN, '<', '/dev/null';
open STDOUT, '>', '/dev/null';
open STDERR, '>', '/dev/null';
} ## end if ($daemonize)
my $pidfile_owner;
if ( defined $pidfile ) {
open my $fh, '>', $pidfile
or die "iqbi-damiq: cannot write pidfile $pidfile: $!\n";
print $fh "$$\n";
close $fh;
$pidfile_owner = $$;
}
END {
unlink $pidfile
if defined $pidfile && defined $pidfile_owner && $$ == $pidfile_owner;
}
$SIG{INT} = $SIG{TERM} = sub { $sukkal->stop };
$SIG{HUP} = 'IGNORE';
printf "iqbi-damiq: serving %s (window=%ds, backend=%s)\n",
$socket, $sukkal->{window}, Algorithm::EventsPerSecond->backend
unless $daemonize;
$sukkal->run;
print "iqbi-damiq: shut down\n" unless $daemonize;
exit 0;
__END__
=head1 NAME
iqbi-damiq - a unix-socket daemon tracking per-key event rates
=head1 SYNOPSIS
iqbi-damiq -s <socket> [options]
iqbi-damiq -s /var/run/iqbi-damiq.sock
iqbi-damiq -s /var/run/iqbi-damiq.sock -w 300 --max-keys 500000
iqbi-damiq -s /var/run/iqbi-damiq.sock -d -p /var/run/iqbi-damiq.pid
=head1 DESCRIPTION
iqbi-damiq ("She said 'it is fine!'") runs a
L<Algorithm::EventsPerSecond::Sukkal> daemon: clients connect to the
unix socket, mark events against keys of their choosing, and query the
sliding-window rate, in-window count, and lifetime total per key. See
L<Algorithm::EventsPerSecond::Sukkal/PROTOCOL> for the line protocol.
A quick poke with socat:
printf 'MARK requests 5\nRATE requests\nQUIT\n' \
| socat - UNIX:/var/run/iqbi-damiq.sock
Or C<MARKRATE> to mark and read the rate back in a single command:
printf 'MARKRATE requests 5\nQUIT\n' \
| socat - UNIX:/var/run/iqbi-damiq.sock
By default the daemon stays in the foreground, which suits systemd and
similar supervisors; C<-d> for classic double-fork daemonization.
=head1 OPTIONS
=over 4
=item -s, --socket PATH
Unix socket path to listen on. Required.
=item -w, --window SECONDS
Averaging window used for every meter. Default 60.
=item --max-keys N
Maximum distinct keys tracked at once; 0 for unlimited. Default
100000.
=item --max-key-length N
Maximum key length in bytes. Default 255.
=item --idle-timeout SECONDS
Evict keys unmarked for this long; must be at least the window.
Default is twice the window.
=item --sweep-interval SECONDS
Seconds between eviction sweeps. Default 30.
=item --max-clients N
Maximum simultaneous client connections; 0 for unlimited, the
default.
=item -m, --mode OCTAL
Permissions for the socket file, e.g. C<0770>. Default is whatever
the umask allows.
=item -x, --require-xs
Refuse to start unless the XS backend of
L<Algorithm::EventsPerSecond> is loaded, rather than silently falling
back to pure Perl. For hosts where the pure-Perl backend's speed or
L<memory use|Algorithm::EventsPerSecond::Sukkal/MEMORY USAGE> is not
acceptable.
=item -d, --daemonize
Detach from the terminal: double-fork, setsid, chdir to /, and point
std streams at /dev/null.
=item -p, --pidfile PATH
Write the daemon PID here after any daemonization; removed on exit.
=item -h, --help
Show usage and options.
=item -v, --version
Show the version.
=back
=head1 SIGNALS
SIGTERM and SIGINT shut the daemon down cleanly, closing clients and
unlinking the socket. SIGHUP is ignored.
=head1 AUTHOR
Zane C. Bowers-Hadley, C<< <vvelox at vvelox.net> >>
=head1 LICENSE AND COPYRIGHT
This software is Copyright (c) 2026 by Zane C. Bowers-Hadley.
( run in 0.768 second using v1.01-cache-2.11-cpan-995e09ba956 )