Akka 2.0 actors with Kafka backed durable mailboxes
Another quick hack I put together the other day was Akka 2.0 actors that use Kafka for durable mailboxes. It was more a learning exercise about implementing durable actor mailboxes for Akka than anything else. Perhaps I'll put it to use one day soon.
The gist is here:
mod_msg_filter - block/allow message delivery over HTTP for ejabberd
One of the requirements we have for our chat service where I work is the ability to decide whether users are allowed to chat based on business logic that we execute in our permission system. This means that we need to ask the permissions system every time people start to exchange messages. To that effect we've implemented modmsgfilter and figured we'd share it in case anyone else on the list has similar use cases.
Here's the blurb:
mod_msg_filter allows the filtering of "message" stanzas across an HTTP service. The URL of the service must be passed as part of the module's configuration. Both JIDs and their resources are passed as part of the query string and the result is expected to be one of: <status value="denied"> <stanza1><error/></stanza1> <stanza2><error/></stanza2> </status> or: <status value="allowed"> <stanza1><noop/></stanza1> <stanza2><noop/></stanza2> </status> The values of thetags or tags will be cached in mnesia using 2 keys that look like: {bare_jid1, bare_jid2, resource1, resource2} {bare_jid2, bare_jid1, resource2, resource1} The tags will then be sent over to both JIDs if the has a "value" of "denied", otherwise the original message is let through. The mnesia cache can be flushed if the ejabberd server is hit on a request handler that maps to this module (for example: /mod_msg_filter/). A stanza must be POSTed that looks like: <flush jid="user@domain.com"/> Note that no resource is included at all. This can be used if ejabberd is part of a system that has billing restrictions on chatting but allows presence to go through all the time.
And you can find the code here:
Mate1's activity feed: Cassandra, Kafka, Netty, Varnish
Guzzler with pattern based routing 2
Guzzler now publishes binlogs and allows pattern based subscriptions using "dbName.tableName.opName" with wild-card support.
dbName is the database, tableName is the table being acted upon and opName is one of update, insert, or delete. Wild cards are also supported.
Guzzler: Stream MySQL binary logs and consume them with Scala actors and RabbitMQ. 1
Guzzler allows you to stream MySQL binary logs from a master and lets you act on them using Scala actors (consumers). Consumers are configurable in guzzler.conf along with the rest of the required parameters. Included with Guzzler is a dummy consumer and a RabbitMQ one that will push queries into a RabbitMQ server for consumption.
Consumers either in Guzzler itself of behind RabbitMQ can analyze the queries (Guzzler provides an SQL query parser based on ZQL) and may decide to update counters, fire off events, log messages, etc.
https://github.com/mardambey/guzzler
Desktop at home
Shrink, Spiffy, Scala! 2
Been writing some Scala code, its fun, and one hell of a fantastic language. You should take a look at it some time.
Happy new year! 37
Quick graphs with Perl / GD::Graph 34
So I had to quickly whip up some graphs today at work based on values coming in from one of our database tables. Nothing better then Perl and GD (GD::Graph) for a quick and effective solution.
use strict;
use DBI;
use GD::Graph::bars;
use GD::Graph::Data;
my $db_host = 'XXXXXX';
my $db_name = 'XXXXXX';
my $db_user = 'XXXXXX';
my $db_pass = 'XXXXXX';
my $query = "select month, undelivered from XXXXX where XXXXX";
# create labels and values for x-axis
my ($labels, $values) = get_data_from_sql($db_host, $db_name, $db_user, $db_pass, $query);
# graph and save the output
graph($labels, $values, "Month", "Undelivered", "Undelivered Messages by Month", "undelivered.png");
sub get_data_from_sql($$$$$)
{
my ($db_host, $db_name, $db_user, $db_pass, $query) = @_;
my $dbh = DBI->connect("dbi:mysql:$db_name:$db_host", $db_user, $db_pass)
or die "Couldn't connect to database: " . DBI->errstr;
my $sth = $dbh->prepare($query)
or die "Couldn't prepare statement: " . $dbh->errstr;
$sth->execute();
my @row= undef;
my @labels = ();
my @values = ();
while (@row = $sth->fetchrow_array())
{
push @labels, $row[0];
push @values, $row[1];
}
$dbh->disconnect;
return (\@labels, \@values);
}
sub graph($$$$$$)
{
my ($labels, $values, $x_label, $y_label, $title, $out_file) = @_;
my $data = GD::Graph::Data->new([$labels, $values,])
or die GD::Graph::Data->error;
my $my_graph = GD::Graph::bars->new();
$my_graph->set(
x_label => $x_label,
y_label => $y_label,
title => $title,
bar_spacing => 8,
shadow_depth => 4,
shadowclr => 'dred',
transparent => 0,
)
or warn $my_graph->error;
$my_graph->plot($data) or die $my_graph->error;
my $gd = $my_graph->plot($data) or die $my_graph->error;
open(IMG, ">$out_file") or die $!;
binmode IMG;
print IMG $gd->png;
}
If you do not want your data coming from an SQL statement simply fill in $labels and $values with anything you want, like:
$labels = ['Monday', 'Tuesday', 'Wednesday'];
$data = [45, 66, 89];
Pretty straight forward and handy. the graph looks like this.