The most recent release POEx::Role::SessionInstantiation now breaks out all of the various aspects of its inner workings into roles that are then composed into the master role. And now, via import, we can tell SessionInstantiation to compose other roles. It was a big refactor. But what did it buy? In terms of customization, it bought a lot.
The various segments were placed under POEx::Role::SessionInstantiation::Meta::Session::*. And so there is now Events, Implementation, Sugar, and Magic.
Events contains the various default events that POE would deliver to Sessions. Implementation takes care of the details of event dispatching and registration. Sugar provides methods that are delegated to the POE::Kernel singleton. And finally, Magic handles the tricky bits of making it all work with POE.
So now that everything is divided we can do some nifty things with the resulting roles. Let's say we wanted to build our objects without telling POE about them. All of that functionality is now stored inside Magic. It is simply a matter of advising the the BUILD method to not call session_alloc on the kernel instance. In fact, that functionality is now bundled up as POEx::Trait::DeferredRegistration.
And what if we wanted to do some initialization not specified in _start, but at that time from an external source? We can consume the Events role and advise _start as necessary. And this functionality is wrapped up in POEx::Trait::ExtraInitialization. It requires an arbitrary coderef at construction time that will be called as a method on the session at _start.
Now most of this was possible without the big refactor, but it would have been making use of under documented features inside SessionInstantiation. Now all of the bits and pieces have their docs and are segregated appropriately to allow for easier customization.
So what can you do with those kinds of traits? Aside from building better tools to manage resource sensitive operations such as loading modules before or after a fork, it will also eventually help with furthering POEx::ProxySession.
There is more to do on the Moose/Class::MOP front to finally make it possible to serialize in total a session, send it somewhere, reconstitute it, and activate it in the foreign POE kernel, but this is good step in that direction.
Saturday, September 26, 2009
Saturday, September 19, 2009
Murmur, DBus and Perl
Short post this week, but a neat project came up that I want to throw together this weekend.
Some quick background. Murmur is a VoIP server. Its typical application is use with the Mumble client to provide voice communications for computer games in the same vein as Ventrillo or Teamspeak. Together it provides a great set of features that include encryption, distinct channels, ACLs similar to IRC, and even user accounts. It is also useful for conference voice communication that provides superior voice quality than that of Skype or even conventional telephone conference calls that tend to be half-duplex.
So what does that have to do with DBus or Perl?
Well, Murmur's configuration all happens via DBus. DBus comes with a CLI app to sending arbitrary data along the bus properly addressed to a listening daemon. And just to add a user to Murmur the length of the command is unwieldy. In fact, you have to send two commands to set the password. You can do all sorts of configuration via DBus, but it is pretty hairy having to do it by hand.
So enter Perl. CPAN has a module called Net::DBus. So I am going to write a set of tools to administer Murmur and publish to CPAN under the App:: namespace.
Lots of good modules to use to make that happen including Moose, MooseX::Getopt, App::Cmd, etc.
By Sunday evening, I should hopefully have something that works (with stand alone libs that could be consumed via GUI app) and we can work on refinements from there.
You'll see the repo show up github soonish.
Some quick background. Murmur is a VoIP server. Its typical application is use with the Mumble client to provide voice communications for computer games in the same vein as Ventrillo or Teamspeak. Together it provides a great set of features that include encryption, distinct channels, ACLs similar to IRC, and even user accounts. It is also useful for conference voice communication that provides superior voice quality than that of Skype or even conventional telephone conference calls that tend to be half-duplex.
So what does that have to do with DBus or Perl?
Well, Murmur's configuration all happens via DBus. DBus comes with a CLI app to sending arbitrary data along the bus properly addressed to a listening daemon. And just to add a user to Murmur the length of the command is unwieldy. In fact, you have to send two commands to set the password. You can do all sorts of configuration via DBus, but it is pretty hairy having to do it by hand.
So enter Perl. CPAN has a module called Net::DBus. So I am going to write a set of tools to administer Murmur and publish to CPAN under the App:: namespace.
Lots of good modules to use to make that happen including Moose, MooseX::Getopt, App::Cmd, etc.
By Sunday evening, I should hopefully have something that works (with stand alone libs that could be consumed via GUI app) and we can work on refinements from there.
You'll see the repo show up github soonish.
Friday, September 11, 2009
TryCatch + Throwable rocks
I hopped on the bandwagon a while ago since I started using these two modules in my own projects so I could have real live try/catch blocks including MyError->throw(). As a bonus I get constraint matching on which catch block to execute.
Lots of people have pushing the Try::Tiny that Yuval put together and that's cool too, but I like my constraint matching. I have had several cases where it makes sense to do different things based on the type of exception I have received. And, I do enjoy having the lexicals put into my scope too.
For me, since I am already using MooseX::Declare which uses MooseX::Method::Signatures which uses Parse::Method::Signatures, it is a natural extension that my catch constraints be defined with the same syntax.
Recently though, I ran into a bug in TryCatch regarding certain scenarios with returns inside the try block. I banged my head against the wall for a day or so to no avail until I manned up and asked Ash what was going on. And much to my delighted surprise, it was already a reported issue and already fixed in a dev release on CPAN. I pulled it down and ran my tests and magically everything started working.
Anyhow, what prompted all of this was my work on POEx::WorkerPool. In my first go around, I wrapped a lot of the potential error spots in try/catch blocks but some of the handling was inconsistent, so I wanted to go back and rework a lot of that to be even more robust.
Now when errors occur, signals are handled properly inside of POE, and are reported via PubSub. For the most part, catastrophic errors are mitigated and reported instead of taking the whole enchilada down into some horrible state.
As soon as Ash does a non-dev release of TryCatch, I'll do another release of POEx::WorkerPool that includes this new found robustness.
Lots of people have pushing the Try::Tiny that Yuval put together and that's cool too, but I like my constraint matching. I have had several cases where it makes sense to do different things based on the type of exception I have received. And, I do enjoy having the lexicals put into my scope too.
For me, since I am already using MooseX::Declare which uses MooseX::Method::Signatures which uses Parse::Method::Signatures, it is a natural extension that my catch constraints be defined with the same syntax.
Recently though, I ran into a bug in TryCatch regarding certain scenarios with returns inside the try block. I banged my head against the wall for a day or so to no avail until I manned up and asked Ash what was going on. And much to my delighted surprise, it was already a reported issue and already fixed in a dev release on CPAN. I pulled it down and ran my tests and magically everything started working.
Anyhow, what prompted all of this was my work on POEx::WorkerPool. In my first go around, I wrapped a lot of the potential error spots in try/catch blocks but some of the handling was inconsistent, so I wanted to go back and rework a lot of that to be even more robust.
Now when errors occur, signals are handled properly inside of POE, and are reported via PubSub. For the most part, catastrophic errors are mitigated and reported instead of taking the whole enchilada down into some horrible state.
As soon as Ash does a non-dev release of TryCatch, I'll do another release of POEx::WorkerPool that includes this new found robustness.
Thursday, September 3, 2009
New Shiny
This past week I've been slammed; working to produce a new module: POEx::WorkerPool. Now, this will probably smack of NIH, but I looked at a couple of other good modules such as MooseX::Workers, and decided that I need to do my own that made use of the POEx tool chain and included MooseX::Declare.
To that end, the POEx::WorkerPool does the usual multi-process management and provides a mechanism to dole out jobs to workers, but where I feel it provides more bang for you buck is highlighted below.
-Easier Customization-
Each piece in the framework can be customized via traits defined in the 'use' statements of those pieces. Each piece does light coupling via Roles checking, so it doesn't hinder customization.
-Transparent Workers-
Workers publish a plethora of events via POEx::PubSub that allow for tracking of a job from the time the worker starts processing to even incremental progress updates
-Rudimentary Priority Modes-
Worker availability is effected by a two different modes: round_robin and fill_up. In round_robin mode, the next available worker is gathered in your typical round_robin fashion. And in fill_up mode, the same worker will continue to be gathered until it's work queue is full.
-Abstract Jobs-
The simple Job Role provides a light shell for whatever needs to be processed, but at the same time giving the framework some consistency for reporting progress, and identification.
And while those things are awesome, there is still room for improvement down the road. The API could be expanded a little further in the WorkerPool itself with regards to how the jobs get delivered. So there will be future releases as I work more on it.
To that end, the POEx::WorkerPool does the usual multi-process management and provides a mechanism to dole out jobs to workers, but where I feel it provides more bang for you buck is highlighted below.
-Easier Customization-
Each piece in the framework can be customized via traits defined in the 'use' statements of those pieces. Each piece does light coupling via Roles checking, so it doesn't hinder customization.
-Transparent Workers-
Workers publish a plethora of events via POEx::PubSub that allow for tracking of a job from the time the worker starts processing to even incremental progress updates
-Rudimentary Priority Modes-
Worker availability is effected by a two different modes: round_robin and fill_up. In round_robin mode, the next available worker is gathered in your typical round_robin fashion. And in fill_up mode, the same worker will continue to be gathered until it's work queue is full.
-Abstract Jobs-
The simple Job Role provides a light shell for whatever needs to be processed, but at the same time giving the framework some consistency for reporting progress, and identification.
And while those things are awesome, there is still room for improvement down the road. The API could be expanded a little further in the WorkerPool itself with regards to how the jobs get delivered. So there will be future releases as I work more on it.
Thursday, August 27, 2009
Introducing new tools
It is exciting to get into a new project and inject new ideas and tools. The project that I am talking about is a generic report runner pulling its information from a database.
In its current incarnation it spins up from cron, and runs reports one at a time, but it now needs to run multiple reports including bulk reports. To do that I am making heavy use of POE, and a worker process pool. And, I am getting to use my own tools such as POEx::Role::SessionInstantiation, in addition to other great tools like MooseX::Declare.
Not only that, but I pulled in local::lib for dev purposes, and Dist::Zilla to handle the disitribution creation.
It's like being a kid in a toy store.
In its current incarnation it spins up from cron, and runs reports one at a time, but it now needs to run multiple reports including bulk reports. To do that I am making heavy use of POE, and a worker process pool. And, I am getting to use my own tools such as POEx::Role::SessionInstantiation, in addition to other great tools like MooseX::Declare.
Not only that, but I pulled in local::lib for dev purposes, and Dist::Zilla to handle the disitribution creation.
It's like being a kid in a toy store.
Thursday, August 20, 2009
Of POE + Moose Awesomeness
So Florian finally dropped the bomb. Devel::Declare, MooseX::Method::Signatures, and MooseX::Declare were all released with all of the wholesome developed goodness that I wrote before YAPC::NA. So what does that mean? It means that I was able to finally release to CPAN a few modules.
POEx::Role::SessionInstantiation is the core of it all. It turns your Moose objects into POE::Sessions and manages the ugly for you.
POEx::Role::TCPClient builds on POEx::Role::SessionInstantiation and rolls up the common SocketFactory/ReadWrite wheels and gives you awesome functionality with minimal effort.
POEx::Role::TCPServer does the same thing as TCPClient, but in reverse.
I chose to stay the lower level for the roles because I found those pieces of the POE world ripe for Moosifying. The upper level Components are a bit unwieldy and I am not a big fan of them.
And once I work the kinks out of POEx::ProxySession, I'll be doing a release of that. I decided to add some more functionality with regards to getting notified from the POEx::ProxySession::Client when TCPClient fires socket errors and connect errors.
And then I'll be able to release an alpha of Voltron. Florian brought the parsed signature attribute on MooseX::Method::Signatures::Meta::Method up to public so that means I can rely on it now for doing signature comparisons instead of dumb string comparsons that I am doing now.
Expect to hear more soon on this front. I'm rather excited about getting to release my modules finally.
POEx::Role::SessionInstantiation is the core of it all. It turns your Moose objects into POE::Sessions and manages the ugly for you.
POEx::Role::TCPClient builds on POEx::Role::SessionInstantiation and rolls up the common SocketFactory/ReadWrite wheels and gives you awesome functionality with minimal effort.
POEx::Role::TCPServer does the same thing as TCPClient, but in reverse.
I chose to stay the lower level for the roles because I found those pieces of the POE world ripe for Moosifying. The upper level Components are a bit unwieldy and I am not a big fan of them.
And once I work the kinks out of POEx::ProxySession, I'll be doing a release of that. I decided to add some more functionality with regards to getting notified from the POEx::ProxySession::Client when TCPClient fires socket errors and connect errors.
And then I'll be able to release an alpha of Voltron. Florian brought the parsed signature attribute on MooseX::Method::Signatures::Meta::Method up to public so that means I can rely on it now for doing signature comparisons instead of dumb string comparsons that I am doing now.
Expect to hear more soon on this front. I'm rather excited about getting to release my modules finally.
Tuesday, August 11, 2009
Working with Rakudo and Parrot
So after pmichaud had a call for applications for Rakudo, I came to a small epiphany that perhaps I should work on a naive port of POE to Rakudo. So this past weekend came and I started to do a little investigative work on what it would take to do POE on Rakudo. The first step is to get the core loop running. In Perl5 terms this means that select(2) needs to exist. In Perl5 world, select() is for the most part a C equivalent. There is another version of select() but that doesn't concern us.
Anyhow, select() let's us do synchronous multiplexing of IO across multiple filedescriptors. This is how POE does it's magic. As things come back from select() placed into the things-to-watch queue via POE::Kernel->select_read and select_write, those are placed into the Queue and get mingled in with all of the rest of the events that need to be dispatched. This is an obviously very simplified explanation.
So the first thing I did was go into various IRC channels to ask some very pertinent questions such as where is select() implemented? I dug around in the classes defined by Rakudo but could not find a definition of select. But someone pointed me in a couple of different directions and referred me to a couple of different people that were interested in the same topic.
Ultimately, it came down to this. I took a look-see into the Parrot source and found that, no, select was not implemented as a generic plain-old C-like call you could make. Instead, each of the Parrot socket objects have a method, poll, that will return to do it's status, if any. Internally, it uses select(2) to do this for the unixy source file anyhow.
Unfortunately, Rakudo has no parallel in the IO classes because it was decided to /remove/ select(2) (including the other version) from the spec. Apparently, people wanted to roll that up into the concurrency layer that doesn't really exist yet, because it is pretty instrumental in event loops. In the mean time, I'm for the most part stuck. Sure I could do a IO::Select port to Rakudo (and had planned to do just that), but I would have to implement it using the non-portable Q:PIR construct and call down to the Parrot sockets methods. I'd have to learn PIR, ontop of any augmentation to Perl6 that I barely know. Plus, it would only work on the Rakudo implementation due to the use of inline PIR.
With that said, I decided to stop looking at doing a naive port until the IO layer is fleshed out a bit more and I have safer abstractions from which I can do simple things like use a select-like idiom that is extremely common for writing socket based network servers. The Parrot and the Rakudo projects have come a very long way in their years of development, but I just don't have the time to be writing core infrastructure pieces and also maintain and further develop my other modules. I really understand the catch-22 that Rakudo and Perl6 in general have when it comes to specs vs implementations, but I can't really do much to fix it without investing a lot of time and effort coming up to speed on the thoughts behind a lot of the decisions (such as removing select()).
I tried to approach this project from the perspective of bringing current Perl5 tools forward to the Perl6 world. That means attempting a naive, get it running, port that doesn't bother with any of the new fancy idioms. At most, I wanted to adjust the sigils, and do some light source filtering by hand to cover the large breakages. Document what I found for other projects looking to do the same. And go from there. I couldn't really get to square one because of the specification vs. implementation situation.
So while I certainly sympathize with these projects, I just don't feel they are ready yet for the casual developer (eg. me) to even take the first steps. I would like to at least revisit the issue for the Rakudo Star release, however, given more of the IO layer has been implemented and I can do what I want without resorting to platform specific inline assembly.
Let the flames begin :-/
Anyhow, select() let's us do synchronous multiplexing of IO across multiple filedescriptors. This is how POE does it's magic. As things come back from select() placed into the things-to-watch queue via POE::Kernel->select_read and select_write, those are placed into the Queue and get mingled in with all of the rest of the events that need to be dispatched. This is an obviously very simplified explanation.
So the first thing I did was go into various IRC channels to ask some very pertinent questions such as where is select() implemented? I dug around in the classes defined by Rakudo but could not find a definition of select. But someone pointed me in a couple of different directions and referred me to a couple of different people that were interested in the same topic.
Ultimately, it came down to this. I took a look-see into the Parrot source and found that, no, select was not implemented as a generic plain-old C-like call you could make. Instead, each of the Parrot socket objects have a method, poll, that will return to do it's status, if any. Internally, it uses select(2) to do this for the unixy source file anyhow.
Unfortunately, Rakudo has no parallel in the IO classes because it was decided to /remove/ select(2) (including the other version) from the spec. Apparently, people wanted to roll that up into the concurrency layer that doesn't really exist yet, because it is pretty instrumental in event loops. In the mean time, I'm for the most part stuck. Sure I could do a IO::Select port to Rakudo (and had planned to do just that), but I would have to implement it using the non-portable Q:PIR construct and call down to the Parrot sockets methods. I'd have to learn PIR, ontop of any augmentation to Perl6 that I barely know. Plus, it would only work on the Rakudo implementation due to the use of inline PIR.
With that said, I decided to stop looking at doing a naive port until the IO layer is fleshed out a bit more and I have safer abstractions from which I can do simple things like use a select-like idiom that is extremely common for writing socket based network servers. The Parrot and the Rakudo projects have come a very long way in their years of development, but I just don't have the time to be writing core infrastructure pieces and also maintain and further develop my other modules. I really understand the catch-22 that Rakudo and Perl6 in general have when it comes to specs vs implementations, but I can't really do much to fix it without investing a lot of time and effort coming up to speed on the thoughts behind a lot of the decisions (such as removing select()).
I tried to approach this project from the perspective of bringing current Perl5 tools forward to the Perl6 world. That means attempting a naive, get it running, port that doesn't bother with any of the new fancy idioms. At most, I wanted to adjust the sigils, and do some light source filtering by hand to cover the large breakages. Document what I found for other projects looking to do the same. And go from there. I couldn't really get to square one because of the specification vs. implementation situation.
So while I certainly sympathize with these projects, I just don't feel they are ready yet for the casual developer (eg. me) to even take the first steps. I would like to at least revisit the issue for the Rakudo Star release, however, given more of the IO layer has been implemented and I can do what I want without resorting to platform specific inline assembly.
Let the flames begin :-/
Subscribe to:
Posts (Atom)