cLive ;-) has asked for the wisdom of the Perl Monks concerning the following question:

Not quite sure what I should be looking for, but I'm trying to create a Moose object that is instantiated in one of two ways:

# initially from arguments my $obj = Pkg->new( arg1 => ..., arg2 => ... ); # subsequently, loaded from a frozen copy of the obj my $obj = Pkg->new( uuid => ... );

ie, if object instantiated from uuid, load frozen copy, else create as normal. On destroy, freeze current copy of object.

I did a quick search on Moose caching, but I'm not 100% sure what I need here to get this working as expected.

Can anyone point me in the right direction? I found MooseX::WithCache, but am not sure if that's the right tool - documentation is sparse.

All insights appreciated!

Thanks :)

Replies are listed 'Best First'.
Re: Creating a Moose object either from args or from cache
by jeffa (Bishop) on Sep 09, 2015 at 19:07 UTC

    Yeah, layers of abstraction tend to obscure error messages, making precise documentation necessary. How about this?

    package MyObject; use Moose; use MooseX::WithCache; with 'MooseX::WithCache' => { backend => 'Cache::FileCache' }; has uuid => ( is => 'rw', default => 0 ); has arg1 => ( is => 'rw' ); has arg2 => ( is => 'rw' ); no Moose; sub get_object { my $self = shift; my %args = @_; my $obj; if ($args{uuid}) { $obj = $self->cache_get( $args{uuid} ); } unless (ref $obj) { my $uuid = 42; # use real UUID generator! $obj = MyObject->new( %args, uuid => $uuid ); $self->cache_set( $uuid => $obj ); } return $obj; } package main; use Data::Dumper; use Cache::FileCache; my $object = MyObject->new( cache => Cache::FileCache->new ); my $foo = $object->get_object( arg1 => 'foo', arg2 => 'bar' ); print Dumper $foo; my $bar = $object->get_object( uuid => 42 ); print Dumper $bar;


    (the triplet paradiddle with high-hat)

      Thanks - that makes it a little clearer :D

      Got it working. Now all I need is a way to cache_set right before DEMOLISH(). I tried it within the DEMOLISH and ended up with recursion issues.

      Is there a way to call a method right before DEMOLISH is called. I just tried before 'DEMOLISH' as a hunch, and it didn't work as hoped :D

      As it stands, I'm just adding a bunch of after calls around the expensive, data creating methods.

        Yeah, I have had the same experiences.   Ordinarily, I define some kind of (say ...) free() method in such objects and am careful to call it before the object goes out of scope.   Also, as you imply, if the object carries-around with it a lot of data that I know is no longer needed, I define another method to explicitly release that data (if it exists).   Attempts to do that sort of thing “more automagically” did not seem to work as I had expected, but I also didn’t pursue the matter too much.   This arrangement based on self-discipline worked well, and it also gave me definite control over exactly when the operation would happen.

        Also, I have had some bad-experiences with freeze/thaw, in which the frozen data either could not be thawed or was not exactly the same.   For this reason, and for the added benefit of actually being able to see the saved data on inspection, I stored the data in JSON format within a database table.   And ... I actually embedded the freeze/thaw-equivalent functionality into a base class of my own devising.   (Now, I had definite control of it ...)

        So, in this case, I might write the method so that it accepted either uuid => uuid or data => hashref.   If given a uuid, it would look-up itself in the database (and die() if it could not be found.   Otherwise, it would instantiate itself, coining a uuid for itself, and snapshot its initial state into the database.   (It explicitly checked that the hashref contained all of the required keys, and that the values were plausible, and would die() on the spot if it smelled any smoke.)   And, once again, in a base class I did all of these things myself, consciously trading convenience for awareness and explicit control over exactly what was going on.   (I never did figure out what was wrong with freeze/thaw on that machine:   some data worked just fine, but of course “some” isn’t good enough.)