fREWdiculous!
24 Aug
One of the cool ways of doing things in Perl is to use a dispatch table. The most obvious dispatch table is a hash of subroutines:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
This is a pretty cool thing to be able to do easily. But what’s even cooler is that we can refactor the dispatch table into a package, which allows us to make objects that can override bits of the dispatch table:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package Table { sub new { bless {}, $_[0] } sub GET { return $_[0]->{x} } sub PUT { $_[0]->{x} = $_[1] } } package SubTable { use parent 'Table'; sub DELETE { delete $_[0]->{x} } } my $table = SubTable->new; sub dispatch { my ($method, $data) = @_; if (my $fn = $table->can($method)) { $table->$method($data) # the following would also work and would be # marginally faster # $table->$fn($data) } else { die 'METHOD NOT ALLOWED!' } } |
Note that one thing you might consider is prefixing the methods with “public_” or something like that; just in case your dispatcher object as private methods you don’t want web browsers executing. Generally though I’d just not put such methods in my dispatcher, but I haven’t yet made anything super complex using this pattern. I am using the pattern for a pluggable dashboard system at work, but the methods there are all called GET_foo or POST_bar, so users can’t run methods I didn’t specifically make for HTTP.
22 Aug
I’m excited to announce a new version of Catalyst::ActionRole::PseudoCache.
New in the current release of Catalyst::ActionRole::PseudoCache is that it can now use Catalyst::Plugin::Cache as the underlying cache mechanism. The main reason was that the existing architecture didn’t work for multiple servers, which is how our system works. Plus this is just better overall.
In the long term I will be removing the old “Pseudo” cache. It might be a good idea to make a separate package with a better name at some point, but that will be for the next release. Enjoy!
22 Aug
I don’t feel great about this past week, but I was really busy with wedding planning stuff. I barely made either of my two main goals (2 blog posts and 2 patches/releases a week.)
Last week I:
I have high hopes for the coming week, that I can get more important releases and more interesting blog posts written. Stay tuned!
21 Aug
Our main product at work is a Windows product. The reasons are complicated, but the main reason is that that is what our customers seem to want. What this means is that I do some of my development on a virtual machine. For a long time I was just using msysGit. msysGit goes a long way; you have a real bash console, a bunch of standard unix commands, and very good windows integration. On the other hand that’s about all you get. After reading his blog post I spoke with Caelum about getting zsh working with msysgit and he said it was probably just better to use cygwin…
There are a handful of reasons to use cygwin, but the main reason I did was for zsh. If you want to follow my path just get the cywin installer and install at least git and ssh. If you are like me you’ll also want to install zsh.
A couple other things that are nice to install are screen and mintty. Screen is just great in general and I use it constantly. I should probably do a blog post on just that at some point. mintty solves the constant bother in windows that the console emulator is horrible and can’t be resized sensibly.
Make sure to follow the instructions in Caelum’s blog post as they are very helpful overall.
cygwin is certainly not perfect though. First off, it is noticeably slower than the already slow msysgit, which is very disappointing. On top of that the home directory is not the same as the standard windows home directory, which is just obnoxious. For some reason with msysgit I could run the vim installed in program files from the command line, but with cygwin I can’t. I even tried making a symlink but those don’t work with cygwin, even though they are supported by ntfs.
Either way, it’s nice to have zsh and screen and a real terminal. Hopefully this helps someone out there
16 Aug
I only use a handful of git aliases, but the ones I do I really like. First off, the basic ones:
1 2 3 4 5 | [alias] ci = commit co = checkout st = status br = branch |
Also, another handy tip, as pointed out by a commenter is aliasing g to git (alias g=git) so that after you do the above instead of git ci you can merely do g ci. Neat.
Those are all very obvious and I’d bet nearly everyone has the first couple. The next ones are more in depth but I totally dig them.
I use zsh which has a huge number of glob expansions; what that means for me is that often when I try to run a git command it conflicts with the zsh globbing and I end up getting “zsh: no matches for ^foo”. So that’s what my first alias solves:
1 | alias git='noglob git' |
Once I put that in my .zshrc that problem went away entirely, which is nice.
I have the same problem with gitk, but also I always want gitk to be backgrounded, since it’s a gui tool. I wrote a tiny wrapper function and an alias to handle that:
1 2 | function g_tk() { /usr/bin/env 'gitk' "$@" & } alias gitk='noglob g_tk' |
That’s excellent. Now instead of ‘gitk …
Often when running gitk I don’t really want to see the entire history of the project. What I typically want is just what’s in the current branch, but not master. I made the following alias for that:
1 | alias grr='noglob g_tk ^origin/master HEAD' |
My main repo at work has eight submodules, and updating submodules is really an obnoxiously long command, so I aliased it too:
1 | alias gosu='git submodule update --init' |
Lastly, I rebase my code regularly onto the latest master, so I made the following alias:
1 | alias gre='git rebase --root --onto origin/master -i --autosquash' |
Another tiny tool I’ve made for less painful merges is what I call “handymerge” or hm.
1 2 3 | #!/bin/bash gitk $(cat .git/MERGE_HEAD) $(cat .git/ORIG_HEAD) "$@" & |
I put that in ~/bin and named it git-hm, so now when I’m merging if I want to look at the commits from both side I just run ‘git hm’. If I just want to see commits to file A I run ‘git hm A’. Pretty cool huh?
15 Aug
This week I:
13 Aug
Usually when searching through files I use ack which is an awesome tool indeed.
Unfortunately, though ack does indeed work on windows, using it on windows is a painful experience. The main two problems are that it’s slow and the color coding doesn’t work.
I figured I’d try out git grep, with the hope that it might be marginally better. I try my best to at least be familiar with all the git commands, so this is one of those things I had been meaning to do anyway.
I was in for a pleasant surprise when I found that git-grep’s color coding worked and it is extremely fast. I profiled it on linux and I get about an order of magnitude difference for a simple repo. If you use a repo with submodules the difference is even more visible, though possibly you would actually want to search submodules by default.
There are two features of ack that I use regularly. The first is that it doesn’t search files it shouldn’t, like .svn and .git. With git grep that is also the case, though it only works with git checkouts (which is all I have at this point.) The second feature is the ability to do –perl or –js or –java or whatever else. This can also be done easily with git grep, and I may make a bash wrapper called git-ack that just gives the interface of ack with the backend of git grep.
1 2 | ack frew --js git grep frew -- '*.js' |
Sure, it’s marginally longer, but if I do make the wrapper it will just be ‘git ack frew –js’ and given that I have cool shell settings based on the directory I’m in I will set it up such that ‘ack frew –js’ just runs ‘git ack frew –js’
Also, check out the amazing -p argument for git grep; it uses git’s code parsing to include the function that matches are in.
11 Aug
One of my projects at work was to make an SMS (and voice actually) gateway. The gist is that instead of our customers each having an account with whatever text message company, they go through us. The benefit is that with a larger pool of users for the text messages users can have a lot more flexibility with how they use their messages. Most gateways sell you messages per month, and we sell yearly messages.
One of the major uses of our software is for duress; that is, sending text messages to all the students at a college in an emergency (note: sending SMS in an emergency is a really bad idea, but people want to do it …) Because of this we really want to put a premium on how many we can send at a time. Our old gateway (non-persistent Perl, weird database, bad API) was excruciatingly slow.
To test the speed of our server when sending a large number of messages from a single server I wrote the following script to test a number of different situations.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #!/usr/bin/env perl use strict; use warnings; use JSON; use Getopt::Long::Descriptive; my ($opt, $usage) = describe_options( 'benchmark.pl %o', [ 'concurrent|c=i', 'number of concurrent connections', {default => 5 } ], [ 'destinations|d=i', "number of destinations to submit", { default => 100 } ], [ 'total-iterations|n=i', "number of iterations to run", { default => 100 } ], [], [ 'help|h|?', 'print usage message and exit' ], ); print($usage->text), exit if $opt->help; open my $fh, '>', 'testtest'; print {$fh} to_json({ message => 'HELP! BUILDING IS ON FIRE!', destinations => [map +{ phone_number => 1000000000 + $_, child_id => $_, }, 1..($opt->destinations)] }); system( 'ab', qw(-T application/json), '-n' => $opt->total_iterations, qw(-p testtest), '-c' => $opt->concurrent, 'http://10.6.1.56:3000/api/1/test/sms' ); |
So we have a handful of nice commandline options, we generate a file of JSON, and then we have ab run the actual speed test.
One of the really neat things you can do is have perl run more than one ab instance at a time, this allowing you to test multiple urls, which ab doesn’t support natively.
Anyway, good luck speed testing the hotspots in your app!
9 Aug
I’m very excited to finally announce a feature that I’ve toyed with in Class::C3::Componentised for over a year now.
New in the current release of Class::C3::Compontised is Class::C3::Componentised::ApplyHooks. The gist is that you can run code, or more importantly methods, against the class being injected into.
I wouldn’t be surprised if few people reading this actually know what Class::C3::Componentised is actually used in; the answer is DBIx::Class. The upshot of this new feature is that you could write a component to add columns or relationships much more nicely than before.
A simple example and usage of it is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | package MyApp::Schema::ResultComponents::TimeStamp; use base 'DBIx::Class::TimeStamp'; use Class::C3::Componentised::ApplyHooks; AFTER_APPLY { my $class = shift; $class->add_columns( timestamp => { data_type => 'datetime', set_on_create => 1, } ); } 1; package MyApp::Schema::Result::User; use base 'DBIx::Class::Core'; __PACKAGE__->table('users'); __PACKAGE__->load_components('+MyApp::Schema::ResultComponents::TimeStamp'); ...; 1; |
There are two caveats.
You cannot simply “use base” a component with Apply Hooks. The hooks just won’t run. There are ideas on how to solve that, but maybe that’s a feature.
The second is that you must load_components after table is set. The simple solution at this point is to yuse DBIx::Class::Candy, as it runs the table code at compile time. I hear that another solution is in the mix as well, which will basically make add_columns et al create the underlying result source on demand, but we’ll see if that materializes.
Either way, it will be interesting to be able to use this internally as it easily lets me share table definition data in a cleaner way than I did before. Hopefully you find it useful as well.
8 Aug
This week I