Skip to content

Added ReadAll structure without support for OldObject #686

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

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions test/on_failure.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/bash
exit 1
echo "failure!\n"

echo "\nARANGODB-STARTER logs: "
Expand Down
1 change: 1 addition & 0 deletions v2/arangodb/collection_documents_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ type CollectionDocumentCreate interface {
}

type CollectionDocumentCreateResponseReader interface {
shared.ReadAllReadable[CollectionDocumentCreateResponse]
Read() (CollectionDocumentCreateResponse, error)
}

Expand Down
2 changes: 2 additions & 0 deletions v2/arangodb/collection_documents_create_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ func newCollectionDocumentCreateResponseReader(array *connection.Array, options
c.response.New = newUnmarshalInto(c.options.NewObject)
}

c.ReadAllReader = shared.ReadAllReader[CollectionDocumentCreateResponse, *collectionDocumentCreateResponseReader]{Reader: c}
return c
}

Expand All @@ -147,6 +148,7 @@ type collectionDocumentCreateResponseReader struct {
Old *UnmarshalInto `json:"old,omitempty"`
New *UnmarshalInto `json:"new,omitempty"`
}
shared.ReadAllReader[CollectionDocumentCreateResponse, *collectionDocumentCreateResponseReader]
}

func (c *collectionDocumentCreateResponseReader) Read() (CollectionDocumentCreateResponse, error) {
Expand Down
2 changes: 2 additions & 0 deletions v2/arangodb/collection_documents_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ type CollectionDocumentDeleteResponse struct {
}

type CollectionDocumentDeleteResponseReader interface {
shared.ReadAllIntoReadable[CollectionDocumentDeleteResponse]
Read(i interface{}) (CollectionDocumentDeleteResponse, error)
}

Expand All @@ -82,6 +83,7 @@ type CollectionDocumentDeleteOptions struct {
WithWaitForSync *bool

// Return additionally the complete previous revision of the changed document
// Should be a pointer to an object
OldObject interface{}

// If set to true, an empty object is returned as response if the document operation succeeds.
Expand Down
3 changes: 3 additions & 0 deletions v2/arangodb/collection_documents_delete_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ var _ CollectionDocumentDelete = &collectionDocumentDelete{}

type collectionDocumentDelete struct {
collection *collection
shared.ReadAllIntoReader[CollectionDocumentDeleteResponse, *collectionDocumentDeleteResponseReader]
}

func (c collectionDocumentDelete) DeleteDocument(ctx context.Context, key string) (CollectionDocumentDeleteResponse, error) {
Expand Down Expand Up @@ -103,6 +104,7 @@ func (c collectionDocumentDelete) DeleteDocumentsWithOptions(ctx context.Context
func newCollectionDocumentDeleteResponseReader(array *connection.Array, options *CollectionDocumentDeleteOptions) *collectionDocumentDeleteResponseReader {
c := &collectionDocumentDeleteResponseReader{array: array, options: options}

c.ReadAllIntoReader = shared.ReadAllIntoReader[CollectionDocumentDeleteResponse, *collectionDocumentDeleteResponseReader]{Reader: c}
return c
}

Expand All @@ -111,6 +113,7 @@ var _ CollectionDocumentDeleteResponseReader = &collectionDocumentDeleteResponse
type collectionDocumentDeleteResponseReader struct {
array *connection.Array
options *CollectionDocumentDeleteOptions
shared.ReadAllIntoReader[CollectionDocumentDeleteResponse, *collectionDocumentDeleteResponseReader]
}

func (c *collectionDocumentDeleteResponseReader) Read(i interface{}) (CollectionDocumentDeleteResponse, error) {
Expand Down
1 change: 1 addition & 0 deletions v2/arangodb/collection_documents_read.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type CollectionDocumentRead interface {

type CollectionDocumentReadResponseReader interface {
Read(i interface{}) (CollectionDocumentReadResponse, error)
shared.ReadAllIntoReadable[CollectionDocumentReadResponse]
}

type CollectionDocumentReadResponse struct {
Expand Down
3 changes: 2 additions & 1 deletion v2/arangodb/collection_documents_read_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (c collectionDocumentRead) ReadDocumentWithOptions(ctx context.Context, key

func newCollectionDocumentReadResponseReader(array *connection.Array, options *CollectionDocumentReadOptions) *collectionDocumentReadResponseReader {
c := &collectionDocumentReadResponseReader{array: array, options: options}

c.ReadAllIntoReader = shared.ReadAllIntoReader[CollectionDocumentReadResponse, *collectionDocumentReadResponseReader]{Reader: c}
return c
}

Expand All @@ -106,6 +106,7 @@ var _ CollectionDocumentReadResponseReader = &collectionDocumentReadResponseRead
type collectionDocumentReadResponseReader struct {
array *connection.Array
options *CollectionDocumentReadOptions
shared.ReadAllIntoReader[CollectionDocumentReadResponse, *collectionDocumentReadResponseReader]
}

func (c *collectionDocumentReadResponseReader) Read(i interface{}) (CollectionDocumentReadResponse, error) {
Expand Down
79 changes: 79 additions & 0 deletions v2/arangodb/shared/read_all.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package shared

import (
"errors"
"reflect"
)

type readReader[T any] interface {
Read() (T, error)
}

type ReadAllReadable[T any] interface {
ReadAll() ([]T, []error)
}

type ReadAllReader[T any, R readReader[T]] struct {
Reader R
}

func (r ReadAllReader[T, R]) ReadAll() ([]T, []error) {
var docs []T
var errs []error
for {
doc, e := r.Reader.Read()
if errors.Is(e, NoMoreDocumentsError{}) {
break
}
errs = append(errs, e)
docs = append(docs, doc)
}
return docs, errs
}

type readReaderInto[T any] interface {
Read(i interface{}) (T, error)
}

type ReadAllIntoReadable[T any] interface {
ReadAll(i interface{}) ([]T, []error)
}

type ReadAllIntoReader[T any, R readReaderInto[T]] struct {
Reader R
}

func (r ReadAllIntoReader[T, R]) ReadAll(i interface{}) ([]T, []error) {

iVal := reflect.ValueOf(i)
if iVal.Kind() != reflect.Ptr || iVal.Elem().Kind() != reflect.Slice {
panic("i must be a pointer to a slice")
}

eVal := iVal.Elem()
eType := eVal.Type().Elem()

var docs []T
var errs []error

for {
res := reflect.New(eType)
doc, e := r.Reader.Read(res.Interface())
if errors.Is(e, NoMoreDocumentsError{}) {
break
}

iDocVal := reflect.ValueOf(doc)
if iDocVal.Kind() == reflect.Ptr {
iDocVal = iDocVal.Elem()
}
docCopy := reflect.New(iDocVal.Type()).Elem()
docCopy.Set(iDocVal)

errs = append(errs, e)
docs = append(docs, docCopy.Interface().(T))
eVal = reflect.Append(eVal, res.Elem())
}
iVal.Elem().Set(eVal)
return docs, errs
}
138 changes: 95 additions & 43 deletions v2/tests/database_collection_doc_create_code_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@ import (
"context"
"testing"

"github.com/arangodb/go-driver/v2/arangodb/shared"

"github.com/stretchr/testify/require"

"github.com/arangodb/go-driver/v2/arangodb"
"github.com/arangodb/go-driver/v2/arangodb/shared"
)

type DocWithCode struct {
Expand All @@ -38,66 +37,119 @@ type DocWithCode struct {

func Test_DatabaseCollectionDocCreateCode(t *testing.T) {
Wrap(t, func(t *testing.T, client arangodb.Client) {
// COMMENTED OUT FOR DEBUGGING ONLY
// WithDatabase(t, client, nil, func(db arangodb.Database) {
// WithCollectionV2(t, db, nil, func(col arangodb.Collection) {
// withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) {
// doc := DocWithCode{
// Key: "test",
// }

// meta, err := col.CreateDocumentWithOptions(ctx, doc, &arangodb.CollectionDocumentCreateOptions{})
// require.NoError(t, err)
// require.NotEmpty(t, meta.Rev)
// require.Empty(t, meta.Old)
// require.Empty(t, meta.New)

// rdoc, err := col.ReadDocument(ctx, "test", &doc)
// require.NoError(t, err)

// require.EqualValues(t, "test", rdoc.Key)
// })
// })
// })

// WithDatabase(t, client, nil, func(db arangodb.Database) {
// WithCollectionV2(t, db, nil, func(col arangodb.Collection) {
// withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) {
// doc := DocWithCode{
// Key: "test",
// }
// doc2 := DocWithCode{
// Key: "test2",
// }

// _, err := col.CreateDocuments(ctx, []any{
// doc, doc2,
// })
// require.NoError(t, err)

// docs, err := col.ReadDocuments(ctx, []string{
// "test",
// "tz44",
// "test2",
// })
// require.NoError(t, err)

// var z DocWithCode

// meta, err := docs.Read(&z)
// require.NoError(t, err)
// require.Equal(t, "test", meta.Key)

// _, err = docs.Read(&z)
// require.Error(t, err)
// require.True(t, shared.IsNotFound(err))

// meta, err = docs.Read(&z)
// require.NoError(t, err)
// require.Equal(t, "test2", meta.Key)

// _, err = docs.Read(&z)
// require.Error(t, err)
// require.True(t, shared.IsNoMoreDocuments(err))
// })
// })
// })

WithDatabase(t, client, nil, func(db arangodb.Database) {
WithCollectionV2(t, db, nil, func(col arangodb.Collection) {
withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) {
doc := DocWithCode{
Key: "test",
doc1 := DocWithCode{
Key: "test",
Code: "code1",
}
doc2 := DocWithCode{
Key: "test2",
Code: "code2",
}

meta, err := col.CreateDocumentWithOptions(ctx, doc, &arangodb.CollectionDocumentCreateOptions{})
readerCrt, err := col.CreateDocuments(ctx, []any{doc1, doc2})
require.NoError(t, err)
require.NotEmpty(t, meta.Rev)
require.Empty(t, meta.Old)
require.Empty(t, meta.New)

rdoc, err := col.ReadDocument(ctx, "test", &doc)
require.NoError(t, err)
metaCrt, errs := readerCrt.ReadAll()

require.EqualValues(t, "test", rdoc.Key)
})
})
})
require.ElementsMatch(t, []any{doc1.Key, doc2.Key}, []any{metaCrt[0].Key, metaCrt[1].Key})
require.ElementsMatch(t, []any{nil, nil}, errs)

WithDatabase(t, client, nil, func(db arangodb.Database) {
WithCollectionV2(t, db, nil, func(col arangodb.Collection) {
withContextT(t, defaultTestTimeout, func(ctx context.Context, tb testing.TB) {
doc := DocWithCode{
Key: "test",
}
doc2 := DocWithCode{
Key: "test2",
}
var docRedRead []DocWithCode

_, err := col.CreateDocuments(ctx, []any{
doc, doc2,
readeRed, err := col.ReadDocuments(ctx, []string{
"test", "test2", "nonexistent",
})
require.NoError(t, err)

docs, err := col.ReadDocuments(ctx, []string{
"test",
"tz44",
"test2",
})
require.NoError(t, err)
metaRed, errs := readeRed.ReadAll(&docRedRead)

require.ElementsMatch(t, []any{doc1.Key, doc2.Key}, []any{metaRed[0].Key, metaRed[1].Key})
require.ElementsMatch(t, []any{nil, nil, shared.ErrArangoDocumentNotFound}, []any{errs[0], errs[1], errs[2].(shared.ArangoError).ErrorNum})

var z DocWithCode
var docOldObject DocWithCode
var docDelRead []DocWithCode

meta, err := docs.Read(&z)
readerDel, err := col.DeleteDocumentsWithOptions(ctx, []string{
"test", "test2", "nonexistent",
}, &arangodb.CollectionDocumentDeleteOptions{OldObject: &docOldObject})
require.NoError(t, err)
require.EqualValues(t, "test", meta.Key)

_, err = docs.Read(&z)
require.Error(t, err)
require.True(t, shared.IsNotFound(err))
metaDel, errs := readerDel.ReadAll(&docDelRead)

meta, err = docs.Read(&z)
require.NoError(t, err)
require.EqualValues(t, "test2", meta.Key)
require.ElementsMatch(t, []any{doc1.Key, doc2.Key, ""}, []any{metaDel[0].Key, metaDel[1].Key, metaDel[2].Key})
require.ElementsMatch(t, []any{nil, nil, shared.ErrArangoDocumentNotFound}, []any{errs[0], errs[1], errs[2].(shared.ArangoError).ErrorNum})

// Will fail as the OldObject is not supported by the ReadAll
require.ElementsMatch(t, []any{doc1.Code, doc2.Code}, []any{metaDel[0].Old.(*DocWithCode).Code, metaDel[1].Old.(*DocWithCode).Code})

_, err = docs.Read(&z)
require.Error(t, err)
require.True(t, shared.IsNoMoreDocuments(err))
})
})
})
Expand Down