Apr 022014
 

Here’s a brief survey of node.js Gearman modules. I’ll have some analysis based on this later.

Module Github Author Last
Commit
Open
Issues
Tests Docs Client Worker Multi
Server
Streams Errors Timeouts
gearman gofullstack/gearman-node smith, gearmanhq 2011-05-02 4
gearman-stream Clever/gearman-stream azylman, templaedhel 2014-03-21 0
Previously named gearman_stream, uses gearman-coffee
gearnode andris9/gearnode andris 2013-02-25 1
gearmanode veny/GearmaNode veny 2014-03-20 4
nodegears enmand/nodegears enmand 2013-12-07 1
que vdemedes/que vdemedes 2012-07-02 0
Uses node-gearman
gearman-js mreinstein/gearman-js mreinstein 2013-11-03 4
gearman2 sazze/gearman-node ksmithson 2013-09-17 0
Fork of gearman with no changes except name
node-gearman andris9/node-gearman andris 2013-08-13 2
node-gearman-ms nachooya/node-gearman-ms nachooya 2013-11-18 0
Fork of node-gearman
gearman-coffee Clever/gearman-coffee rgarcia, azylman, jonahkagan 2013-03-19 2
magictoolbox/node-gearman oleksiyk 2012-12-03 0
Oct 162013
 

The “every” command is that I wrote, inspired by the unix “at” command.  It adds command to your crontab for you, using an easier to remember syntax.  You can find it on github, here: https://github.com/iarna/App-Every

I was reminded because of this article on cron for perl programmers who are unix novices:

http://perltricks.com/article/43/2013/10/11/How-to-schedule-Perl-scripts-using-cron

Here’s how you’d write their examples using “every”:

What’s more, there’s no need to specify the path to Perl, because unlike using crontab straight up, it will maintain your path.  Even better, you can use relative paths to refer to your script, eg:

This works because every ensures that it executes from the place you set it up.  Just like “at” it uses all of the same context as your normal shell.

Sep 112013
 

“Education clearly pays. Despite recent questioning of the value of university degrees, more than two thirds of the top one per cent had a university degree, compared to 20.9 per cent of the total population.”

No, that’s not what that says at all. It says that the wealthy value degrees, not that degrees make one wealthy.  It says that degrees are something that wealthy people do, but if you just get a degree thinking it will make you wealthy, you’re as confused as the cargo-cults that would build bamboo airports in hopes of attracting a supply plane.

Sep 242012
 

webify-dir

This is just a little hack of mine to make it trivial for me to reflect any directory on my server as a website, either with a name I specify or a hash. Handy for all sorts of things, I initially created it to give myself an easy way to view remote coverage reports that generated to HTML. It’s also a nice way to view HTML docs bundled with a package, or any other random HTML you come across.

How it works

As part of setup, we create a file based apache rewrite map that rewrites slugs off of our domain based on rules from a text file. These text files are super simple, just the slug followed by a space and then what to rewrite to.

With the setup out of the way, we have a very simple shell script that uses Perl to figure out the absolute path from your relative one and uses openssl to generate a hash from that. It uses the hash as the slug if you don’t specify one.  Once it’s appended these to the rewritemap file it tells you what your new URL is.

The example in the repo obviously isn’t generic, it refers to a host I control, but that’s easily editable.  This is less software package and more stupid sysadmin hack.

Aug 232012
 

Beyond the standard 80 and 443 to handle web traffic, Android also needs 5222 (Jabber) and 5228 (allegedly Google Marketplace, but needed for a phone to fully connect to the network and have functioning Google Talk).

Mail is also likely needed too of course, with SMTP 25 and 995, POP 110 and 993, and IMAP 143 and 465. For some setups you may also need LDAP, 389 and 636. Exchange needs 135 and in some esoteric configurations, NNTP with 119 and 563.

Aug 032012
 

Cage7.jpg
I’ve been a busy little bee lately, and have published a handful of new CPAN modules— I’ll be posting about all of them, but to start things off, I bring you: AnyEvent::Capture

It adds a little command to make calling async APIs in a synchronous, but non-blocking manner easy. Let’s start with an example of how you might do this without my shiny new module:

The above is not an uncommon pattern when using AnyEvent, especially in libraries, where your code should block, but you don’t want to block other event listeners. AnyEvent::Capture makes this pattern a lot cleaner:

The AnyEvent::DBus documentation provides another excellent example of just how awkward this can be:

With AnyEvent::Capture this would be:

We can also find similar examples in the Coro documentation, where rouse_cb/rouse_wait replace condvars:

Even still, for the common case, AnyEvent::Capture provides a much cleaner interface, especially as it will manage the guard object for you.

Jul 152012
 

I’ve been building a little stand alone command line tool lately, which led to me looking at using App::FatPacker to make a standalone, single-script download. This was going well until I tried to load Digest::Perl::MD5, which caused fatpacker to mysteriously crash with an undefined value. The reason for this is interesting…

When fatpacker goes to analyze a module list, it at one stage runs require on all of them, like so:

Then later on it uses @packages and discovers that one of the elements has is now undef. How did this happen?

Well, if the module you require fiddles with $_ without localizing it first, that will ultimately result in modifying @packages. How did Digest::Perl::MD5 do this?

It read its data block at load load time. And of course, the last value in $_ there is undef. This all would have been avoided had the require loop been written out to be less golfy:

Of course, this is the same function that had:

And anyone who would publish code with that in it is probably beyond hope. ;)

(Bugs with patches have been filed with both App::FatPacker and Digest::Perl::MD5. The latter, to just localize $_ before the while loop.)

Jul 082012
 

While I was browsing the CPAN the other day, I came across Coro::LocalScalar and I said to myself, oh, what a useful idea… it lets you localize globals to a thread. An important feature if you do anything in your thread with those pesky globals from perlvar, for instance.

But, said I, its calling convention is the rather gross Coro::LocalScalar->new->localize($scalar); and it’s implemented using tie and only for scalar values. It would be nice to have a new keyword and support for arrays and hashes as well. As it happens, I’d also recently run across Begin::Declare, which is a Devel::Declare based module that provides custom variable declarations.

A few hours later, with the example of Begin::Declare to work from, I bring you Coro::Localize (now on a CPAN mirror near you). It’s localization is achieved through a combination of Coro’s on_enter /on_leave blocks and Data::Alias.

So you might use it this way:

$scalar will be set to "thread local" for all of the code inside the async block, even if you cede and someone else fiddles with the variable. Similarly, any code outside the async block will only ever see "some value".

Sep 262011
 

While on the one hand, ORMs make up most of the published best practices for interfacing with databases, (see the success of DBIx::Class, and many other similar products), on the other hand, there is a certain amount of backlash against them, eg ORM is an Antipattern.

I would add two further critiques of ORMs. First, most people use ORMs as their model layer (every Catalyst project I’ve seen does this, for instance), rather then implementing their model layer using the ORM as simply the database access layer. Using the ORM as your model layer violates abstraction— it ties your business logic intimately to the structure of your data. It makes you think of your data in terms of nouns defined by how the database itself is laid out. Instead, you should be thinking in terms of verbs— what do you want to do, not what do you want to do it to. That is, ask me how many users are online, not how many rows in the user table have the online column set to 1.

Continue reading »