Wednesday, October 29, 2014

Redis & Bedrock

Been playing a bit with Redis, a really cool in-memory database based on keys and values.  It's a key/value database on steroids and has a lot of applicability for web applications that need to scale or just want better performance.

A Perl module is available on CPAN, appropriately named Redis.  One might therefore be tempted to do something like:

<plugin:Redis server localhost:6379>
<null $Redis.set('key', 'value')>

Great idea, however it turns out that didn't work.  Is Bedrock broken? Hmmm...let's find out.

Perl modules like Redis that utilize a large number of AUTOLOAD subroutines and do not implement an appropriate can method are not going to present a code reference when Bedrock's parser calls the module's can method...so as a recognition of this possibility the Func.pm module within Bedrock's parsing does this:

my $funcref;
$funcref = $obj->can($func);
...
if ( $funcref ) {
    @ref_v = $funcref->( $obj, @funcargs );
  }
  else {
    &log_message(
     undef,
     "$self: eval function in case implemented via AUTOLOAD\n\@ref_v = $obj->$func(\@args);"
    );

    eval '@ref_v = $obj->' . $func . '(@args);';

    if ( $@ ) {
      if ( $@ =~/TagX::Scalar/ ) {
  die "attempt to invoke possibly non-existent method ($func) on a possibly non-existent scalar\n";
      }
      else {
        die "$@\n";
      }
    }
  }

Hey, umm...what's that? @args? Shouldn't that be @funcargs? Yup....bug.  Fixed in 2.4.1-snapshot today.  Okay, so anyway...

What can we do with Bedrock and Redis?

Well, generally we can use it as a persistent storage mechanism similar to the way we use the $session object.

<null $Redis.set('foo', 'bar')>

...on one page and then...

<var $Redis.get('foo')>

...on the next...

Of course that example is like saying you can use a brick to prop open a door!  There are lot more interesting and exciting things you can do with Redis.

How about counting page hits from unique IPs?

<null $Redis.pfadd('home-page', $env.REMOTE_ADDR)>

Using Redis' HyperLogLog (requires Redis 2.8.9) facility we can add a member and let Redis keep track of counting unique hits.

<var $Redis.pfcount('home-page')>

Or resetting a counter at midnight by specifying a time value (seconds since the epoch) to the expireat function.

<sqlselect "select unix_timestamp(date_add(curdate(), interval 1 day)) exp">
<null $Redis.expireat('home-page', $exp)></sqlselect>

...and of course we can store serialized data to Redis.

<null $Redis.set('env', $env.json()>

and deserialize it later to a Bedrock object...

<null:user_env --json $Redis.get('env')>

Yup...this is cool!  ;-)

Sunday, October 19, 2014

Pretty Print JSON objects

Added --pretty as an option to the <var> tag for pretty printing JSON objects.  Changes pushed to git master.

<sink><null $header.content_type('application/json')>
<hash:foo red 1 blue 2 green 3>
</sink><var --pretty --json $foo>

...would yield

{
   "green" : "3",
   "blue" : "2",
   "red" : "1"
}

Saturday, October 18, 2014

AWS with Bedrock

I'm starting to tinker with using Amazon's web services from Bedrock pages.  Embedding AWS in Bedrock applications is not new - particularly if you are running Bedrock on an EC2 instance, RDS (hosted MySQL) or you are using Amazon's S3 object storage system.   There are other Amazon web services that are particularly useful in any web development environment, exposing these to Bedrock pages looks interesting.

Plugin Bug

Fixed a bug in the <plugin>  tag.   Class names were not being parsed correctly if there was more that 1 level to the namespace.

For example, Amazon::SNS::VerifySignature was being incorrectly parsed as Amazon::SNS which happens to be valid Perl module.

Fix pushed to master.

Saturday, October 11, 2014

Amazon SNS - Verifying Signatures

While creating a Bedrock example of using Amazon's Simple Notification Service, I was surprised to find that Googling for a Perl example of verifying the signature from an SNS notification message came up empty.  So I wrote my own...