Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add Sorted.Delete.Value using ZREM #3

Merged
merged 1 commit into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions pkg/conformance/client_single_sorted_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,109 @@ func Test_Client_Single_Sorted_Delete_Score(t *testing.T) {
}
}

func Test_Client_Single_Sorted_Delete_Value(t *testing.T) {
var err error

var cli redigo.Interface
{
c := client.Config{
Kind: client.KindSingle,
}

cli, err = client.New(c)
if err != nil {
t.Fatal(err)
}

err = cli.Purge()
if err != nil {
t.Fatal(err)
}
}

{
err = cli.Sorted().Create().Value("ssk", "foo", 8.0)
if err != nil {
t.Fatal(err)
}
err = cli.Sorted().Create().Value("ssk", "bar", 7.0)
if err != nil {
t.Fatal(err)
}
err = cli.Sorted().Create().Value("ssk", "baz", 6.0)
if err != nil {
t.Fatal(err)
}
err = cli.Sorted().Create().Value("ssk", "zap", 5.0)
if err != nil {
t.Fatal(err)
}
}

{
res, err := cli.Sorted().Search().Order("ssk", 0, -1)
if err != nil {
t.Fatal(err)
}
if len(res) != 4 {
t.Fatal("expected", 4, "got", len(res))
}
if res[0] != "foo" {
t.Fatal("expected", "foo", "got", res[0])
}
if res[1] != "bar" {
t.Fatal("expected", "bar", "got", res[1])
}
if res[2] != "baz" {
t.Fatal("expected", "baz", "got", res[2])
}
if res[3] != "zap" {
t.Fatal("expected", "zap", "got", res[3])
}
}

// Deleting multiple values, including a non existing one, should remove all
// of the existing values regardless.
{
err := cli.Sorted().Delete().Value("ssk", "foo", "bar", "NON", "baz")
if err != nil {
t.Fatal(err)
}
}

{
res, err := cli.Sorted().Search().Order("ssk", 0, -1)
if err != nil {
t.Fatal(err)
}
if len(res) != 1 {
t.Fatal("expected", 1, "got", len(res))
}
if res[0] != "zap" {
t.Fatal("expected", "zap", "got", res[0])
}
}

// Deleting the last value should result in all values being removed. This
// call also tests that single removals work.
{
err := cli.Sorted().Delete().Value("ssk", "zap")
if err != nil {
t.Fatal(err)
}
}

{
res, err := cli.Sorted().Search().Order("ssk", 0, -1)
if err != nil {
t.Fatal(err)
}
if len(res) != 0 {
t.Fatal("expected", 0, "got", len(res))
}
}
}

func Test_Client_Single_Sorted_Exists(t *testing.T) {
var err error

Expand Down
9 changes: 9 additions & 0 deletions pkg/fake/sorted_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ type SortedDelete struct {
FakeIndex func() error
FakeLimit func() error
FakeScore func() error
FakeValue func() error
}

func (d *SortedDelete) Clean(key string) error {
Expand Down Expand Up @@ -38,3 +39,11 @@ func (d *SortedDelete) Score(key string, sco float64) error {

return nil
}

func (d *SortedDelete) Value(key string, val ...string) error {
if d.FakeValue != nil {
return d.FakeValue()
}

return nil
}
21 changes: 21 additions & 0 deletions pkg/sorted/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,24 @@ func (d *delete) Score(key string, sco float64) error {

return nil
}

func (d *delete) Value(key string, val ...string) error {
con := d.pool.Get()
defer con.Close()

var arg []interface{}
{
arg = append(arg, prefix.WithKeys(d.prefix, key))

for _, x := range val {
arg = append(arg, x)
}
}

_, err := redis.Int64(con.Do("ZREM", arg...))
if err != nil {
return tracer.Mask(err)
}

return nil
}
14 changes: 11 additions & 3 deletions pkg/sorted/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ type Create interface {
// Score creates an element within the sorted set under key, tracking the
// element using the unique score given by sco. The element's value provided
// by val can be ensured to have unique associations, like indices using ind.
// Scores are enforced to be unique.
//
// TODO should be renamed to Index because of the index feature.
Score(key string, val string, sco float64, ind ...string) error
// Value creates an element within the sorted set under key transparently
// using ZADD. Value does not enforce scores to be unique like Score.
// using ZADD. Scores are not enforced to be unique.
//
// https://redis.io/commands/zadd
//
Value(key string, val string, sco float64) error
}

Expand All @@ -44,8 +48,12 @@ type Delete interface {
// set. Note that indices associated with the underlying element are purged
// automatically as well.
Score(key string, sco float64) error

// TODO provide Value method that only uses native ZREM and accept multiple values
// Value deletes the elements identified by the given values within the
// specified sorted set. Non-existing elements are ignored.
//
// https://redis.io/commands/zrem
//
Value(key string, val ...string) error
}

type Exists interface {
Expand Down