diff --git a/lib/Myriad/Role/Storage.pm b/lib/Myriad/Role/Storage.pm index 41403644..0d468764 100644 --- a/lib/Myriad/Role/Storage.pm +++ b/lib/Myriad/Role/Storage.pm @@ -59,6 +59,9 @@ our @WRITE_METHODS = qw( orderedset_add orderedset_remove_member orderedset_remove_byscore + unorderedset_add + unorderedset_remove + unorderedset_replace del unlink set_unless_exists @@ -233,7 +236,7 @@ Returns a L. method orderedset_add; -=head2 orderedset_remove_memeber +=head2 orderedset_remove_member Removes a member from an orderedset structure Takes the following parameters: @@ -273,6 +276,63 @@ Returns a L. method orderedset_remove_byscore; +=head2 unorderedset_add + +Adds members to a set. +Takes the following parameters: + +=over 4 + +=item * C<< $k >> - the relative key in storage + +=item * C<< $members >> - an arrayref holding zero or more members to add + +=back + +Returns a L. + +=cut + +method unorderedset_add; + +=head2 unorderedset_remove + +Removes members from a set. +Takes the following parameters: + +=over 4 + +=item * C<< $k >> - the relative key in storage + +=item * C<< $members >> - an arrayref holding zero or more members to remove + +=back + +Returns a L. + +=cut + +method unorderedset_remove; + +=head2 unorderedset_replace + +Atomically replace all members in a set. +Takes the following parameters: + +=over 4 + +=item * C<< $k >> - the relative key in storage + +=item * C<< $members >> - an arrayref holding zero or more members to form the new set + +=back + +Returns a L. + +=cut + +method unorderedset_replace; + method del; method unlink; method set_unless_exists; @@ -293,6 +353,9 @@ our @READ_METHODS = qw( hash_as_list orderedset_member_count orderedset_members + unorderedset_is_member + unorderedset_member_count + unorderedset_members when_key_changed ); @@ -461,6 +524,60 @@ Returns a L. method orderedset_members; +=head2 unorderedset_is_member + +Returns true if the given key is a member in the set. +Takes the following parameters: + +=over 4 + +=item * C<< $k >> - the relative key in storage + +=item * C<< $value >> - the value to check for presence in the set + +=back + +Returns a L. + +=cut + +method unorderedset_is_member; + +=head2 unorderedset_member_count + +Returns the count of all members. + +Takes the following parameters: + +=over 4 + +=item * C<< $k >> - the relative key in storage + +=back + +Returns a L. + +=cut + +method unorderedset_member_count; + +=head2 unorderedset_members + +Returns a list of all members in the set. +Takes the following parameters: + +=over 4 + +=item * C<< $k >> - the relative key in storage + +=back + +Returns a L. + +=cut + +method unorderedset_members; + method when_key_changed; 1; diff --git a/lib/Myriad/Storage/Implementation/Memory.pm b/lib/Myriad/Storage/Implementation/Memory.pm index 17c2abd8..21214014 100644 --- a/lib/Myriad/Storage/Implementation/Memory.pm +++ b/lib/Myriad/Storage/Implementation/Memory.pm @@ -488,6 +488,62 @@ async method orderedset_remove_byscore : Defer ($k, $min, $max) { return 0 + @keys_before - @keys_after; } +=head2 unorderedset_add + +Takes the following parameters: + +=over 4 + +=item * C<< $k >> - the relative key in storage + +=item * C<< $m >> - the scalar member value + +=back + +Note that references are currently B supported - attempts to write an arrayref, hashref +or object will fail. + +Returns a L which will resolve on completion. + +=cut + +async method unorderedset_add : Defer ($k, $m) { + $m = [ $m ] unless ref($m) eq 'ARRAY'; + die 'set member values cannot be a reference for key:' . $k . ' - ' . ref($_) for grep { ref } $m->@*; + $data{$k} = {} unless defined $data{$k}; + return @{$data{$k}}{$m->@*} = (); +} + +=head2 unorderedset_remove + +Takes the following parameters: + +=over 4 + +=item * C<< $k >> - the relative key in storage + +=item * C<< $m >> - the scalar member value + +=back + +Returns a L which will resolve on completion. + +=cut + +async method unorderedset_remove : Defer ($k, $m) { + $m = [ $m ] unless ref($m) eq 'ARRAY'; + my $keys_before = 0 + keys $data{$k}->%*; + delete @{$data{$k}}{$m->@*}; + return $keys_before - keys $data{$k}->%*; +} + +async method unorderedset_replace : Defer ($k, $m) { + $m = [ $m ] unless ref($m) eq 'ARRAY'; + delete @{$data{$k}}{keys $data{$k}->%*}; + @{$data{$k}}{$m->@*} = (); + return 0 + keys $data{$k}->%*; +} + async method unlink : Defer (@keys) { delete @data{@keys}; $key_change->{$_}->done for grep { $key_change->{$_} } @keys; @@ -548,6 +604,50 @@ async method orderedset_members : Defer ($k, $min = '-inf', $max = '+inf', $with return [ map { ($_ >= $min and $_ <= $max ) ? $with_score ? ($data{$k}->{$_}, $_) : ($data{$k}->{$_}) : () } sort keys $data{$k}->%* ]; } +=head2 unorderedset_member_count + +Takes the following parameters: + +=over 4 + +=item * C<< $k >> - the relative key in storage + +=back + +Returns a L which will resolve on completion. + +=cut + +async method unorderedset_member_count : Defer ($k) { + return 0 + keys $data{$k}->%*; +} + +=head2 unorderedset_members + +Takes the following parameters: + +=over 4 + +=item * C<< $k >> - the relative key in storage + +=item * C<< $min >> - minimum score for selection + +=item * C<< $max >> - maximum score for selection + +=back + +Returns a L which will resolve on completion. + +=cut + +async method unorderedset_members : Defer ($k) { + return [ keys $data{$k}->%* ]; +} + +async method unorderedset_is_member : Defer ($k, $m) { + return exists $data{$k}{$m}; +} + 1; =head1 AUTHOR diff --git a/lib/Myriad/Storage/Implementation/Redis.pm b/lib/Myriad/Storage/Implementation/Redis.pm index 41f2e5f9..31156f4f 100644 --- a/lib/Myriad/Storage/Implementation/Redis.pm +++ b/lib/Myriad/Storage/Implementation/Redis.pm @@ -517,6 +517,80 @@ async method orderedset_remove_byscore ($k, $min, $max) { await $redis->zremrangebyscore($self->apply_prefix($k), $min => $max); } +=head2 unorderedset_add + +Takes the following parameters: + +=over 4 + +=item * C<< $k >> - the relative key in storage + +=item * C<< $m >> - the scalar member value + +=back + +Note that references are B supported - attempts to write an arrayref, hashref +or object will fail. + +Redis sorted sets data structure family. +add a scored member value to a storage key + +Returns a L which will resolve on completion. + +=cut + +async method unorderedset_add ($k, $m) { + $m = [ $m ] unless ref($m) eq 'ARRAY'; + die 'set member values cannot be a reference for key:' . $k . ' - ' . ref($_) for grep { ref } $m->@*; + await $redis->sadd($self->apply_prefix($k), $m->@*); +} + +=head2 unorderedset_remove + +Takes the following parameters: + +=over 4 + +=item * C<< $k >> - the relative key in storage + +=item * C<< $m >> - the scalar member value + +=back + +Returns a L which will resolve on completion. + +=cut + +async method unorderedset_remove ($k, $m) { + $m = [ $m ] unless ref($m) eq 'ARRAY'; + await $redis->srem($self->apply_prefix($k), $m->@*); +} + +=head2 unorderedset_replace + +Takes the following parameters: + +=over 4 + +=item * C<< $k >> - the relative key in storage + +=item * C<< $m >> - the scalar member value + +=back + +Returns a L which will resolve on completion. + +=cut + +async method unorderedset_replace ($k, $m) { + $m = [ $m ] unless ref($m) eq 'ARRAY'; + my $prefixed = $self->apply_prefix($k); + await $redis->multi(sub ($redis) { + $redis->unlink($prefixed); + $redis->sadd($prefixed, $m->@*); + }); +} + async method unlink (@keys) { await $redis->unlink(map { $self->apply_prefix($_) } @keys); return $self; @@ -579,6 +653,46 @@ async method orderedset_members ($k, $min = '-inf', $max = '+inf', $with_score = await $redis->zrange($self->apply_prefix($k), $min => $max, 'BYSCORE', ($with_score ? 'WITHSCORES' : ())); } +=head2 unorderedset_member_count + +Takes the following parameters: + +=over 4 + +=item * C<< $k >> - the relative key in storage + +=back + +Returns a L which will resolve on completion. + +=cut + +async method unorderedset_member_count ($k) { + await $redis->scard($self->apply_prefix($k)); +} + +=head2 unorderedset_members + +Takes the following parameters: + +=over 4 + +=item * C<< $k >> - the relative key in storage + +=back + +Returns a L which will resolve on completion. + +=cut + +async method unorderedset_members ($k) { + await $redis->smembers($self->apply_prefix($k)); +} + +async method unorderedset_is_member ($k, $m) { + await $redis->sismember($self->apply_prefix($k), $m); +} + 1; =head1 AUTHOR