diff --git a/operations.go b/operations.go index 5e443c1..f68cf88 100644 --- a/operations.go +++ b/operations.go @@ -10,22 +10,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 -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 { @@ -61,7 +63,7 @@ func (h *Handler) write(ctx context.Context, typ, id string, q interface{}, f wr if refTag == "" { return "", ErrEmptyRefTag } - if _, err := h.write(ctx, refTag, id, rvQField.Interface(), f); err != nil { + if _, err := h.write(ctx, refTag, id, rvQField.Interface(), f, cas); err != nil { return id, err } } else { @@ -72,7 +74,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 } @@ -139,18 +143,19 @@ func (h *Handler) Remove(ctx context.Context, typ, id string, ptr interface{}) e 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 } diff --git a/operations_test.go b/operations_test.go index fcf213d..06728ca 100644 --- a/operations_test.go +++ b/operations_test.go @@ -32,7 +32,7 @@ func TestInsertNullString(t *testing.T) { IssuingBank: "", CardType: null.String{String: "US", Valid: true}, } - _, err := th.Insert(context.Background(), "card_type", "", cardTypeWrite) + _, _, err := th.Insert(context.Background(), "card_type", "", cardTypeWrite) if err != nil { t.Error(err) } @@ -42,7 +42,7 @@ func TestInsertNullString(t *testing.T) { func TestInsertCustomID(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) } @@ -51,10 +51,13 @@ func TestInsertCustomID(t *testing.T) { func TestInsertPtrValue(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.Errorf("Cas should store 3 elements, instead of %d", len(cas)) + } } func TestInsertPrimitivePtr(t *testing.T) { @@ -62,30 +65,39 @@ func TestInsertPrimitivePtr(t *testing.T) { 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.Errorf("Cas should store 1 element, instead of %d", len(cas)) + } } func TestInsertPrimitivePtrNil(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.Errorf("Cas should store 1 element, instead of %d", len(cas)) + } } func TestInsertNonExportedField(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.Errorf("Cas should store 1 element, instead of %d", len(cas)) + } } func TestInsertExpectDuplicateError(t *testing.T) { @@ -94,11 +106,11 @@ func TestInsertExpectDuplicateError(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) } @@ -107,7 +119,7 @@ func TestInsertExpectDuplicateError(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 } @@ -137,7 +149,7 @@ func TestGetNullString(t *testing.T) { IssuingBank: "", CardType: null.String{String: "US", Valid: true}, } - id, err := th.Insert(context.Background(), "card_type", "", cardTypeWrite) + _, id, err := th.Insert(context.Background(), "card_type", "", cardTypeWrite) if err != nil { t.Error(err) } @@ -159,7 +171,7 @@ func TestGetPrimitivePtrNil(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") } @@ -177,7 +189,7 @@ func TestGetPrimitivePtr(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") } @@ -196,7 +208,7 @@ func TestGetNonPointerInput(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") } @@ -214,7 +226,7 @@ func TestGetNonExportedField(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") } @@ -309,21 +321,25 @@ 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.Errorf("Cas should store 3 element, instead of %d", len(cas)) + + } } 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) } @@ -339,30 +355,40 @@ 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.Errorf("Cas should store 1 element, instead of %d", len(cas)) + + } } 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.Errorf("Cas should store 1 element, instead of %d", len(cas)) + } } 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.Errorf("Cas should store 1 element, instead of %d", len(cas)) + } } func TestUpsertEmptyID(t *testing.T) { @@ -377,7 +403,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 } @@ -402,14 +428,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{}) @@ -436,7 +462,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()