[Catalyst] Re: use for expand_modules
Gianni Ceccarelli
dakkar at thenautilus.net
Mon Aug 8 09:13:14 GMT 2011
(re-sent, since apparently the mailing list didn't like my previous
attempt)
Hello.
I am using expand_modules at work. It may not be the best solution to
my problem, but it seemed appropriate. Let's see if I can describe
what I'm doing.
I have a thing that just happens to be a Catalyst application, using
Catalyst::Engine::Stomp to respond to ActiveMQ messages instead of
HTTP requests. Since the actual logic of the application does not
depend on the fact that we're using Catalyst as a module loader and
dispatcher, I have written a sort of "insulation layer" between
Catalyst and the actual business logic.
The "insulated" consumer modules look like this:
package MyApp::Consume::Something;
use Moose;
extends 'MyFramework::Base::Consume';
sub routes {
return {
a_queue_name => {
a_message_type => \&a_method_to_handle_it,
another_message_type => \&you_get_the_idea,
},
a_different_queue => {
and_so => \&on_and_on,
},
}
}
# here go the actual subs / methods
The MyFramework::Base::Consume class is a Catalyst::Component (well,
better said, ->can('COMPONENT')), and implements a expand_modules
method that does more or less this:
- collect the queues this module wants to listen on
- create (via Moose::Meta::Class->create, and only if it's not already
there) a Catalyst Controller per queue, under the appropriate
namespace (the controller inherits from
Catalyst::Controller::MessageDriven, part of the
Catalyst::Engine::Stomp distribution)
- add a "after 'register_actions'" modifier on the controller to
create the actions that will dispatch the message to the appropriate
method as required
Pseudo-code:
sub expand_modules {
my ($class) = @_;
my @ret = ();
for my $queue (keys %{$class->routes}) {
my $controller_name = the_name_for($queue);
if (not is_controller_there($controller_name)) {
create_controller($controller_name,$queue);
}
for my $message_type (keys %{$class->routes->{$queue}}) {
add_after_register_actions(
$controller_name,
$message_type,
$class->routes->{$queue}{$message_type}
);
}
push @ret, $controller_name;
}
return @ret;
}
Answers to some probable questions:
- Can't your Consume modules be Controllers, and then you do
$something to the Dispatcher?
Maybe, but Catalyst::Engine::Stomp /
Catalyst::Controller::MessageDriven do enough strange things to the
dispatch, and I prefer not to rewrite them
- Do you really need to insulate your modules so much from Catalyst?
There is talk to use some other system to handle ActiveMQ in the
future, and I don't want to have to touch my code more than strictly
necessary
- How the &%$%$^# did you think this was a good idea?
Well, it *is* documented :) And it seems to be the obvious hook:
when loaded, my component creates more components…
Questions:
- am I insane? :)
- is there a better / cleaner / more future-proof way of getting the
same result?
- will the "much better solution" that t0m hinted at still allow me
this kind of contortions?
Thanks :)
--
Dakkar - <Mobilis in mobile>
GPG public key fingerprint = A071 E618 DD2C 5901 9574
6FE2 40EA 9883 7519 3F88
key id = 0x75193F88
"Why's it called Ming?" said the Archchancellor, on cue.
The Bursar tapped the pot. It went *ming*.
-- Discworld archeology revealed
(Terry Pratchett, Moving Pictures)
More information about the Catalyst
mailing list