-
Notifications
You must be signed in to change notification settings - Fork 81
added len method #708
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
base: master
Are you sure you want to change the base?
added len method #708
Changes from all commits
1c7a996
1fcdb93
7d62181
dbc9070
4433ac8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,6 +24,7 @@ import ( | |
| "context" | ||
| "io" | ||
| "net/http" | ||
| "reflect" | ||
|
|
||
| "github.com/pkg/errors" | ||
|
|
||
|
|
@@ -129,10 +130,19 @@ func newCollectionDocumentCreateResponseReader(array *connection.Array, options | |
| c := &collectionDocumentCreateResponseReader{array: array, options: options} | ||
|
|
||
| if c.options != nil { | ||
| // Cache reflection types once during initialization for performance | ||
| if c.options.OldObject != nil { | ||
| c.oldType = reflect.TypeOf(c.options.OldObject).Elem() | ||
| } | ||
| if c.options.NewObject != nil { | ||
| c.newType = reflect.TypeOf(c.options.NewObject).Elem() | ||
| } | ||
|
|
||
| c.response.Old = newUnmarshalInto(c.options.OldObject) | ||
| c.response.New = newUnmarshalInto(c.options.NewObject) | ||
| } | ||
|
|
||
| c.ReadAllReader = shared.ReadAllReader[CollectionDocumentCreateResponse, *collectionDocumentCreateResponseReader]{Reader: c} | ||
| return c | ||
| } | ||
|
|
||
|
|
@@ -147,22 +157,51 @@ type collectionDocumentCreateResponseReader struct { | |
| Old *UnmarshalInto `json:"old,omitempty"` | ||
| New *UnmarshalInto `json:"new,omitempty"` | ||
| } | ||
| shared.ReadAllReader[CollectionDocumentCreateResponse, *collectionDocumentCreateResponseReader] | ||
|
|
||
| // Cache for len() method - allows Read() to work after Len() is called | ||
| cachedResults []CollectionDocumentCreateResponse | ||
| cachedErrors []error | ||
| cached bool | ||
| readIndex int // Track position in cache for Read() after Len() | ||
|
|
||
| // Performance: Cache reflection types to avoid repeated lookups | ||
| oldType reflect.Type | ||
| newType reflect.Type | ||
| } | ||
|
|
||
| func (c *collectionDocumentCreateResponseReader) Read() (CollectionDocumentCreateResponse, error) { | ||
| // If Len() was called, serve from cache | ||
| if c.cached { | ||
| if c.readIndex >= len(c.cachedResults) { | ||
| return CollectionDocumentCreateResponse{}, shared.NoMoreDocumentsError{} | ||
| } | ||
| result := c.cachedResults[c.readIndex] | ||
| err := c.cachedErrors[c.readIndex] | ||
| c.readIndex++ | ||
| return result, err | ||
| } | ||
|
|
||
| // Normal streaming read | ||
| if !c.array.More() { | ||
| return CollectionDocumentCreateResponse{}, shared.NoMoreDocumentsError{} | ||
| } | ||
|
|
||
| var meta CollectionDocumentCreateResponse | ||
|
|
||
| if c.options != nil { | ||
| meta.Old = c.options.OldObject | ||
| meta.New = c.options.NewObject | ||
| // Create new instances for each document to avoid pointer reuse | ||
| // Use cached types for performance | ||
| if c.oldType != nil { | ||
| meta.Old = reflect.New(c.oldType).Interface() | ||
| } | ||
| if c.newType != nil { | ||
| meta.New = reflect.New(c.newType).Interface() | ||
| } | ||
|
|
||
| c.response.DocumentMeta = &meta.DocumentMeta | ||
| c.response.ResponseStruct = &meta.ResponseStruct | ||
| c.response.Old = newUnmarshalInto(meta.Old) | ||
| c.response.New = newUnmarshalInto(meta.New) | ||
|
|
||
| if err := c.array.Unmarshal(&c.response); err != nil { | ||
| if err == io.EOF { | ||
|
|
@@ -175,5 +214,30 @@ func (c *collectionDocumentCreateResponseReader) Read() (CollectionDocumentCreat | |
| return meta, meta.AsArangoError() | ||
| } | ||
|
|
||
| // Copy data from the new instances back to the original option objects for backward compatibility | ||
| if c.options != nil { | ||
| if c.options.OldObject != nil && meta.Old != nil { | ||
| oldValue := reflect.ValueOf(meta.Old).Elem() | ||
| originalValue := reflect.ValueOf(c.options.OldObject).Elem() | ||
| originalValue.Set(oldValue) | ||
| } | ||
| if c.options.NewObject != nil && meta.New != nil { | ||
| newValue := reflect.ValueOf(meta.New).Elem() | ||
| originalValue := reflect.ValueOf(c.options.NewObject).Elem() | ||
| originalValue.Set(newValue) | ||
| } | ||
| } | ||
|
|
||
| return meta, nil | ||
| } | ||
|
|
||
| // Len returns the number of items in the response. | ||
| // After calling Len(), you can still use Read() to iterate through items. | ||
| func (c *collectionDocumentCreateResponseReader) Len() int { | ||
| if !c.cached { | ||
| c.cachedResults, c.cachedErrors = c.ReadAll() | ||
| c.cached = true | ||
| c.readIndex = 0 // Reset read position to allow Read() after Len() | ||
| } | ||
| return len(c.cachedResults) | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Race Conditions from Unsynchronized Shared StateThe |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,6 +24,7 @@ import ( | |
| "context" | ||
| "io" | ||
| "net/http" | ||
| "reflect" | ||
|
|
||
| "github.com/pkg/errors" | ||
|
|
||
|
|
@@ -42,6 +43,7 @@ var _ CollectionDocumentDelete = &collectionDocumentDelete{} | |
|
|
||
| type collectionDocumentDelete struct { | ||
| collection *collection | ||
| shared.ReadAllIntoReader[CollectionDocumentDeleteResponse, *collectionDocumentDeleteResponseReader] | ||
| } | ||
|
|
||
| func (c collectionDocumentDelete) DeleteDocument(ctx context.Context, key string) (CollectionDocumentDeleteResponse, error) { | ||
|
|
@@ -103,6 +105,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 | ||
| } | ||
|
|
||
|
|
@@ -111,9 +114,28 @@ var _ CollectionDocumentDeleteResponseReader = &collectionDocumentDeleteResponse | |
| type collectionDocumentDeleteResponseReader struct { | ||
| array *connection.Array | ||
| options *CollectionDocumentDeleteOptions | ||
| shared.ReadAllIntoReader[CollectionDocumentDeleteResponse, *collectionDocumentDeleteResponseReader] | ||
| // Cache for len() method - allows Read() to work after Len() is called | ||
| cachedResults []CollectionDocumentDeleteResponse | ||
| cachedErrors []error | ||
| cached bool | ||
| readIndex int // Track position in cache for Read() after Len() | ||
| } | ||
|
|
||
| func (c *collectionDocumentDeleteResponseReader) Read(i interface{}) (CollectionDocumentDeleteResponse, error) { | ||
| // If Len() was called, serve from cache | ||
| // Note: When serving from cache, the 'i' parameter is not populated with document data | ||
| if c.cached { | ||
| if c.readIndex >= len(c.cachedResults) { | ||
| return CollectionDocumentDeleteResponse{}, shared.NoMoreDocumentsError{} | ||
| } | ||
| result := c.cachedResults[c.readIndex] | ||
| err := c.cachedErrors[c.readIndex] | ||
| c.readIndex++ | ||
| return result, err | ||
| } | ||
|
|
||
| // Normal streaming read | ||
| if !c.array.More() { | ||
| return CollectionDocumentDeleteResponse{}, shared.NoMoreDocumentsError{} | ||
| } | ||
|
|
@@ -146,11 +168,33 @@ func (c *collectionDocumentDeleteResponseReader) Read(i interface{}) (Collection | |
| } | ||
|
|
||
| if c.options != nil && c.options.OldObject != nil { | ||
| meta.Old = c.options.OldObject | ||
| // Create a new instance for each document to avoid reusing the same pointer | ||
| oldObjectType := reflect.TypeOf(c.options.OldObject).Elem() | ||
| meta.Old = reflect.New(oldObjectType).Interface() | ||
|
|
||
| // Extract old data into the new instance | ||
| if err := response.Object.Object.Extract("old").Inject(meta.Old); err != nil { | ||
| return CollectionDocumentDeleteResponse{}, err | ||
| } | ||
|
|
||
| // Copy data from the new instance to the original OldObject for backward compatibility | ||
| oldValue := reflect.ValueOf(meta.Old).Elem() | ||
| originalValue := reflect.ValueOf(c.options.OldObject).Elem() | ||
| originalValue.Set(oldValue) | ||
| } | ||
|
|
||
| return meta, nil | ||
| } | ||
|
|
||
| // Len returns the number of items in the response. | ||
| // After calling Len(), you can still use Read() to iterate through items. | ||
| // Note: When Read() serves from cache, the document data parameter is not populated. | ||
| func (c *collectionDocumentDeleteResponseReader) Len() int { | ||
| if !c.cached { | ||
| var dummySlice []interface{} | ||
| c.cachedResults, c.cachedErrors = c.ReadAll(&dummySlice) | ||
| c.cached = true | ||
| c.readIndex = 0 // Reset read position to allow Read() after Len() | ||
| } | ||
| return len(c.cachedResults) | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Concurrent Access Corrupts Shared Reader StateThe |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
| } | ||
|
|
||
|
|
@@ -106,9 +106,28 @@ var _ CollectionDocumentReadResponseReader = &collectionDocumentReadResponseRead | |
| type collectionDocumentReadResponseReader struct { | ||
| array *connection.Array | ||
| options *CollectionDocumentReadOptions | ||
| shared.ReadAllIntoReader[CollectionDocumentReadResponse, *collectionDocumentReadResponseReader] | ||
| // Cache for len() method - allows Read() to work after Len() is called | ||
| cachedResults []CollectionDocumentReadResponse | ||
| cachedErrors []error | ||
| cached bool | ||
| readIndex int // Track position in cache for Read() after Len() | ||
| } | ||
|
|
||
| func (c *collectionDocumentReadResponseReader) Read(i interface{}) (CollectionDocumentReadResponse, error) { | ||
| // If Len() was called, serve from cache | ||
| // Note: When serving from cache, the 'i' parameter is not populated with document data | ||
| if c.cached { | ||
| if c.readIndex >= len(c.cachedResults) { | ||
| return CollectionDocumentReadResponse{}, shared.NoMoreDocumentsError{} | ||
| } | ||
| result := c.cachedResults[c.readIndex] | ||
| err := c.cachedErrors[c.readIndex] | ||
| c.readIndex++ | ||
| return result, err | ||
| } | ||
|
|
||
| // Normal streaming read | ||
| if !c.array.More() { | ||
| return CollectionDocumentReadResponse{}, shared.NoMoreDocumentsError{} | ||
| } | ||
|
|
@@ -142,3 +161,16 @@ func (c *collectionDocumentReadResponseReader) Read(i interface{}) (CollectionDo | |
|
|
||
| return meta, nil | ||
| } | ||
|
|
||
| // Len returns the number of items in the response. | ||
| // After calling Len(), you can still use Read() to iterate through items. | ||
| // Note: When Read() serves from cache, the document data parameter is not populated. | ||
| func (c *collectionDocumentReadResponseReader) Len() int { | ||
| if !c.cached { | ||
| var dummySlice []interface{} | ||
| c.cachedResults, c.cachedErrors = c.ReadAll(&dummySlice) | ||
| c.cached = true | ||
| c.readIndex = 0 // Reset read position to allow Read() after Len() | ||
| } | ||
| return len(c.cachedResults) | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Concurrent Access Causes Data RacesThe |
||
Uh oh!
There was an error while loading. Please reload this page.