File Coverage

blib/lib/ShardedKV/Continuum/Jump.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package ShardedKV::Continuum::Jump;
2              
3             # This implementation is based heavily on the ShardedKV::Continuum::CHash module by Steffen Mueller
4              
5 1     1   16016 use 5.014002;
  1         2  
  1         31  
6 1     1   5 use strict;
  1         1  
  1         28  
7 1     1   3 use warnings;
  1         10  
  1         43  
8              
9             our $VERSION = '0.01';
10              
11 1     1   479 use Algorithm::ConsistentHash::JumpHash;
  1         590  
  1         50  
12              
13 1     1   186 use Moose;
  0            
  0            
14             use JSON::XS qw(encode_json decode_json);
15              
16             with 'ShardedKV::Continuum';
17              
18             has '_orig_continuum_spec' => (
19             is => 'ro',
20             );
21              
22             sub choose {
23             my ($self, $key) = @_;
24             my $idx = Algorithm::ConsistentHash::JumpHash::jumphash_siphash($key, scalar @{$self->_orig_continuum_spec->{ids}});
25             return $self->_orig_continuum_spec->{ids}->[$idx];
26             }
27              
28             sub serialize {
29             my $self = shift;
30             encode_json( $self->_orig_continuum_spec )
31             }
32              
33             sub deserialize {
34             my $class = shift;
35             return $class->new(from => decode_json( $_[1] ));
36             }
37              
38             sub clone {
39             my $self = shift;
40             my $clone = ref($self)->new(from => $self->_orig_continuum_spec);
41             return $clone;
42             }
43              
44             sub extend {
45             my $self = shift;
46             my $spec = shift;
47              
48             $self->_assert_spec_ok($spec);
49              
50             # Build clone of the original spec (to avoid action at a
51             # distance) and add the new nodes.
52             my $orig_spec = $self->_orig_continuum_spec;
53             my $clone_spec = {
54             %$orig_spec, # replicas + in case there's other gunk in it, at least make an effort
55             ids => [ @{$orig_spec->{ids}} ], # deep clone
56             };
57             push @{ $clone_spec->{ids} }, @{ $spec->{ids} };
58              
59             $self->{_orig_continuum_spec} = $clone_spec;
60             return 1;
61             }
62              
63             sub get_bucket_names {
64             my $self = shift;
65              
66             return @{ $self->_orig_continuum_spec()->{ids} };
67             }
68              
69             sub BUILD {
70             my ($self, $args) = @_;
71              
72             my $from = delete $args->{from};
73             if (ref($from) eq 'HASH') {
74             $self->{_orig_continuum_spec} = $from;
75             } else {
76             die "Invalid 'from' specification for " . __PACKAGE__;
77             }
78             }
79              
80             sub _assert_spec_ok {
81             my ($self, $spec) = @_;
82             Carp::croak("Continuum spec must be a hash of the form {ids => [qw(node1 node2 node3)]}")
83             if not ref($spec) eq 'HASH'
84             or not ref($spec->{ids}) eq 'ARRAY';
85             return 1;
86             }
87              
88             no Moose;
89             __PACKAGE__->meta->make_immutable;
90              
91             __END__