Skip to content
This repository has been archived by the owner on May 22, 2020. It is now read-only.

Feature/return cas #44

Merged
merged 6 commits into from
Oct 2, 2019
Merged
Show file tree
Hide file tree
Changes from 2 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
27 changes: 16 additions & 11 deletions operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,24 @@ import (

type writerF func(string, string, interface{}, int) (gocb.Cas, error)
type readerF func(string, string, interface{}, int) (gocb.Cas, error)
type CAS map[string]gocb.Cas
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to Cas


func (h *Handler) Insert(ctx context.Context, typ, id string, q interface{}) (string, error) {
func (h *Handler) Insert(ctx context.Context, typ, id string, q interface{}) (CAS, string, error) {
cas := make(map[string]gocb.Cas)
if id == "" {
id = xid.New().String()
}
id, err := h.write(ctx, typ, id, q, func(typ, id string, ptr interface{}, ttl int) (gocb.Cas, error) {
documentID := typ + "::" + id
return h.state.bucket.Insert(documentID, ptr, 0)
})
}, cas)
if err != nil {
return "", err
return nil, "", err
}
return id, nil
return cas, id, nil
}

func (h *Handler) write(ctx context.Context, typ, id string, q interface{}, f writerF) (string, error) {
func (h *Handler) write(ctx context.Context, typ, id string, q interface{}, f writerF, cas CAS) (string, error) {
if !h.state.inspect(typ) {
err := h.state.setType(typ, typ)
if err != nil {
Expand Down Expand Up @@ -59,7 +61,7 @@ func (h *Handler) write(ctx context.Context, typ, id string, q interface{}, f wr
}
if rvQField.Kind() == reflect.Struct {
if tag, ok := rtQField.Tag.Lookup(tagJson); ok {
if _, err := h.write(ctx, removeOmitempty(tag), id, rvQField.Interface(), f); err != nil {
if _, err := h.write(ctx, removeOmitempty(tag), id, rvQField.Interface(), f, cas); err != nil {
return id, err
}
}
Expand All @@ -71,7 +73,9 @@ func (h *Handler) write(ctx context.Context, typ, id string, q interface{}, f wr
}
}
}
_, err := f(typ, id, fields, -1)
c, err := f(typ, id, fields, -1)
cas[typ] = c

return id, err
}

Expand Down Expand Up @@ -180,18 +184,19 @@ func (h *Handler) remove(ctx context.Context, typs []string, ptr interface{}, id
return nil
}

func (h *Handler) Upsert(ctx context.Context, typ, id string, q interface{}, ttl uint32) (string, error) {
func (h *Handler) Upsert(ctx context.Context, typ, id string, q interface{}, ttl uint32) (CAS, string, error) {
cas := make(map[string]gocb.Cas)
if id == "" {
id = xid.New().String()
}
id, err := h.write(ctx, typ, id, q, func(typ, id string, q interface{}, ttl int) (gocb.Cas, error) {
documentID := typ + "::" + id
return h.state.bucket.Upsert(documentID, q, uint32(ttl))
})
}, cas)
if err != nil {
return "", err
return nil, "", err
}
return id, nil
return cas, id, nil

}

Expand Down
71 changes: 48 additions & 23 deletions operations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ import (
)

func TestWrite(t *testing.T) {
if _, id, err := testInsert(); err != nil || id == "" {
_, id, err := testInsert()
if err != nil || id == "" {
t.Fatal(err)
}
}

func TestWriteCustomID(t *testing.T) {
cID := xid.New().String() + "Faswwq123942390**12312_+"
ws := generate()
id, err := th.Insert(context.Background(), "webshop", cID, &ws)
_, id, err := th.Insert(context.Background(), "webshop", cID, &ws)
if err != nil {
t.Error(err)
}
Expand All @@ -30,41 +31,53 @@ func TestWriteCustomID(t *testing.T) {

func TestWritePtrValue(t *testing.T) {
ws := generate()
id, err := th.Insert(context.Background(), "webshop", "", &ws)
cas, id, err := th.Insert(context.Background(), "webshop", "", &ws)
if err != nil || id == "" {
t.Fatal(err)
}
if len(cas) != 3 {
t.Error("error")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Provide better error something like, t.Errorf("Cas should store 3 elements, instead of %d", len(cas)). We are writing these errors for people who possible won't know anything about the system.

}
}

func TestWritePrimitivePtr(t *testing.T) {
asd := "asd"
s := struct {
Name *string `json:"name,omitempty"`
}{Name: &asd}
id, err := th.Insert(context.Background(), "webshop", "", s)
cas, id, err := th.Insert(context.Background(), "webshop", "", s)
if err != nil || id == "" {
t.Error("Missing error")
}
if len(cas) != 1 {
t.Error("error")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same error here

}
}

func TestWritePrimitivePtrNil(t *testing.T) {
s := struct {
Name *string `json:"name,omitempty"`
}{}
id, err := th.Insert(context.Background(), "webshop", "", s)
cas, id, err := th.Insert(context.Background(), "webshop", "", s)
if err != nil || id == "" {
t.Error("Missing error")
}
if len(cas) != 1 {
t.Error("error")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same error here

}
}

func TestWriteNonExportedField(t *testing.T) {
s := struct {
name string
}{name: "Jackson"}
id, err := th.Insert(context.Background(), "member", "", s)
cas, id, err := th.Insert(context.Background(), "member", "", s)
if err != nil || id == "" {
t.Error("Missing error")
}
if len(cas) != 1 {
t.Error("error")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same error here

}
}

func TestWriteExpectDuplicateError(t *testing.T) {
Expand All @@ -73,11 +86,11 @@ func TestWriteExpectDuplicateError(t *testing.T) {
}{name: "Jackson"}
ctx := context.Background()
id := xid.New().String()
_, err := th.Insert(ctx, "member", id, s)
_, _, err := th.Insert(ctx, "member", id, s)
if err != nil {
t.Error("Missing error")
}
_, errDuplicateInsert := th.Insert(ctx, "member", id, s)
_, _, errDuplicateInsert := th.Insert(ctx, "member", id, s)
if errDuplicateInsert == nil {
t.Error("error missing", errDuplicateInsert)
}
Expand All @@ -86,7 +99,7 @@ func TestWriteExpectDuplicateError(t *testing.T) {

func testInsert() (webshop, string, error) {
ws := generate()
id, err := th.Insert(context.Background(), "webshop", "", ws)
_, id, err := th.Insert(context.Background(), "webshop", "", ws)
return ws, id, err
}

Expand All @@ -109,7 +122,7 @@ func TestReadPrimitivePtrNil(t *testing.T) {
Job *string `json:"name,omitempty"`
}
test := wtyp{Job: &a}
id, errInsert := th.Insert(context.Background(), "webshop", "", test)
_, id, errInsert := th.Insert(context.Background(), "webshop", "", test)
if errInsert != nil {
t.Error("Error")
}
Expand All @@ -127,7 +140,7 @@ func TestReadPrimitivePtr(t *testing.T) {
Job *string `json:"name,omitempty"`
}
test := wtyp{Job: &a}
id, errInsert := th.Insert(context.Background(), "webshop", "", test)
_, id, errInsert := th.Insert(context.Background(), "webshop", "", test)
if errInsert != nil {
t.Error("Error")
}
Expand All @@ -146,7 +159,7 @@ func TestReadNonPointerInput(t *testing.T) {
Job *string `json:"name,omitempty"`
}
test := wtyp{Job: &a}
id, errInsert := th.Insert(context.Background(), "webshop", "", test)
_, id, errInsert := th.Insert(context.Background(), "webshop", "", test)
if errInsert != nil {
t.Error("Error")
}
Expand All @@ -164,7 +177,7 @@ func TestReadNonExportedField(t *testing.T) {
job string
}
testInsert := wtyp{job: a}
id, errInsert := th.Insert(context.Background(), "webshop", "", testInsert)
_, id, errInsert := th.Insert(context.Background(), "webshop", "", testInsert)
if errInsert != nil {
t.Error("Error")
}
Expand Down Expand Up @@ -259,21 +272,24 @@ func TestUpsertSameID(t *testing.T) {

func TestUpsertPtrValueNewID(t *testing.T) {
ws := generate()
id, err := th.Upsert(context.Background(), "webshop", xid.New().String(), &ws, 0)
cas, id, err := th.Upsert(context.Background(), "webshop", xid.New().String(), &ws, 0)
if err != nil || id == "" {
t.Fatal(err)
}
if len(cas) != 3 {
t.Error("error")
}
}

func TestUpsertPtrValueSameID(t *testing.T) {
ws := generate()
id := xid.New().String()
_, err := th.Upsert(context.Background(), "webshop", id, &ws, 0)
_, _, err := th.Upsert(context.Background(), "webshop", id, &ws, 0)
if err != nil {
t.Fatal(err)
}
wsD := generate()
_, errD := th.Upsert(context.Background(), "webshop", id, &wsD, 1)
_, _, errD := th.Upsert(context.Background(), "webshop", id, &wsD, 1)
if errD != nil {
t.Fatal(errD)
}
Expand All @@ -289,30 +305,39 @@ func TestUpsertPrimitivePtr(t *testing.T) {
s := struct {
Name *string `json:"name,omitempty"`
}{Name: &asd}
id, err := th.Upsert(context.Background(), "webshop", xid.New().String(), s, 0)
cas, id, err := th.Upsert(context.Background(), "webshop", xid.New().String(), s, 0)
if err != nil || id == "" {
t.Error("Missing error")
}
if len(cas) != 1 {
t.Error("error")
}
}

func TestUpsertPrimitivePtrNil(t *testing.T) {
s := struct {
Name *string `json:"name,omitempty"`
}{}
id, err := th.Upsert(context.Background(), "webshop", xid.New().String(), s, 0)
cas, id, err := th.Upsert(context.Background(), "webshop", xid.New().String(), s, 0)
if err != nil || id == "" {
t.Error("Missing error")
}
if len(cas) != 1 {
t.Error("error")
}
}

func TestUpsertNonExportedField(t *testing.T) {
s := struct {
name string
}{name: "Jackson"}
id, err := th.Upsert(context.Background(), "webshop", xid.New().String(), s, 0)
cas, id, err := th.Upsert(context.Background(), "webshop", xid.New().String(), s, 0)
if err != nil || id == "" {
t.Error("Missing error")
}
if len(cas) != 1 {
t.Error("error")
}
}

func TestUpsertEmptyID(t *testing.T) {
Expand All @@ -327,7 +352,7 @@ func TestUpsertEmptyID(t *testing.T) {

func testUpsert(id string) (webshop, string, error) {
ws := generate()
id, err := th.Upsert(context.Background(), "webshop", id, ws, 0)
_, id, err := th.Upsert(context.Background(), "webshop", id, ws, 0)
return ws, id, err
}

Expand All @@ -352,14 +377,14 @@ func BenchmarkInsertEmb(b *testing.B) {

func BenchmarkInsert(b *testing.B) {
for i := 0; i < b.N; i++ {
_, _ = th.Insert(context.Background(), "webshop", "", generate())
_, _, _ = th.Insert(context.Background(), "webshop", "", generate())
}
}

func BenchmarkGetSingle(b *testing.B) {
for i := 0; i < b.N; i++ {
startInsert := time.Now()
ID, _ := th.Insert(context.Background(), "webshop", "", generate())
_, ID, _ := th.Insert(context.Background(), "webshop", "", generate())
fmt.Printf("Insert: %vns\tGet: ", time.Since(startInsert).Nanoseconds())
start := time.Now()
_ = th.Get(context.Background(), "webshop", ID, webshop{})
Expand All @@ -386,7 +411,7 @@ func BenchmarkGetPtr(b *testing.B) {
for i := 0; i < b.N; i++ {
job := jobtyp{Job: &j}
startInsert := time.Now()
id, _ := th.Insert(context.Background(), "job", "", job)
_, id, _ := th.Insert(context.Background(), "job", "", job)
fmt.Printf("Insert: %vns\tGet: ", time.Since(startInsert).Nanoseconds())
var jobRead jobtyp
start := time.Now()
Expand Down