Roleing Along Like a Tumbling Tumbleweed

Well here is a little store from the trenches today that oddly enough does has something to do with Moose and roles.

li-moose-sign-20130412.jpg

Well my very talented colleague of mine came up with a very nice little Moose class that nicely encapsulated connecting to and sending messages to and from a Amazon SQS server.

Well we already had a very good application that parsed and assembled messages (Emails, Faxes, PDFs and alike) so I though why not introduce Amazon SQS into the mix so we could send these sorts of messages as well.

Seemed simple enough all I did was change the original module a little

From this


package AmazonSQS;

use Amazon::SQS::Simple qw//;
use Moose;

to this;


package AmazonSQS;

use Amazon::SQS::Simple qw//;
use Moose::Role;

and presto it turns from a class to role. Now I could add it into a message if the message was to be sent over SQS . I just used 'use Moose::Util qw(apply_all_roles )' like I do in this post and I was off to the races.

Well the we sent out our first post and got


Can't locate object method "host" via package "URI::_generic" at /usr/lib/perl5/site_perl/5.8.8/Amazon/SQS/Simple/Base.pm line 238.

Well what was that. Fortunately my colleague recognized the problem (despite the rather poor and cryptic error message) it was the the queue was missing the 'Endpoint' value.

How could that be as the 'Endpoint' was like this


has 'endpoint' => ( is => 'ro', builder => '_build_endpoint');


sub _build_endpoint {
my $self = shift;
return 'https://sqs.yeah.right.I.am.going.to.put.a.real.url.in.a blog';

}

The I checked the object itself and a quick dump got me this;


'sqs' => bless( {
                                   'SecretKey' => 'fsdsffdsfds+3Oqfdsfdfds',
                                   'AWSAccessKeyId' => 'dsffdsdsffdsdfsfdsfd',
                                   'Version' => '2012-11-0fffff',
                                   'Endpoint' => 'https://sqs.yeah.right.I.am.going.to.put.a.real.url.in.a blog',
                                   'SignatureVersion' => 2
                                 }, 'Amazon::SQS::Simple' ),
                 'secret_key' =>'fsdsffdsfds+3Oqfdsfdfds',
                 'queue' => bless( {
                                     'SecretKey' => ''fsdsffdsfds+3Oqfdsfdfds"
                                     'AWSAccessKeyId' => 'dsffdsdsffdsdfsfdsfd',
                                     'Version' => '2012-11-0fffff',
                                     'Endpoint' => '',
                                     'SignatureVersion' => 2
                                   }, 'Amazon::SQS::Simple::Queue' ),

What gives my queue is this


sub _build_queue {
        my $self = shift;
        return $self->sqs->GetQueue($self->endpoint);
}

So I should never get empty for it?

I fiddled with the orignial code and it seem to but then I remembered this line in the Moose Manual

If your default is dependent on other parts of the object's state, you can make the attribute lazy. Laziness is covered in the next section.

Could this be the case? So a quick change to my


has 'endpoint' => ( is => 'ro', builder => '_build_endpoint', lazy=>1);

and tried again got what I wanted


\...
EBUG: .../IO/Socket/SSL.pm:1609: OK free ctx 220098496

VAR1 = [
bless( {
'MessageBody' => '{"Message":{"fsddsfsdf":{"sdfsfdsfd":dsfsdsf,"ssfdsd":{"ssfsfd":2,"sfsfd":1},"sfsdfsdf":null},"fsdsfdsdfsdf":" Email"," SOURCE":"dsfsdfsfd"},"Message":"2014-03-28"," Type":"dsffdsfds"}',
'Id' => 'msg_1',
'MD5OfMessageBody' => '957f3de5sdfsfsdf6b584c4db1f093',
'MessageId' => 'feafsdsdfsdf6-826d-11bb0469b6d4'
}, 'Amazon::SQS::Simple::SendResponse' )
];

So if you are going to use builders with roles it is a good Idea to set them to lazy just as a matter of course.

This one did not cost much time fortunately I guess all those AD&D posts are paying off.


Leave a comment

About byterock

user-pic Long time Perl guy, a few CPAN mods allot of work on DBD::Oracle and a few YAPC presentations