File Coverage

blib/lib/App/bif/sync.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package App::bif::sync;
2 1     1   1475 use strict;
  1         1  
  1         27  
3 1     1   3 use warnings;
  1         2  
  1         33  
4 1     1   904 use AnyEvent;
  1         4470  
  1         37  
5 1     1   400 use Bif::Sync::Client;
  0            
  0            
6             use Bif::Mo;
7             use Coro;
8             use DBIx::ThinSQL qw/qv/;
9              
10             our $VERSION = '0.1.5_5';
11             extends 'App::bif';
12              
13             sub run {
14             my $self = shift;
15             my $opts = $self->opts;
16             my $dbw = $self->dbw;
17              
18             # Consider upping PRAGMA cache_size? Or handle that in Bif::Role::Sync?
19             my @hubs = $dbw->xhashrefs(
20             select => [ 'h.id', 'n.name', 'h.location', 'n.uuid' ],
21             from => 'hubs h',
22             inner_join => 'nodes n',
23             on => 'n.id = h.id',
24             $opts->{hub} ? ( where => { 'n.name' => $opts->{hub} } ) : (),
25             order_by => 'n.name',
26             );
27              
28             return $self->err( 'SyncNone', 'no (matching) hubs found' )
29             unless @hubs;
30              
31             $|++; # no buffering
32              
33             foreach my $hub (@hubs) {
34             my $error;
35             my $cv = AE::cv;
36              
37             my $client = Bif::Sync::Client->new(
38             name => $hub->{name},
39             db => $dbw,
40             location => $hub->{location},
41             debug => $opts->{debug},
42             debug_bifsync => $opts->{debug_bifsync},
43             on_update => sub {
44             my $client = shift;
45             $self->lprint( $client->name . ': ' . $_[0] );
46             },
47             on_error => sub {
48             $error = shift;
49             $cv->send;
50             },
51             );
52              
53             my $fh = select;
54             my $coro = async {
55             select $fh;
56              
57             eval {
58             $dbw->txn(
59             sub {
60             $self->start_work(
61             node_id => $hub->{id},
62             start => time,
63             start_comment => "sync",
64             billable => 1,
65             save => 1,
66             );
67              
68             my @status = $client->sync_hub( $hub->{id} );
69              
70             unless ( $status[0] eq 'HubMatch'
71             or $status[0] eq 'HubSync' )
72             {
73             $dbw->rollback;
74             $error =
75             "unexpected HubSync/Match status received: @status";
76             return;
77              
78             }
79              
80             if ( $status[0] eq 'HubSync' ) {
81             @status = $client->transfer_hub_changes;
82             if ( $status[0] ne 'TransferHubChanges' ) {
83             $dbw->rollback;
84             $error =
85             "unexpected TransferHubChanges status received: @status";
86             return;
87             }
88             }
89              
90             print "\n";
91             $self->lprint('');
92             my $hub_id = $client->hub_id;
93             my @projects = $dbw->xhashrefs(
94             select_distinct =>
95             [ 'p2.id AS id', 'n.path AS path' ],
96             from => 'projects p',
97             inner_join => 'nodes_tree nt',
98             on => 'nt.parent = p.id',
99             inner_join => 'projects p2',
100             on => 'p2.id = nt.child AND p2.local = 1',
101             inner_join => 'nodes n',
102             on => 'n.id = p2.id',
103             where => {
104             'p.default_hub_id' => $hub_id,
105             },
106             );
107              
108             foreach my $project (@projects) {
109             $client->name("$hub->{name}\[$project->{path}\]");
110             my $status =
111             $client->sync_project( $project->{id} );
112             if ( $status eq 'ProjectSync' ) {
113             @status =
114             $client->transfer_project_related_changes;
115              
116             if ( $status[0] ne
117             'TransferProjectRelatedChanges' )
118             {
119             $dbw->rollback;
120             $error =
121             "unexpected TransferProjectRelatedChanges status received: @status";
122             return;
123             }
124             }
125             elsif ( $status ne 'ProjectMatch' ) {
126             $dbw->rollback;
127             $error =
128             "unexpected sync_project status received: $status";
129             return $status;
130             }
131              
132             print "\n";
133             $self->lprint('');
134             }
135              
136             $dbw->xdo(
137             insert_or_replace_into =>
138             [ 'bifkv', qw/key change_id change_id2/ ],
139             select =>
140             [ qv('last_sync'), 'MAX(c.id)', 'MAX(c.id)', ],
141             from => 'changes c',
142             );
143              
144             $self->stop_work(
145             stop => time,
146             restore => 1,
147             );
148              
149             return;
150             }
151             );
152             };
153              
154             if ($@) {
155             $error = $@;
156             print "\n";
157             }
158              
159             return $cv->send;
160             };
161              
162             $cv->recv;
163             $client->disconnect;
164              
165             return $self->err( 'Unknown', $error ) if $error;
166              
167             }
168              
169             # TODO make this dependent on how many changes received/made since the last
170             # analyze
171             $dbw->do('ANALYZE');
172              
173             return $self->ok('Sync');
174             }
175              
176             1;
177              
178             __END__