summaryrefslogtreecommitdiff
path: root/posts/2009-11-09-modules-i-like-devel-declare.org
diff options
context:
space:
mode:
authorFranck Cuny <franck.cuny@gmail.com>2016-08-10 14:33:04 -0700
committerFranck Cuny <franck.cuny@gmail.com>2016-08-10 20:17:56 -0700
commit8d7d02f42c3947f756c18cb4d37d9d97fbd0d27d (patch)
treea6cecddaaea7e87d901a6c28bebe3a531438f24b /posts/2009-11-09-modules-i-like-devel-declare.org
parentMerge branch 'convert-to-org' (diff)
downloadlumberjaph-8d7d02f42c3947f756c18cb4d37d9d97fbd0d27d.tar.gz
convert back to md
Diffstat (limited to '')
-rw-r--r--posts/2009-11-09-modules-i-like-devel-declare.org265
1 files changed, 0 insertions, 265 deletions
diff --git a/posts/2009-11-09-modules-i-like-devel-declare.org b/posts/2009-11-09-modules-i-like-devel-declare.org
deleted file mode 100644
index facdc81..0000000
--- a/posts/2009-11-09-modules-i-like-devel-declare.org
+++ /dev/null
@@ -1,265 +0,0 @@
-For [[http://linkfluence.net/][$work]], I've been working on a job queue
-system, using Moose, Catalyst (for a REST API) and DBIx::Class to store
-the jobs and some meta (yeah I know, there is not enough job queue
-system already, the world really needs a new one ...).
-
-Basicaly, I've got a XXX::Worker class that all the workers extends.
-This class provide methods for fetching job, add a new job, mark a job
-as fail, retry, ...
-
-The main loop in the XXX::Worker class look like this:
-
-#+BEGIN_SRC perl
- # $context is a hashref with some info the job or method may need
- while (1) {
- my @jobs = $self->fetch_jobs();
- foreach my $job (@jobs) {
- my $method = $job->{funcname};
- $self->$method($context, $job);
- }
- $self->wait;
- }
-#+END_SRC
-
-and the worker look like this
-
-#+BEGIN_SRC perl
- package MyWorker;
- use Moose;
- extends 'XXX::Worker';
-
- sub foo {
- my ($self, $context, $job) = @_;
-
- # do something
- $self->job_success();
- }
-#+END_SRC
-
-But as I'm using Moose, I want to add more sugar to the syntax, so
-writing a new worker would be really more easy.
-
-Here comes
-[[http://search.cpan.org/perldoc?Devel::Declare][Devel::Declare]].
-
-The syntax I want for my worker is this one:
-
-#+BEGIN_SRC perl
- work foo {
- $self->logger->info("start to work on job");
- # do something with $job
- };
-
- work bar {
- # do something with $job
- };
-
- success foo {
- $self->logger->info("woot job success");
- };
-
- fail bar {
- $self->logger->info("ho noez this one failed");
- };
-#+END_SRC
-
-Where with =work= I write the code the writer will execute on a task,
-=success=, a specific code that will be executed after a job is marked
-as successfull, and =fail= for when the job fail.
-
-I will show how to add the =work= keyword. I start by writing a new
-package:
-
-#+BEGIN_SRC perl
- package XXX::Meta;
-
- use Moose;
- use Moose::Exporter;
- use Moose::Util::MetaRole;
-
- use Devel::Declare;
-
- use XXX::Meta::Class;
- use XXX::Keyword::Work;
-
- Moose::Exporter->setup_import_methods();
-
- sub init_meta {
- my ($me, %options) = @_;
-
- my $for = $options{for_class};
-
- XXX::Keyword::Work->install_methodhandler(into => $for,);
-
- Moose::Util::MetaRole::apply_metaclass_roles(
- for_class => $for,
- metaclass_roles => ['XXX::Meta::Class'],
- );
-
- }
-
- 1;
-#+END_SRC
-
-The =init_meta= method is provided by Moose: (from the POD)
-
-#+BEGIN_QUOTE
- The =init_meta= method sets up the metaclass object for the class
- specified by =for_class=. This method injects a a meta accessor into
- the class so you can get at this object. It also sets the class's
- superclass to base\_class, with Moose::Object as the default.
-#+END_QUOTE
-
-So I inject into the class that will use XXX::Meta a new metaclass,
-XXX::Meta::Class.
-
-Let's take a look to XXX::Meta::Class:
-
-#+BEGIN_SRC perl
- package XXX::Meta::Class;
-
- use Moose::Role;
- use Moose::Meta::Class;
- use MooseX::Types::Moose qw(Str ArrayRef ClassName Object);
-
- has work_metaclass => (
- is => 'ro',
- isa => Object,
- builder => '_build_metaclass',
- lazy => 1,
- );
-
- has 'local_work' => (
- traits => ['Array'],
- is => 'ro',
- isa => ArrayRef [Str],
- required => 1,
- default => sub { [] },
- auto_deref => 1,
- handles => {'_add_work' => 'push',}
- );
-
- sub _build_metaclass {
- my $self = shift;
- return Moose::Meta::Class->create_anon_class(
- superclasses => [$self->method_metaclass],
- cache => 1,
- );
- }
-
- sub add_local_method {
- my ($self, $method, $name, $code) = @_;
-
- my $method_name = $method . "_" . $name;
- my $body = $self->work_metaclass->name->wrap(
- $code,
- original_body => $code,
- name => $method_name,
- package_name => $self->name,
- );
-
- my $method_add = "_add_" . $method;
- $self->add_method($method_name, $body);
- $self->$method_add($method_name);
- }
-
- 1;
-#+END_SRC
-
-Here I add to the =->meta= provided by Moose =local_work=, which is an
-array that contains all my =work= methods. So each time I do something
-like
-
-#+BEGIN_SRC perl
- work foo {};
-
- work bar {};
-#+END_SRC
-
-in my worker, I add this method to *->meta->local\_work*.
-
-And the class for our keyword work:
-
-#+BEGIN_SRC perl
- package XXX::Keyword::Work;
-
- use strict;
- use warnings;
-
- use Devel::Declare ();
- use Sub::Name;
-
- use base 'Devel::Declare::Context::Simple';
-
- sub install_methodhandler {
- my $class = shift;
- my %args = @_;
- {
- no strict 'refs';
- *{$args{into} . '::work'} = sub (&) { };
- }
-
- my $ctx = $class->new(%args);
- Devel::Declare->setup_for(
- $args{into},
- { work => {
- const => sub { $ctx->parser(@_) }
- },
- }
- );
- }
-
- sub parser {
- my $self = shift;
- $self->init(@_);
-
- $self->skip_declarator;
- my $name = $self->strip_name;
- $self->strip_proto;
- $self->strip_attrs;
-
- my $inject = $self->scope_injector_call();
- $self->inject_if_block(
- $inject . " my (\$self, \$content, \$job) = \@_; ");
-
- my $pack = Devel::Declare::get_curstash_name;
- Devel::Declare::shadow_sub(
- "${pack}::work",
- sub (&) {
- my $work_method = shift;
- $pack->meta->add_local_method('work', $name, $work_method);
- }
- );
- return;
- }
-
- 1;
-#+END_SRC
-
-The =install_methodhandler= add the =work= keyword, with a block of
-code. This code is sent to the parser, that will add more sugar. With
-the inject\_if\_block, I inject the following line
-
-#+BEGIN_SRC perl
- my ($self, $context, $job) = @_;
-#+END_SRC
-
-as this will always be my 3 arguments for a work method.
-
-Now, for each new worker, I write something like this:
-
-#+BEGIN_SRC perl
- package MyWorker;
- use Moose;
- extends 'XXX::Worker';
- use XXX::Meta;
-
- work foo {};
-#+END_SRC
-
-The next step is too find the best way to reduce the first four lines to
-two.
-
-(some of this code is ripped from other modules that use Devel::Declare.
-The best way to learn what you can do with this module is to read code
-from other modules that use it)