Monday, November 4, 2013

What's installed on my ec2

What's installed on my ec2?

I swear between debian/ubuntu/mac os x/irix (well not anymore), I can never remember how to list installed packages on my ec2. 

Here is is:

   sudo yum list installed

Plus or minus sudo depending on who you are. For once, the command is what i'd expect.

__END__

Tuesday, September 24, 2013

Toying around with backbone.js

Toying around with Backbone.js

At $work, we've been using more and more backbone.js to create a more responsive front end experience and help the dev team manage the code.

I like backbone.js and find that its it is very helpful to seperate data and code on the client. But I've found that it challenges me to think in different ways.

I find it helpful to create an app so I did :)

Introducing Brewers Radio Finder

Over the years, i've often driven between Milwaukee and St. Paul, MN. While on the drive, there are areas of the state where finding the close Brewer's radio station is tough and figuring out which station is the closest to you is difficult when looking at the map from Brewers Radio network. Am I currently closer to Reedsburg or Portage?

The app is pretty simple, you can type in or give it your current location and it will show the 3 closest Brewers radio stations to you. 

You can check it out at http://radiofinder.leecarmichael.com/

If anyone is interested I'd be willing to make the code public on github. I didn't do it by default since I had to do some geocoding and storage of the station locations and i'm not sure if i can share that (even though its public). And i haven't dropped a license in there (not sure which one to do).

The app is only a few parts:
  • backbonejs + bootstrap front end 
  • Perl Dancer backend (serving JSON to front end and some initial templates)
  • MySQL Database
  • Use of Google's geocoding library/service (for initial coding of stations) and GIS::Distance
Using Dancer with backbone is very slick. The Dancer json (de)serialization setup is very elegant. Basically set it in the config and you can return data structures in 'ajax' routes and it does its (de)serialization magic. Pretty nice way to hide that complexity.

As a full start from scratch project in backbonejs that didn't involve todo items. It was a good learning experience. I ran into some mental issues using templates w/ widgets that didn't have a model but otherwise it went pretty well. I had some trouble with routes that opened and closed widgets ('about' dialog was a bit of a fight and still isn't perfect). And I still haven't got my mind around using a view and route with something that didn't have a model (the search inputs). I felt like making it a model was a bit of extra cruft that didn't add value (but i bet it might be helpful as the app grew). There are areas, that i'll revisit when i get some time.

A few future things that I'm working on:
  • Displaying current location and stations on a map (this is pretty close)
  • Fixing a few display issues with the responsive layout on smaller screens
  • More unit tests for "live" dev instance
That's all for now.

__END__

Tuesday, June 25, 2013

backbonejs' alteration of ajax handler parameters

As I spend time learning Backbone I've found some unexpected things (to me probably not to others). Today I found that even though Backbone fetch allows you to pass in typical jQuery ajax options (like success or error handlers), it will alter what parameters are passed back to those handlers.

In jQuery


Here is an example of plain jane ajax call (in older style jQuery before renaming of events):



In backbone handler

In backbone fetch changes up what you receive. It is nicely stated in that section:
The options hash takes success and error callbacks which will both be passed (collection, response, options) as arguments.
I only read that like 3 times before i actually saw that note :)

Here is an example of backbone success handler:

The one really nice part of the different parameters is that backbone gives you objects instead of raw-ish data. This means if you need to create two different models (or collections) from the same call, you can pass it directly into the model 'set' method. (see line 13).

Now the question is the best way to handle a situation where the backend server returns multiple models in a response. In this case, I chose to pull them out in a custom ajax handler and update one collection to use specific part of the return data. But I could have been persuaded to create custom ajax call to retrieve and then create each model/collection separately. This might be a good place to write out some examples, code snippets and write about what I learn. I suspect that it will vary like most things :)

__END__

Thursday, March 28, 2013

Altering TT's INCLUDE_PATH in Dancer with Custom View

Altering Template Toolkit's INCLUDE_PATH in Dancer

This just came up on Dancer's mailing list and I've been sitting on this code (and post) for a few months since the project I was working on didn't need it.

Basically Dancer's Template Toolkit view requires you completely alter it or use the default setting. This is pain if you just want to add to it but not have to manage all the changes.

I created a new TT view class, to get inside the TT init and add to the INCLUDE_PATH instead of replace it. The code was a bit involved and I extended it a bit by adding a customization flag in each environment (if needed).

On to the code

Here is the code and config that i used to do this

Disclaimer

I don't recall all the other issues that i ran into while doing this. It was over 6 months ago but post questions if you have them

__END__

Friday, January 25, 2013

Dancer + Nginx + FastCGI

Bring together the parts

I was able to find complete documentation on running dancer with nginx using FastCGI. In the dancer deployment it discusses using Apache and fastcgi or nginx with proxy. Often, using nginx as proxy to starman(or some other plack webserver) is probably the right thing. But sometimes using fastcgi is good idea too :) I'm running some benchmarks but it seems like memory usage is a bit smaller with FCGI but I still need to do more digging on this.

Make it so

Lets get all the parts install and then configure them

Install the Parts

Note: These parts will be very dependent on your system. I'm assuming a debian/ubuntu system below.

First you need to have nginx and dancer installed. For nginx i would recommend doing something like:

apt-get install nginx

or building and install from source. 

Next, install need Perl modules:

cpanm + Dancer's Makefile.PL

I like to install using Dancer's app generated Makefile.PL along with cpanm to manage Perl dependencies.

Setup your Makefile.PL:

use strict;
use warnings;
use ExtUtils::MakeMaker;

WriteMakefile(
    NAME                => 'AppName',
    AUTHOR              => q{your name},
    VERSION_FROM        => 'lib/ExApp.pm',
    ABSTRACT            => 'example dancer app',
    ($ExtUtils::MakeMaker::VERSION >= 6.3002
      ? ('LICENSE'=> 'perl')
      : ()),
    PL_FILES            => {},
    PREREQ_PM => {
        'Test::More' => 0,
        'YAML'       => 0,
        'Dancer'     => 1.3095,

        # required to run in fcgi mode
        'Plack'      => 0,
        'FCGI'       => 0,
        'FCGI::ProcManager' => 0,
 
        # application specific
        'Template'   => 0,
        'Dancer::Plugin::Database' => 0,
        'DateTime' => 0,
        'DateTime::Format::MySQL'  => 0,
         
    },
    dist                => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
    clean               => { FILES => 'example-app-name-*' },
);

You can do: cpanm --installdeps .

Other options....

cpanm Dancer Plack FCGI FCGI::ProcManager
Or
cpan install Dancer Plack FCGI FCGI::ProcManager

Configure nginx

Now, lets configure nginx nginx.conf. It isn't a large change from http://wiki.nginx.org/NginxFcgiExample. There are three main changes below.

  1. Configure nginx to serve the static content (in dev this isn't a huge deal but in production you will save some major time and resources).
  2. Plack's FCGI handler requires SCRIPT_NAME to be empty. I'm not sure why but i'm sure its a very smart security thing or due the fact that it isn't using a dispatch script.
  3. Plack's FCGI handler uses PATH_INFO and needs it to be configured. See:set $path_info $uri; line

Example Configuration:

    server {
        listen       80;
        server_name  fastcgi-example.leecarmichael.com;
        root /home/user/dancer_app/public;
        access_log  logs/fcgi-example.access.log  main;

        # serve static content from nginx not dancer
        location = /favicon.ico {
        }

        location /images {
        }

        location /js {
        }

        location /css {
        }

        # serve all other stuff from appserver
        location / {
                set $script "";
                set $path_info $uri;
                fastcgi_param   QUERY_STRING        $query_string;
                fastcgi_param   REQUEST_METHOD      $request_method;
                fastcgi_param   CONTENT_TYPE        $content_type;
                fastcgi_param   CONTENT_LENGTH      $content_length;

                fastcgi_param   SCRIPT_FILENAME     $request_filename;

                # plack FCGI handler requires these changes
                fastcgi_param   SCRIPT_NAME         $script;
                fastcgi_param   PATH_INFO           $path_info;

                fastcgi_param   REQUEST_URI         $request_uri;
                fastcgi_param   DOCUMENT_URI        $document_uri;
                fastcgi_param   DOCUMENT_ROOT       $document_root;
                fastcgi_param   SERVER_PROTOCOL     $server_protocol;

                fastcgi_param   GATEWAY_INTERFACE   CGI/1.1;
                fastcgi_param   SERVER_SOFTWARE     nginx/$nginx_version;

                fastcgi_param   REMOTE_ADDR         $remote_addr;
                fastcgi_param   REMOTE_PORT         $remote_port;
                fastcgi_param   SERVER_ADDR         $server_addr;
                fastcgi_param   SERVER_PORT         $server_port;
                fastcgi_param   SERVER_NAME         $server_name;

                # can use port as well
                fastcgi_pass  unix:/tmp/myapp-fcgi.sock;
        }
}

Start, Restart and Go

Start or restart nginx.

On debian: /etc/init.d/nginx restart

Startup your app server (make sure you'ave changed to /home/user/dancer_app):
plackup -E development -s FCGI -a bin/app.pl -S /tmp/myapp-fcgi.sock -D

See plackup for all the options. I added -D and usually add --error-log but a start up script is probably a better long term choice

After writing all this, i stumbled across a pretty helpful reference in the Plack docs on Plack::Handler::FCGI which replicates the fast-cgi nginx.conf above.

__END__