File Coverage

blib/lib/ElasticSearchX/UniqueKey.pm
Criterion Covered Total %
statement 12 103 11.6
branch 0 38 0.0
condition 0 15 0.0
subroutine 4 22 18.1
pod 12 13 92.3
total 28 191 14.6


line stmt bran cond sub pod time code
1             package ElasticSearchX::UniqueKey;
2             $ElasticSearchX::UniqueKey::VERSION = '0.05';
3 1     1   58332 use strict;
  1         3  
  1         35  
4 1     1   6 use warnings;
  1         2  
  1         30  
5 1     1   5 use Carp;
  1         6  
  1         923  
6              
7             #===================================
8             sub new {
9             #===================================
10 0     0 1   my $class = shift;
11 0           my %params = (
12             index => 'unique_key',
13 0 0         ref $_[0] ? %{ shift() } : @_
14             );
15 0           my $self = bless {}, $class;
16 0           for (qw(index es)) {
17 0 0         $self->{"_$_"} = $params{$_}
18             or croak "Missing required param $_";
19             }
20 0           return $self;
21             }
22              
23             #===================================
24             sub create {
25             #===================================
26 0     0 1   my $self = shift;
27 0           my %params = $self->_params( 'create', @_ );
28              
29 0 0         eval {
30 0           $self->es->create( %params, data => {} );
31 0           1;
32             }
33             && return 1;
34 0 0 0       return 0
35             if $@->isa('Search::Elasticsearch::Error::Conflict')
36             || $@->isa('ElasticSearch::Error::Conflict');
37 0           croak $@;
38             }
39              
40             #===================================
41             sub delete {
42             #===================================
43 0     0 1   my $self = shift;
44 0           my %params = $self->_params( 'delete', @_ );
45 0           $self->es->delete( %params, ignore_missing => 1 );
46             }
47              
48             #===================================
49             sub exists {
50             #===================================
51 0     0 1   my $self = shift;
52 0           my %params = $self->_params( 'exists', @_ );
53 0           $self->es->exists(%params);
54             }
55              
56             #===================================
57             sub update {
58             #===================================
59 0     0 1   my $self = shift;
60 0           my %params = $self->_params( 'update', shift(), shift() );
61 0           my $new_id = shift();
62 0 0 0       croak "No new id passed to update()"
63             unless defined $new_id and length $new_id;
64              
65 0           my ( $type, $old_id ) = @params{ 'type', 'id' };
66 0 0         return 1 if $new_id eq $old_id;
67 0 0         return unless $self->create( $type, $new_id );
68 0           $self->delete( $type, $old_id );
69 0           1;
70              
71             }
72              
73             #===================================
74             sub multi_create {
75             #===================================
76 0     0 1   my ( $self, %keys ) = @_;
77              
78 0           my @docs = map { { type => $_, id => $keys{$_}, data => {} } } keys %keys;
  0            
79              
80 0           my %failed;
81             $self->es->bulk_create(
82             index => $self->index,
83             docs => \@docs,
84             on_conflict => sub {
85 0     0     my ( $action, $doc ) = @_;
86 0           $failed{ $doc->{type} } = $doc->{id};
87             },
88             on_error => sub {
89 0     0     die "Error creating multi unique keys: $_[2]";
90             }
91 0           );
92 0 0         if (%failed) {
93 0           delete @keys{ keys %failed };
94 0           $self->multi_delete(%keys);
95             }
96 0           return %failed;
97             }
98              
99             #===================================
100             sub multi_delete {
101             #===================================
102 0     0 1   my ( $self, %keys ) = @_;
103              
104 0           my @docs = map { { type => $_, id => $keys{$_} } } keys %keys;
  0            
105              
106             $self->es->bulk_delete(
107             index => $self->index,
108             docs => \@docs,
109             on_error => sub {
110 0     0     die "Error deleting multi unique keys: $_[2]";
111             }
112 0           );
113 0           return 1;
114             }
115              
116             #===================================
117             sub multi_update {
118             #===================================
119 0     0 1   my $self = shift;
120 0 0         my %old = %{ shift() || {} };
  0            
121 0 0         my %new = %{ shift() || {} };
  0            
122 0           for ( keys %new ) {
123 1     1   5 no warnings 'uninitialized';
  1         2  
  1         842  
124 0 0         next unless $old{$_} eq $new{$_};
125 0           delete $old{$_};
126 0           delete $new{$_};
127             }
128 0           my %failed = $self->multi_create(%new);
129 0 0         $self->multi_delete(%old) unless %failed;
130 0           return %failed;
131             }
132              
133             #===================================
134             sub multi_exists {
135             #===================================
136 0     0 0   my ( $self, %keys ) = @_;
137 0           my @docs = map { { _type => $_, _id => $keys{$_} } } keys %keys;
  0            
138 0           my $exists = $self->es->mget( index => $self->index, docs => \@docs );
139 0           for (@$exists) {
140 0 0         next unless $_->{exists};
141 0           delete $keys{ $_->{_type} };
142             }
143 0           return %keys;
144             }
145              
146             #===================================
147             sub _params {
148             #===================================
149 0     0     my ( $self, $method, $type, $id ) = @_;
150 0 0 0       croak "No type passed to ${method}()"
151             unless defined $type and length $type;
152 0 0 0       croak "No id passed to ${method}()"
153             unless defined $id and length $id;
154              
155             return (
156 0           index => $self->index,
157             type => $type,
158             id => $id
159             );
160             }
161              
162             #===================================
163             sub bootstrap {
164             #===================================
165 0     0     my $self = shift;
166 0 0         my %params = ref $_[0] eq 'HASH' ? %{ shift() } : @_;
  0            
167 0 0         %params = (
168             auto_expand_replicas => '0-all',
169             number_of_shards => 1,
170             ) unless %params;
171              
172 0           my $es = $self->es;
173 0           my $index = $self->index;
174 0 0         return if $es->index_exists( index => $index );
175              
176 0           $es->create_index(
177             index => $index,
178             settings => \%params,
179             mappings => {
180             _default_ => {
181             _all => { enabled => 0 },
182             _source => { enabled => 0 },
183             _type => { index => 'no' },
184             enabled => 0,
185             }
186             }
187             );
188 0           $es->cluster_health( wait_for_status => 'yellow' );
189 0           return $self;
190             }
191              
192             #===================================
193 0     0 1   sub index { shift->{_index} }
194 0     0 1   sub es { shift->{_es} }
195             #===================================
196              
197             #===================================
198             sub delete_type {
199             #===================================
200 0     0 1   my $self = shift;
201 0           my $type = shift;
202 0 0 0       croak "No type passed to delete_type()"
203             unless defined $type and length $type;
204              
205 0           $self->es->delete_mapping(
206             index => $self->index,
207             type => $type,
208             ignore_missing => 1
209             );
210 0           return $self;
211             }
212              
213             #===================================
214             sub delete_index {
215             #===================================
216 0     0 1   my $self = shift;
217 0           $self->es->delete_index( index => $self->index, ignore_missing => 1 );
218 0           return $self;
219             }
220              
221             1;
222              
223             # ABSTRACT: Track unique keys in ElasticSearch
224              
225             __END__