[Bps-public-commit] r11660 - in Prophet/trunk: . lib/Prophet/Handle

jesse at bestpractical.com jesse at bestpractical.com
Tue Apr 8 23:51:33 EDT 2008


Author: jesse
Date: Tue Apr  8 23:51:32 2008
New Revision: 11660

Modified:
   Prophet/trunk/   (props changed)
   Prophet/trunk/Makefile.PL
   Prophet/trunk/lib/Prophet/Handle.pm
   Prophet/trunk/lib/Prophet/Handle/SVN.pm

Log:
 r29543 at 31b:  jesse | 2008-04-08 23:51:19 -0400
 * Specced out the methods that a handle class needs to implement.


Modified: Prophet/trunk/Makefile.PL
==============================================================================
--- Prophet/trunk/Makefile.PL	(original)
+++ Prophet/trunk/Makefile.PL	Tue Apr  8 23:51:32 2008
@@ -15,19 +15,18 @@
 requires('Test::Exception');
 requires('Acme::MetaSyntactic');
 requires('UNIVERSAL::require');
-requires('App::Cache');
 requires('Class::Data::Inheritable');
 requires('DateTime::Format::HTTP');
 requires('Devel::Gladiator');
 requires('RT::Client::REST');
 requires('RT::Client::REST::Ticket');
 requires('RT::Client::REST::User');
-requires('SVB::Record');
 requires('Term::ReadKey');
 requires('Digest::SHA1');
 requires('LWP::Simple');
 requires('URI');
 requires('JSON');
+requires('Module::Pluggable');
 requires('Test::HTTP::Server::Simple');
 requires('HTTP::Server::Simple');
 requires('Test::WWW::Mechanize');

Modified: Prophet/trunk/lib/Prophet/Handle.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Handle.pm	(original)
+++ Prophet/trunk/lib/Prophet/Handle.pm	Tue Apr  8 23:51:32 2008
@@ -34,7 +34,7 @@
 
 sub integrate_changeset {
     my $self      = shift;
-    my $changeset = shift;
+    my ($changeset) = validate_pos(@_, { isa => 'Prophet::ChangeSet'});
 
     $self->begin_edit();
     $self->record_changeset($changeset);
@@ -42,10 +42,19 @@
     $self->commit_edit();
 }
 
+=head2 record_resolutions Prophet::ChangeSet, (Prophet::Handle, a resolution database handle)
+
+Given a resolution changeset and a resolution database handle,
+record all the resolution changesets as well as resolution records
+in the content-addressed-store.
+
+Called ONLY on local resolution creation. (Synced resolutions are just synced as records)
+
+=cut
+
 sub record_resolutions {
     my $self       = shift;
-    my $changeset  = shift;
-    my $res_handle = shift;
+    my ($changeset, $res_handle) = validate_pos(@_, { isa => 'Prophet::ChangeSet'}, { isa => 'Prophet::Handle'});
 
     return unless $changeset->changes;
 
@@ -55,14 +64,15 @@
     $self->commit_edit();
 }
 
-=head2 record_resolution
-
+=head2 record_resolution Prophet::Change
+ 
 Called ONLY on local resolution creation. (Synced resolutions are just synced as records)
 
 =cut
 
 sub record_resolution {
-    my ( $self, $change ) = @_;
+    my $self      = shift;
+    my ($change) = validate_pos(@_, { isa => 'Prophet::Change'});
 
     return 1 if $self->node_exists(
         uuid => $self->uuid,
@@ -79,16 +89,23 @@
     );
 }
 
+=head2 record_changeset Prophet::ChangeSet
+
+Inside an edit (transaction), integrate all changes in this transaction
+and then call the _post_process_integrated_changeset() hook
+
+=cut
+
 sub record_changeset {
     my $self      = shift;
-    my $changeset = shift;
+    my ($changeset) = validate_pos(@_, { isa => 'Prophet::ChangeSet'});
 
     eval {
 
         my $inside_edit = $self->current_edit ? 1 : 0;
         $self->begin_edit() unless ($inside_edit);
         $self->_integrate_change($_) for ( $changeset->changes );
-        $self->_cleanup_integrated_changeset($changeset);
+        $self->_post_process_integrated_changeset($changeset);
 
         $self->commit_edit() unless ($inside_edit);
     };
@@ -97,7 +114,7 @@
 
 sub _integrate_change {
     my $self   = shift;
-    my $change = shift;
+    my ($change) = validate_pos(@_, { isa => 'Prophet::Change'});
 
     my %new_props = map { $_->name => $_->new_value } $change->prop_changes;
 
@@ -151,6 +168,14 @@
     return $self->_record_metadata_for( $MERGETICKET_METATYPE, $source_uuid, 'last-changeset', $sequence_no );
 }
 
+=head2 metadata_storage $RECORD_TYPE, $PROPERTY_NAME
+
+Returns a function which takes a UUID and an optional value to get (or set) metadata rows in a metadata table.
+We use this to record things like merge tickets
+
+
+=cut
+
 sub metadata_storage {
     my $self = shift;
     my ( $type, $prop_name ) = validate_pos( @_, 1, 1 );
@@ -192,4 +217,77 @@
     );
 }
 
+=head1 DATA STORE API
+
+=head1 The following functions need to be implemented by any Prophet backing store.
+
+=head2 uuid
+
+Returns this replica's UUID
+
+=head2 create_node { type => $TYPE, uuid => $uuid, props => { key-value pairs }}
+
+Create a new record of type C<$type> with uuid C<$uuid>  within the current replica.
+
+Sets the record's properties to the key-value hash passed in as the C<props> argument.
+
+If called from within an edit, it uses the current edit. Otherwise it manufactures and finalizes one of its own.
+
+
+
+=head2 delete_node {uuid => $uuid, type => $type }
+
+Deletes the node C<$uuid> of type C<$type> from the current replica. 
+
+Manufactures its own new edit if C<$self->current_edit> is undefined.
+
+=head2 set_node_props { uuid => $uuid, type => $type, props => {hash of kv pairs }}
+
+
+Updates the record of type C<$type> with uuid C<$uuid> to set each property defined by the props hash. It does NOT alter any property not defined by the props hash.
+
+Manufactures its own current edit if none exists.
+
+
+=head2 get_node_props {uuid => $uuid, type => $type, root => $root }
+
+Returns a hashref of all properties for the record of type $type with uuid C<$uuid>.
+
+'root' is an optional argument which you can use to pass in an alternate historical version of the replica to inspect.  Code to look at the immediately previous version of a record might look like:
+
+    $handle->get_node_props(
+        type => $record->type,
+        uuid => $record->uuid,
+        root => $self->repo_handle->fs->revision_root( $self->repo_handle->fs->youngest_rev - 1 )
+    );
+
+=head2 node_exists {uuid => $uuid, type => $type, root => $root }
+
+Returns true if the node in question exists. False otherwise
+
+
+=head2 enumerate_nodes { type => $type }
+
+Returns a reference to a list of all the records of type $type
+
+=head2 enumerate_nodes
+
+Returns a reference to a list of all the known types in your Prophet database
+
+
+=head2 type_exists { type => $type }
+
+Returns true if we have any nodes of type C<$type>
+
+
+
+=cut
+
+
+
+=head2 The following functions need to be implemented by any _writable_ prophet backing store
+
+=cut
+
+
 1;

Modified: Prophet/trunk/lib/Prophet/Handle/SVN.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Handle/SVN.pm	(original)
+++ Prophet/trunk/lib/Prophet/Handle/SVN.pm	Tue Apr  8 23:51:32 2008
@@ -84,7 +84,7 @@
     return CREATED_DB_UUID;
 }
 
-sub _cleanup_integrated_changeset {
+sub _post_process_integrated_changeset {
     my $self = shift;
     my ($changeset) = validate_pos( @_, { isa => 'Prophet::ChangeSet' } );
 
@@ -172,7 +172,7 @@
     my $inside_edit = $self->current_edit ? 1 : 0;
     $self->begin_edit() unless ($inside_edit);
 
-    my $file = $self->file_for( uuid => $args{uuid}, type => $args{'type'} );
+    my $file = $self->_file_for( uuid => $args{uuid}, type => $args{'type'} );
     $self->current_edit->root->make_file($file);
     {
         my $stream = $self->current_edit->root->apply_text( $file, undef );
@@ -193,7 +193,7 @@
     my $self = shift;
     my %args = validate( @_, { uuid => 1, props => 1, type => 1 } );
 
-    my $file = $self->file_for( uuid => $args{uuid}, type => $args{type} );
+    my $file = $self->_file_for( uuid => $args{uuid}, type => $args{type} );
     foreach my $prop ( keys %{ $args{'props'} } ) {
         eval { $self->current_edit->root->change_node_prop( $file, $prop, $args{'props'}->{$prop}, undef ) };
         Carp::confess($@) if ($@);
@@ -215,7 +215,7 @@
     my $inside_edit = $self->current_edit ? 1 : 0;
     $self->begin_edit() unless ($inside_edit);
 
-    $self->current_edit->root->delete( $self->file_for( uuid => $args{uuid}, type => $args{type} ) );
+    $self->current_edit->root->delete( $self->_file_for( uuid => $args{uuid}, type => $args{type} ) );
     $self->commit_edit() unless ($inside_edit);
     return 1;
 }
@@ -236,7 +236,7 @@
     my $inside_edit = $self->current_edit ? 1 : 0;
     $self->begin_edit() unless ($inside_edit);
 
-    my $file = $self->file_for( uuid => $args{uuid}, type => $args{'type'} );
+    my $file = $self->_file_for( uuid => $args{uuid}, type => $args{'type'} );
     $self->_set_node_props(
         uuid  => $args{uuid},
         props => $args{props},
@@ -265,25 +265,25 @@
     my $self = shift;
     my %args = validate( @_, { uuid => 1, type => 1, root => undef } );
     my $root = $args{'root'} || $self->current_root;
-    return $root->node_proplist( $self->file_for( uuid => $args{'uuid'}, type => $args{'type'} ) );
+    return $root->node_proplist( $self->_file_for( uuid => $args{'uuid'}, type => $args{'type'} ) );
 }
 
-=head2 file_for { uuid => $UUID, type => $type }
+=head2 _file_for { uuid => $UUID, type => $type }
 
 Returns a file path within the repository (starting from the root)
 
 =cut
 
-sub file_for {
+sub _file_for {
     my $self = shift;
     my %args = validate( @_, { uuid => 1, type => 1 } );
     Carp::cluck unless $args{uuid};
-    my $file = join( "/", $self->directory_for_type( type => $args{'type'} ), $args{'uuid'} );
+    my $file = join( "/", $self->_directory_for_type( type => $args{'type'} ), $args{'uuid'} );
     return $file;
 
 }
 
-sub directory_for_type {
+sub _directory_for_type {
     my $self = shift;
     my %args = validate( @_, { type => 1 } );
     Carp::cluck unless defined $args{type};
@@ -302,27 +302,47 @@
     my %args = validate( @_, { uuid => 1, type => 1, root => undef } );
 
     my $root = $args{'root'} || $self->current_root;
-    return $root->check_path( $self->file_for( uuid => $args{'uuid'}, type => $args{'type'} ) );
+    return $root->check_path( $self->_file_for( uuid => $args{'uuid'}, type => $args{'type'} ) );
 
 }
 
+=head2 enumerate_nodes { type => $type }
+
+Returns a reference to a list of all the records of type $type
+
+=cut
+
 sub enumerate_nodes {
     my $self = shift;
     my %args = validate( @_ => { type => 1 } );
     return [ keys %{ $self->current_root->dir_entries( $self->db_uuid . '/' . $args{type} . '/' ) } ];
 }
 
+=head2 enumerate_types
+
+Returns a reference to a list of all the known types in your Prophet database
+
+=cut
+
 sub enumerate_types {
     my $self = shift;
     return [ keys %{ $self->current_root->dir_entries( $self->db_uuid . '/' ) } ];
 }
 
+
+=head2 type_exists { type => $type }
+
+Returns true if we have any nodes of type C<$type>
+
+=cut
+
+
 sub type_exists {
     my $self = shift;
     my %args = validate( @_, { type => 1, root => undef } );
 
     my $root = $args{'root'} || $self->current_root;
-    return $root->check_path( $self->directory_for_type( type => $args{'type'}, ) );
+    return $root->check_path( $self->_directory_for_type( type => $args{'type'}, ) );
 
 }
 



More information about the Bps-public-commit mailing list