February 2013 Archives

Please build this for me, yesterday, also!

use Port::Authority;

Port::Authority would be a module which assigns and tracks ports for use with multiple application servers running on the same box. It would need an algorithm, capable of generating reproducible results, to generate port numbers in which are available, maybe it could be based on a namespace or random string + current user (etc), or maybe you could be able to specify the type of algorithm (e.g. UUID).

I need this yesterday for a variety of reason, what do you guys think?

Please build this for me, yesterday!

#!/usr/bin/env perl

=head1 NAME

App-sourcery

=head1 USAGE

# loads all @assets within $path and reports any not referenced in at-least one of the @sources
./sourcery --path=/var/www --asset=*.css --asset=*.js --asset=*.png --source=*.html

=head1 DESCRIPTION

Often times I'll find myself mucking around with an old webapp codebase that has had assets (css, js, images, etc) added to it over and over throughout its life, and being the neat-freak that I am I like to keep my codebase clean.

This (potentially) is a program that f…

The Power of the Sun, in the Palm of your Hand

Over the weekend I worked on a new Perl library, MongoDB::QueryBuilder, a tool which is designed to simplify composing complex and dynamic queries for MongoDB in a chainable and object-oriented fashion.

Seldomly do we see examples of querying a MongoDB datastore of significant size and complexity, however, as your application grows and your data evolves, the questions you’ll want to ask your datastore will become more intricate.

For example. Let’s suppose we have an inventory management application that tracks equipment used in our business. Over time the business grows as does the database and (for whatever reason) we want to ask the database to “give us the (serial number, asset type, and the location manager’s name and phone number) closest to one-of-the-three latitude/longitude coordinates we will provide where the asset has been inspected and placed in a bin-location”. Oh, and limit that result-set by 100 documents.

Using MongoDB::QueryBuilder, the abstraction might resemble the following:

use MongoDB::QueryBuilder;

my $query = MongoDB::QueryBuilder->new(
    only => [
        'serial_number',
        'asset.type.name',
        'asset.location.phone',
        'asset.location.manager.name'
    ],
    and_where => [
        'asset.location.bin$ne' => undef,
        '$or' => [ # this condition will short-circuit
            {'asset.location.latlng$near' => [$a, $b]},
            {'asset.location.latlng$near' => [$c, $d]},
            {'asset.location.latlng$near' => [$e, $f]}
        ]
    ],
    limit => 100
);

Needless to say, manually producing the code to query the database would be a bit more involved. Another noteworthy feature is that the query-builder object is chainable which allows you to create classes that will return a result-set.

For example. Considering the aforementioned scenario.

package MyApp::Inventory::Assets;

use MongoDB::QueryBuilder;

has 'query';
sub _build_query { MongoDB::QueryBuilder->new }

sub has_been_inspected {
    my $self = shift;
    $self->query->and_where('asset.location.bin$ne' => undef);
    return $self;
}

sub is_located_near {
    my $self = shift;
    $self->query->and_where('asset.location.latlng$near' => [@_]);
    return $self;
}

sub limit {
    my $self = shift;
    $self->query->limit($_[0] || 100);
    return $self;
}

package main;

my $assets = MyApp::Inventory::Assets->new;

my $cursor = $assets->limit(25)->has_been_inspected;

while (my $asset = $cursor->next) {
    say $asset->{serial_number};
}

.. I rushed through the demonstration, sorry. I’m extremely busy these days. I hope this module will be of as-much use to others as it is to me (at-the-moment).

The end.

About Al Newkirk

user-pic ... proud Perl hacker, ask me anything!