-
Notifications
You must be signed in to change notification settings - Fork 670
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1999 from RanVaknin/s3-custom-paginators
S3 custom paginators
- Loading branch information
Showing
3 changed files
with
493 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"id": "a7aeef88-7867-446a-8c51-7f39c2be006e", | ||
"type": "feature", | ||
"description": "added custom paginators for listMultipartUploads and ListObjectVersions", | ||
"modules": [ | ||
"service/s3" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
package s3 | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
) | ||
|
||
// ListObjectVersionsAPIClient is a client that implements the ListObjectVersions | ||
// operation | ||
type ListObjectVersionsAPIClient interface { | ||
ListObjectVersions(context.Context, *ListObjectVersionsInput, ...func(*Options)) (*ListObjectVersionsOutput, error) | ||
} | ||
|
||
var _ ListObjectVersionsAPIClient = (*Client)(nil) | ||
|
||
// ListObjectVersionsPaginatorOptions is the paginator options for ListObjectVersions | ||
type ListObjectVersionsPaginatorOptions struct { | ||
// (Optional) The maximum number of Object Versions that you want Amazon S3 to | ||
// return. | ||
Limit int32 | ||
|
||
// Set to true if pagination should stop if the service returns a pagination token | ||
// that matches the most recent token provided to the service. | ||
StopOnDuplicateToken bool | ||
} | ||
|
||
// ListObjectVersionsPaginator is a paginator for ListObjectVersions | ||
type ListObjectVersionsPaginator struct { | ||
options ListObjectVersionsPaginatorOptions | ||
client ListObjectVersionsAPIClient | ||
params *ListObjectVersionsInput | ||
firstPage bool | ||
keyMarker *string | ||
versionIDMarker *string | ||
isTruncated bool | ||
} | ||
|
||
// NewListObjectVersionsPaginator returns a new ListObjectVersionsPaginator | ||
func NewListObjectVersionsPaginator(client ListObjectVersionsAPIClient, params *ListObjectVersionsInput, optFns ...func(*ListObjectVersionsPaginatorOptions)) *ListObjectVersionsPaginator { | ||
if params == nil { | ||
params = &ListObjectVersionsInput{} | ||
} | ||
|
||
options := ListObjectVersionsPaginatorOptions{} | ||
options.Limit = params.MaxKeys | ||
|
||
for _, fn := range optFns { | ||
fn(&options) | ||
} | ||
|
||
return &ListObjectVersionsPaginator{ | ||
options: options, | ||
client: client, | ||
params: params, | ||
firstPage: true, | ||
keyMarker: params.KeyMarker, | ||
versionIDMarker: params.VersionIdMarker, | ||
} | ||
} | ||
|
||
// HasMorePages returns a boolean indicating whether more pages are available | ||
func (p *ListObjectVersionsPaginator) HasMorePages() bool { | ||
return p.firstPage || p.isTruncated | ||
} | ||
|
||
// NextPage retrieves the next ListObjectVersions page. | ||
func (p *ListObjectVersionsPaginator) NextPage(ctx context.Context, optFns ...func(*Options)) (*ListObjectVersionsOutput, error) { | ||
if !p.HasMorePages() { | ||
return nil, fmt.Errorf("no more pages available") | ||
} | ||
|
||
params := *p.params | ||
params.KeyMarker = p.keyMarker | ||
params.VersionIdMarker = p.versionIDMarker | ||
|
||
var limit int32 | ||
if p.options.Limit > 0 { | ||
limit = p.options.Limit | ||
} | ||
params.MaxKeys = limit | ||
|
||
result, err := p.client.ListObjectVersions(ctx, ¶ms, optFns...) | ||
if err != nil { | ||
return nil, err | ||
} | ||
p.firstPage = false | ||
|
||
prevToken := p.keyMarker | ||
p.isTruncated = result.IsTruncated | ||
p.keyMarker = nil | ||
p.versionIDMarker = nil | ||
if result.IsTruncated { | ||
p.keyMarker = result.NextKeyMarker | ||
p.versionIDMarker = result.NextVersionIdMarker | ||
} | ||
|
||
if p.options.StopOnDuplicateToken && | ||
prevToken != nil && | ||
p.keyMarker != nil && | ||
*prevToken == *p.keyMarker { | ||
p.isTruncated = false | ||
} | ||
|
||
return result, nil | ||
} | ||
|
||
// ListMultipartUploadsAPIClient is a client that implements the ListMultipartUploads | ||
// operation | ||
type ListMultipartUploadsAPIClient interface { | ||
ListMultipartUploads(context.Context, *ListMultipartUploadsInput, ...func(*Options)) (*ListMultipartUploadsOutput, error) | ||
} | ||
|
||
var _ ListMultipartUploadsAPIClient = (*Client)(nil) | ||
|
||
// ListMultipartUploadsPaginatorOptions is the paginator options for ListMultipartUploads | ||
type ListMultipartUploadsPaginatorOptions struct { | ||
// (Optional) The maximum number of Multipart Uploads that you want Amazon S3 to | ||
// return. | ||
Limit int32 | ||
|
||
// Set to true if pagination should stop if the service returns a pagination token | ||
// that matches the most recent token provided to the service. | ||
StopOnDuplicateToken bool | ||
} | ||
|
||
// ListMultipartUploadsPaginator is a paginator for ListMultipartUploads | ||
type ListMultipartUploadsPaginator struct { | ||
options ListMultipartUploadsPaginatorOptions | ||
client ListMultipartUploadsAPIClient | ||
params *ListMultipartUploadsInput | ||
firstPage bool | ||
keyMarker *string | ||
uploadIDMarker *string | ||
isTruncated bool | ||
} | ||
|
||
// NewListMultipartUploadsPaginator returns a new ListMultipartUploadsPaginator | ||
func NewListMultipartUploadsPaginator(client ListMultipartUploadsAPIClient, params *ListMultipartUploadsInput, optFns ...func(*ListMultipartUploadsPaginatorOptions)) *ListMultipartUploadsPaginator { | ||
if params == nil { | ||
params = &ListMultipartUploadsInput{} | ||
} | ||
|
||
options := ListMultipartUploadsPaginatorOptions{} | ||
options.Limit = params.MaxUploads | ||
|
||
for _, fn := range optFns { | ||
fn(&options) | ||
} | ||
|
||
return &ListMultipartUploadsPaginator{ | ||
options: options, | ||
client: client, | ||
params: params, | ||
firstPage: true, | ||
keyMarker: params.KeyMarker, | ||
uploadIDMarker: params.UploadIdMarker, | ||
} | ||
} | ||
|
||
// HasMorePages returns a boolean indicating whether more pages are available | ||
func (p *ListMultipartUploadsPaginator) HasMorePages() bool { | ||
return p.firstPage || p.isTruncated | ||
} | ||
|
||
// NextPage retrieves the next ListMultipartUploads page. | ||
func (p *ListMultipartUploadsPaginator) NextPage(ctx context.Context, optFns ...func(*Options)) (*ListMultipartUploadsOutput, error) { | ||
if !p.HasMorePages() { | ||
return nil, fmt.Errorf("no more pages available") | ||
} | ||
|
||
params := *p.params | ||
params.KeyMarker = p.keyMarker | ||
params.UploadIdMarker = p.uploadIDMarker | ||
|
||
var limit int32 | ||
if p.options.Limit > 0 { | ||
limit = p.options.Limit | ||
} | ||
params.MaxUploads = limit | ||
|
||
result, err := p.client.ListMultipartUploads(ctx, ¶ms, optFns...) | ||
if err != nil { | ||
return nil, err | ||
} | ||
p.firstPage = false | ||
|
||
prevToken := p.keyMarker | ||
p.isTruncated = result.IsTruncated | ||
p.keyMarker = nil | ||
p.uploadIDMarker = nil | ||
if result.IsTruncated { | ||
p.keyMarker = result.NextKeyMarker | ||
p.uploadIDMarker = result.NextUploadIdMarker | ||
} | ||
|
||
if p.options.StopOnDuplicateToken && | ||
prevToken != nil && | ||
p.keyMarker != nil && | ||
*prevToken == *p.keyMarker { | ||
p.isTruncated = false | ||
} | ||
|
||
return result, nil | ||
} |
Oops, something went wrong.