[Bps-public-commit] Prophet branch, master, updated. 116cc80beb996dac8a3e388c441da8346281e1a1

jesse jesse at bestpractical.com
Fri Apr 17 03:00:18 EDT 2009


The branch, master has been updated
       via  116cc80beb996dac8a3e388c441da8346281e1a1 (commit)
       via  a0c1ba27ddcd4c4a1eb86aa4e64d5c114e716677 (commit)
       via  b0d1242e3ea82747e8f6deb04c8f60da112bdeee (commit)
       via  0cc8326a7e20729af9b4f54dc1336de160a6eb5c (commit)
       via  1c6eb21b0d628528bf571c349d934f23e78d2844 (commit)
       via  1dea11849ccca5a775e3eb142c4b82749e679d0d (commit)
       via  d2d32cb41164449dd573ff840a055b6a2d0df3a5 (commit)
      from  b39f00a9f3e3f9bf6f951713816a9c5393b4a07d (commit)

Summary of changes:
 lib/Prophet/CLI/Command/Merge.pm |    3 +-
 lib/Prophet/CLI/MirrorCommand.pm |    5 ++
 lib/Prophet/ChangeSet.pm         |   27 ++++++++++++
 lib/Prophet/FilesystemReplica.pm |   14 ++++--
 lib/Prophet/Replica/sqlite.pm    |   88 +++++++++++++++++++++++++------------
 lib/Prophet/Server.pm            |    9 +++-
 lib/Prophet/Server/Dispatcher.pm |   48 ++++++++++++++++++++-
 7 files changed, 156 insertions(+), 38 deletions(-)

- Log -----------------------------------------------------------------
commit d2d32cb41164449dd573ff840a055b6a2d0df3a5
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Fri Apr 17 14:53:32 2009 +0800

    Add new sha1 and canonical_json_representation methods to changesets

diff --git a/lib/Prophet/ChangeSet.pm b/lib/Prophet/ChangeSet.pm
index bd55550..f4e800c 100644
--- a/lib/Prophet/ChangeSet.pm
+++ b/lib/Prophet/ChangeSet.pm
@@ -2,6 +2,8 @@ package Prophet::ChangeSet;
 use Any::Moose;
 use Prophet::Change;
 use Params::Validate;
+use Digest::SHA1 qw/sha1_hex/;
+use JSON;
 
 has creator => (
     is  => 'rw',
@@ -58,6 +60,11 @@ has changes => (
     default    => sub { [] },
 );
 
+has sha1 => ( 
+    is => 'rw',
+    isa => 'Maybe[Str]'
+    );
+
 sub has_changes { scalar @{ $_[0]->changes } }
 sub _add_change {
     my $self = shift;
@@ -252,6 +259,26 @@ sub created_as_rfc3339 {
     return $c."Z";
 }
 
+sub calculate_sha1 {
+    my $self = shift;
+    return sha1_hex($self->canonical_json_representation);
+}
+
+sub canonical_json_representation {
+my $self = shift;
+    my $hash_changeset = $self->as_hash;
+    # These two things should never actually get stored
+     delete $hash_changeset->{'sequence_no'};
+     delete $hash_changeset->{'source_uuid'};
+
+
+    return to_json( $hash_changeset,
+                        { canonical => 1, pretty => 0, utf8 => 1 } );
+
+
+
+}
+
 __PACKAGE__->meta->make_immutable;
 no Any::Moose;
 

commit 1dea11849ccca5a775e3eb142c4b82749e679d0d
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Fri Apr 17 14:54:07 2009 +0800

    Restore count of merged changesets on merge

diff --git a/lib/Prophet/CLI/Command/Merge.pm b/lib/Prophet/CLI/Command/Merge.pm
index 44462a1..eb9e229 100644
--- a/lib/Prophet/CLI/Command/Merge.pm
+++ b/lib/Prophet/CLI/Command/Merge.pm
@@ -44,7 +44,6 @@ sub run {
 sub print_report {
     my $self = shift;
     my $changesets = shift;
-    print "\n";
     if ($changesets == 0) {
         print "No new changesets.\n";
     }
@@ -104,7 +103,7 @@ sub _do_merge {
             $changesets++;
         };
     } else {
-        $import_args{reporting_callback} = $self->progress_bar( max => ($source_latest - $source_last_seen), format => "%30b %p %E\r" );
+        $import_args{reporting_callback} = sub { $changesets++; $self->progress_bar( max => ($source_latest - $source_last_seen), format => "%30b %p %E\r" );}
     }
 
     $self->target->import_changesets( %import_args);

commit 1c6eb21b0d628528bf571c349d934f23e78d2844
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Fri Apr 17 14:54:44 2009 +0800

    Add feedback to the user that a mirror is already up to date on NOOP sync

diff --git a/lib/Prophet/CLI/MirrorCommand.pm b/lib/Prophet/CLI/MirrorCommand.pm
index 1a1934a..7771cb9 100644
--- a/lib/Prophet/CLI/MirrorCommand.pm
+++ b/lib/Prophet/CLI/MirrorCommand.pm
@@ -22,6 +22,11 @@ sub sync_cache_from_source {
     my $self = shift;
     my %args = validate(@_, { target => { isa => 'Prophet::Replica::prophet_cache'}, source => { isa => 'Prophet::Replica'}});
 
+    if ($args{target}->latest_sequence_no == $args{source}->latest_sequence_no) {
+        print "Mirror of ".$args{source}->url. " is already up to date\n";
+        return 
+    }
+
     print "Mirroring resolutions from " . $args{source}->url . "\n";
     $args{target}->resolution_db_handle->mirror_from(
         source => $args{source}->resolution_db_handle,

commit 0cc8326a7e20729af9b4f54dc1336de160a6eb5c
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Fri Apr 17 14:55:36 2009 +0800

    add a send_replica_content method

diff --git a/lib/Prophet/Server.pm b/lib/Prophet/Server.pm
index 5538fa5..253ada0 100644
--- a/lib/Prophet/Server.pm
+++ b/lib/Prophet/Server.pm
@@ -286,11 +286,18 @@ sub serve_replica {
         return undef unless $self->handle->can('read_file');
         my $content = $self->handle->read_file($repo_file);
         return unless defined $content && length($content);
+        $self->send_replica_content($content);
+    }
+
+sub send_replica_content {
+    my $self = shift;
+    my $content = shift;
         return $self->send_content(
             content_type => 'application/x-prophet',
             content      => $content
         );
-    }
+
+}
 
 sub show_template {
     my $self = shift;

commit b0d1242e3ea82747e8f6deb04c8f60da112bdeee
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Fri Apr 17 14:56:06 2009 +0800

    Added a method to filesystem replicas to fetch serialized changesets by their sha1

diff --git a/lib/Prophet/FilesystemReplica.pm b/lib/Prophet/FilesystemReplica.pm
index c098b0c..faf9ce0 100644
--- a/lib/Prophet/FilesystemReplica.pm
+++ b/lib/Prophet/FilesystemReplica.pm
@@ -242,10 +242,8 @@ sub _get_changeset_index_entry {
     # XXX: deserialize the changeset content from the cas with $key
     my ( $seq, $orig_uuid, $orig_seq, $key )  =@{ $self->_changeset_index_entry(%args)};
 
-    my $casfile = $self->changeset_cas->filename($key);
-
     my $changeset = $self->_deserialize_changeset(
-        content              => $self->_read_file($casfile),
+        content              => $self->fetch_serialized_changeset(sha1 => $key),
         original_source_uuid => $orig_uuid,
         original_sequence_no => $orig_seq,
         sequence_no          => $seq
@@ -253,6 +251,14 @@ sub _get_changeset_index_entry {
 
     return $changeset;
 }
+
+sub fetch_serialized_changeset {
+    my $self = shift;
+    my %args = validate(@_, { sha1 => 1 });
+    my $casfile = $self->changeset_cas->filename($args{sha1});
+    return $self->_read_file($casfile);
+}
+
 sub _get_changeset_index_handle {
     my $self = shift;
 
@@ -273,7 +279,7 @@ sub lwp_get {
             return $response->decoded_content;
         }
     }
-    warn "Could not fetch" . $url . " - " . $response->status_line;
+    warn "Could not fetch " . $url . " - " . $response->status_line;
     return undef;
 }
           

commit a0c1ba27ddcd4c4a1eb86aa4e64d5c114e716677
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Fri Apr 17 14:56:54 2009 +0800

    Add a fetch_serialized_changeset method which emulates what the filesystem replicas do

diff --git a/lib/Prophet/Replica/sqlite.pm b/lib/Prophet/Replica/sqlite.pm
index 0aae52f..3743ba8 100644
--- a/lib/Prophet/Replica/sqlite.pm
+++ b/lib/Prophet/Replica/sqlite.pm
@@ -408,6 +408,7 @@ sub traverse_changesets {
             callback => 1,
             until    => 0,
             reverse  => 0,
+            load_changesets => { default => 1 }
         }
     );
 
@@ -421,10 +422,17 @@ sub traverse_changesets {
     $self->log_debug("Traversing changesets between $first_rev and $latest");
     my @range = ( $first_rev .. $latest );
     @range = reverse @range if $args{reverse};
-    for my $rev ( @range ) {
+    for my $rev (@range) {
         $self->log_debug("Fetching changeset $rev");
-        my $changeset = $self->_load_changeset_from_db( sequence_no => $rev,);
-        $args{callback}->($changeset);
+        my $data;
+        if ( $args{load_changesets} ) {
+            $data = $self->_load_changeset_from_db( sequence_no => $rev );
+        } else {
+            my $row = $self->_load_changeset_metadata_from_db( sequence_no => $rev );
+            $data = [ $row->{sequence_no}, $row->{original_source_uuid}, $row->{original_sequence_no}, $row->{sha1} ];
+
+        }
+        $args{callback}->($data);
     }
 }
 
@@ -459,27 +467,60 @@ sub changesets_for_record {
     return @changesets;
 }
 
-sub _load_changeset_from_db {
+
+sub fetch_serialized_changeset {
     my $self = shift;
-    my %args = validate( @_, {   sequence_no          => 1 });
+    my %args = validate(@_, { sha1 => 1 });
+    my $cs = $self->_load_changeset_from_db(sha1 => $args{sha1});
+    return $cs->canonical_json_representation;
+}   
 
+sub _load_changeset_from_db {
+    my $self = shift;
+    my %args = validate(
+        @_,
+        {   sequence_no => 0,
+            sha1        => 0
 
-    my $sth = $self->dbh->prepare("SELECT creator, created, sequence_no, ".
-                                  "original_source_uuid, original_sequence_no, ".
-                                  "is_nullification, is_resolution, sha1 from changesets ".
-                                  "WHERE sequence_no = ?");
-            $sth->execute($args{sequence_no});
+        }
+    );
+    my $data = $self->_load_changeset_metadata_from_db(%args);
+    return $self->_instantiate_changeset_from_db($data);
+}
 
+sub _load_changeset_metadata_from_db {
+    my $self = shift;
+    my %args = validate(
+        @_,
+        {   sequence_no => 0,
+            sha1        => 0
 
+        }
+    );
+    my ( $attr, @bind );
+    if ( $args{sequence_no} ) {
+        $attr = 'sequence_no';
+        @bind = ( $args{sequence_no} );
+    } elsif ( $args{sha1} ) {
+        $attr = 'sha1';
+        @bind = ( $args{sha1} );
+    } else {
+        die "$self->_load_changeset_from_db called with neither a sequence_no nor a sha1";
+    }
+    my $sth = $self->dbh->prepare( "SELECT creator, created, sequence_no, "
+            . "original_source_uuid, original_sequence_no, "
+            . "is_nullification, is_resolution, sha1 from changesets "
+            . "WHERE $attr = ?" );
+    $sth->execute(@bind);
     my $data = $sth->fetchrow_hashref;
-    return $self->_instantiate_changeset_from_db($data);
+
 }
 
+
 sub _instantiate_changeset_from_db {
     my $self = shift;
     my $data = shift;
     require Prophet::ChangeSet;
-    my $sha1 = delete $data->{sha1};
     my $changeset = Prophet::ChangeSet->new(%$data, source_uuid => $self->uuid );
 
     
@@ -499,9 +540,12 @@ sub _instantiate_changeset_from_db {
         push @{$changeset->changes}, $change;
     }
 
-    if(!$sha1) {
+    if(!$data->{sha1}) {
+        my $sha1 = $changeset->calculate_sha1();
          my $update_sth = $self->dbh->prepare('UPDATE changesets set sha1 = ? where sequence_no = ?');
-        $update_sth->execute($self->_calculate_changeset_sha1($changeset), $changeset->sequence_no);
+        $update_sth->execute($sha1, $changeset->sequence_no);
+        $changeset->sha1($sha1);
+
     }
 
     return $changeset;
@@ -545,25 +589,11 @@ sub commit_edit {
     $self->current_edit(undef);
 }
 
-sub _calculate_changeset_sha1 {
-my $self = shift;
-my $changeset = shift;
-    my $hash_changeset = $changeset->as_hash;
-    # These two things should never actually get stored
-    my $seqno = delete $hash_changeset->{'sequence_no'};
-    my $uuid  = delete $hash_changeset->{'source_uuid'};
-
-    my $sha1 = sha1_hex(to_json( $hash_changeset,
-                        { canonical => 1, pretty => 0, utf8 => 1 } ));
-
-    return $sha1;
-}
-
 sub _write_changeset_to_db {
     my $self = shift;
     my $changeset = shift;
 
-    my $sha1 = $self->_calculate_changeset_sha1($changeset);
+    my $sha1 = $changeset->calculate_sha1();
 
     $self->dbh->do(
         "INSERT INTO changesets "

commit 116cc80beb996dac8a3e388c441da8346281e1a1
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Fri Apr 17 14:57:52 2009 +0800

    make standalone server's "serve the replica" functionality use a facade so it works with sqlite replicas

diff --git a/lib/Prophet/Server/Dispatcher.pm b/lib/Prophet/Server/Dispatcher.pm
index 129acb9..0d11f41 100644
--- a/lib/Prophet/Server/Dispatcher.pm
+++ b/lib/Prophet/Server/Dispatcher.pm
@@ -24,12 +24,56 @@ under { method => 'GET' } => sub {
     on qr'^/=/prophet/autocomplete' => sub {
         shift->server->show_template('/_prophet_autocompleter') };
     on qr'^/static/prophet/(.*)$' => sub { shift->server->send_static_file($1)};
-    on qr'^/replica/+(.*)$' => sub { shift->server->serve_replica($1) };
-    on qr'^/records.json' => sub { shift->server->get_record_types };
+
+   on qr'^/records.json' => sub { shift->server->get_record_types };
     under qr'/records' => sub {
         on qr|^/(.*)/(.*)/(.*)$| => sub { shift->server->get_record_prop($1,$2,$3); };
         on qr|^/(.*)/(.*).json$| => sub { shift->server->get_record($1,$2) };
         on qr|^/(.*).json$|      => sub { shift->server->get_record_list($1) };
+
+    };
+
+    on qr'^/replica(/resolutions)?' => sub {
+        my $self = shift;
+        if ($1 && $1 eq '/resolutions') {
+            $_->metadata->{replica_handle} = $self->server->app_handle->handle->resolution_db_handle;
+        } else {
+            $_->metadata->{replica_handle} = $self->server->app_handle->handle;
+        }
+        next_rule;
+    };
+
+    under qr'^/replica(/resolutions/)?' => sub {
+        on 'replica-version' => sub { shift->server->send_replica_content('1')};
+        on 'replica-uuid' => sub { my $self = shift; $self->server->send_replica_content( $_->metadata->{replica_handle}->uuid ); };
+        on 'database-uuid' => sub { my $self = shift; $self->server->send_replica_content( $_->metadata->{replica_handle}->db_uuid ); };
+        on 'latest-sequence-no' => sub { my $self = shift; $self->server->send_replica_content( $_->metadata->{replica_handle}->latest_sequence_no ); };
+        
+        on 'changesets.idx' => sub {
+            my $self  = shift;
+            my $index = '';
+            $_->metadata->{replica_handle}->traverse_changesets(
+                after=> 0,
+                load_changesets => 0,
+                callback => sub {
+                    my $data            = shift;
+                    my $changeset_index_line = pack( 'Na16NH40',
+                        $data->[0],
+                        Data::UUID->new->from_string( $data->[1]),
+                        $data->[2],
+                        $data->[3]);
+                    $index .= $changeset_index_line;
+                }
+            );
+            $self->server->send_replica_content($index);
+        };
+        on qr|cas/changesets/././(.{40})$| => sub {
+            my $self = shift;
+            my $sha1 = $1;
+            $self->server->send_replica_content($_->metadata->{replica_handle}->fetch_serialized_changeset(sha1 => $sha1));
+        } ;
+
+
     };
 };
 

-----------------------------------------------------------------------



More information about the Bps-public-commit mailing list