die on errors, fix "Maximum message size exceeded"
[MojoFacets.git] / lib / MojoFacets / Import / CouchDB.pm
1 package MojoFacets::Import::CouchDB;
2
3 use warnings;
4 use strict;
5
6 use base 'Mojo::Base';
7
8 use File::Slurp;
9 use Data::Dump qw(dump);
10 use JSON;
11 use Mojo::UserAgent;
12
13 __PACKAGE__->attr('path');
14 __PACKAGE__->attr('full_path');
15
16 sub ext { '.couchdb' };
17
18 sub flatten {
19         my ($flat,$data,$prefix) = @_;
20         if ( ref $data eq '' ) {
21                 push @{ $$flat->{$prefix} }, $data;
22         } elsif ( ref $data eq 'HASH' ) {
23                 foreach my $key ( keys %$data ) {
24                         my $full_prefix = $prefix ? $prefix . '_' : '';
25                         $full_prefix .= $key;
26                         flatten( $flat, $data->{$key}, $full_prefix );
27                 }
28         } elsif ( ref $data eq 'ARRAY' ) {
29                 foreach my $el ( @$data ) {
30                         flatten( $flat, $el, $prefix );
31                 }
32         } elsif ( ref $data eq 'Mojo::JSON::_Bool' ) {
33                 push @{ $$flat->{$prefix} }, $data;
34         } else {
35                 die "unsupported ",ref($data)," from ",dump($data);
36         }
37 }
38
39 sub data {
40         my $self = shift;
41
42         my $path = $self->path;
43
44         my $url = read_file $self->full_path;
45
46         $url =~ s{/?\s*$}{}s;
47         $url .= '/_all_docs?include_docs=true' unless $url =~ m/\?/;
48
49         warn "# CouchDB URL: $url";
50
51         # fix "Maximum message size exceeded"
52         $ENV{MOJO_MAX_MESSAGE_SIZE} = 64 * 1024 * 1024;
53
54         my $tx = Mojo::UserAgent->new->get($url);
55         my ( $res, $json );
56
57         if ( my $res = $tx->success) {
58                 $json = $res->json;
59         } else {
60                 die $tx->error;
61         }
62
63         my $data;
64
65         if ( ref $json->{rows} eq 'ARRAY' ) {
66                 foreach my $doc ( @{$json->{rows}} ) {
67                         if ( exists $doc->{id} && exists $doc->{doc} ) {
68                                 next if $doc->{id} =~ m{^_design/}; # $doc->{id} == $doc->{doc}->{_id}
69                                 my $flat;
70                                 flatten( \$flat, $doc->{doc}, '' );
71                                 push @{ $data->{items} }, $flat;
72                         } else {
73                                 push @{ $data->{items} }, $doc;
74                         }
75                 }
76         } else {
77                 die "can't find rows in ",dump( $res->body );
78         }
79
80         return $data;
81
82 }
83
84 1