Skip to content

Commit

Permalink
good for the client
Browse files Browse the repository at this point in the history
  • Loading branch information
millotp committed Jul 15, 2024
1 parent 463eb62 commit d511b4b
Show file tree
Hide file tree
Showing 11 changed files with 328 additions and 548 deletions.
1 change: 1 addition & 0 deletions clients/algoliasearch-client-go/.golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ linters:
- canonicalheader
- mnd
- perfsprint
- containedctx

# Deprecated
- execinquery
Expand Down
6 changes: 3 additions & 3 deletions clients/algoliasearch-client-go/algolia/errs/wait_err.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ func NewWaitError(msg string) *WaitError {
}
}

func (e *WaitError) Error() string {
func (e WaitError) Error() string {
return e.msg
}

type WaitKeyUpdateError struct{}

func (e *WaitKeyUpdateError) Error() string {
func (e WaitKeyUpdateError) Error() string {
return "`apiKey` is required when waiting for an `update` operation."
}

type WaitKeyOperationError struct{}

func (e *WaitKeyOperationError) Error() string {
func (e WaitKeyOperationError) Error() string {
return "`operation` must be one of `add`, `update` or `delete`."
}
157 changes: 157 additions & 0 deletions clients/algoliasearch-client-go/algolia/utils/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package utils

import (
"context"
"net/url"
"time"
)

type Options struct {
// -- Request options for API calls
Context context.Context
QueryParams url.Values
HeaderParams map[string]string

// -- ChunkedBatch options
WaitForTasks bool
BatchSize int

// -- Iterable options
MaxRetries int
Timeout func(int) time.Duration
Aggregator func(any, error)
IterableError *IterableError
}

// --------- Request options for API calls ---------

type RequestOption interface {
Apply(*Options)
}

type requestOption func(*Options)

func (r requestOption) Apply(o *Options) {
r(o)
}

func WithContext(ctx context.Context) requestOption {
return requestOption(func(o *Options) {
o.Context = ctx
})
}

func WithHeaderParam(key, value string) requestOption {
return requestOption(func(o *Options) {
o.HeaderParams[key] = value
})
}

func WithQueryParam(key, value string) requestOption {
return requestOption(func(o *Options) {
o.QueryParams.Add(key, value)
})
}

// --------- ChunkedBatch options ---------

type ChunkedBatchOption interface {
RequestOption
chunkedBatch()
}

type chunkedBatchOption func(*Options)

var (
_ ChunkedBatchOption = (*chunkedBatchOption)(nil)
_ ChunkedBatchOption = (*requestOption)(nil)
)

func (c chunkedBatchOption) Apply(o *Options) {
c(o)
}

func (c chunkedBatchOption) chunkedBatch() {}

func (r requestOption) chunkedBatch() {}

func WithWaitForTasks(waitForTasks bool) chunkedBatchOption {
return chunkedBatchOption(func(o *Options) {
o.WaitForTasks = waitForTasks
})
}

func WithBatchSize(batchSize int) chunkedBatchOption {
return chunkedBatchOption(func(o *Options) {
o.BatchSize = batchSize
})
}

// --------- Iterable options ---------.
type IterableOption interface {
RequestOption
iterable()
}

type iterableOption func(*Options)

var (
_ IterableOption = (*iterableOption)(nil)
_ IterableOption = (*requestOption)(nil)
)

func (i iterableOption) Apply(o *Options) {
i(o)
}

func (r requestOption) iterable() {}

func (i iterableOption) iterable() {}

func WithMaxRetries(maxRetries int) iterableOption {
return iterableOption(func(o *Options) {
o.MaxRetries = maxRetries
})
}

func WithTimeout(timeout func(int) time.Duration) iterableOption {
return iterableOption(func(o *Options) {
o.Timeout = timeout
})
}

func WithAggregator(aggregator func(any, error)) iterableOption {
return iterableOption(func(o *Options) {
o.Aggregator = aggregator
})
}

func WithIterableError(iterableError *IterableError) iterableOption {
return iterableOption(func(o *Options) {
o.IterableError = iterableError
})
}

// --------- Helper to convert options ---------

func ToRequestOptions[T RequestOption](opts []T) []RequestOption {
requestOpts := make([]RequestOption, 0, len(opts))

for _, opt := range opts {
requestOpts = append(requestOpts, opt)
}

return requestOpts
}

func ToIterableOptions(opts []ChunkedBatchOption) []IterableOption {
iterableOpts := make([]IterableOption, 0, len(opts))

for _, opt := range opts {
if opt, ok := opt.(IterableOption); ok {
iterableOpts = append(iterableOpts, opt)
}
}

return iterableOpts
}
63 changes: 24 additions & 39 deletions clients/algoliasearch-client-go/algolia/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package utils

import (
"encoding/json"
"fmt"
"reflect"
"time"

Expand Down Expand Up @@ -65,54 +66,32 @@ func IsNilOrEmpty(i any) bool {
}
}

type IterableOptions[T any] struct {
Aggregator func(*T, error)
Timeout func() time.Duration
IterableErr *IterableError[T]
type IterableError struct {
Validate func(any, error) bool
Message func(any, error) string
}

type IterableOption[T any] func(*IterableOptions[T])

func WithAggregator[T any](aggregator func(*T, error)) IterableOption[T] {
return func(options *IterableOptions[T]) {
options.Aggregator = aggregator
}
}

func WithTimeout[T any](timeout func() time.Duration) IterableOption[T] {
return func(options *IterableOptions[T]) {
options.Timeout = timeout
}
}

func WithIterableError[T any](iterableErr *IterableError[T]) IterableOption[T] {
return func(options *IterableOptions[T]) {
options.IterableErr = iterableErr
}
}

type IterableError[T any] struct {
Validate func(*T, error) bool
Message func(*T, error) string
}

func CreateIterable[T any](execute func(*T, error) (*T, error), validate func(*T, error) bool, opts ...IterableOption[T]) (*T, error) {
options := IterableOptions[T]{
Aggregator: nil,
Timeout: func() time.Duration {
func CreateIterable[T any](execute func(*T, error) (*T, error), validate func(*T, error) bool, opts ...IterableOption) (*T, error) {
options := Options{
MaxRetries: 50,
Timeout: func(_ int) time.Duration {
return 1 * time.Second
},
IterableErr: nil,
}

for _, opt := range opts {
opt(&options)
opt.Apply(&options)
}

var executor func(*T, error) (*T, error)

retryCount := 0

executor = func(previousResponse *T, previousError error) (*T, error) {
response, responseErr := execute(previousResponse, previousError)

retryCount++

if options.Aggregator != nil {
options.Aggregator(response, responseErr)
}
Expand All @@ -121,15 +100,21 @@ func CreateIterable[T any](execute func(*T, error) (*T, error), validate func(*T
return response, responseErr
}

if options.IterableErr != nil && options.IterableErr.Validate(response, responseErr) {
if options.IterableErr.Message != nil {
return nil, errs.NewWaitError(options.IterableErr.Message(response, responseErr))
if retryCount >= options.MaxRetries {
return nil, errs.NewWaitError(fmt.Sprintf("The maximum number of retries exceeded. (%d/%d)", retryCount, options.MaxRetries))
}

if options.IterableError != nil && options.IterableError.Validate(response, responseErr) {
if options.IterableError.Message != nil {
return nil, errs.NewWaitError(options.IterableError.Message(response, responseErr))
}

return nil, errs.NewWaitError("an error occurred")
}

time.Sleep(options.Timeout())
fmt.Println("Sleeping for", options.Timeout(retryCount))

time.Sleep(options.Timeout(retryCount))

return executor(response, responseErr)
}
Expand Down
2 changes: 1 addition & 1 deletion playground/go/ingestion.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func testIngestion(appID, apiKey string) int {
// another example to generate payload for a request.
createAuthenticationResponse, err := ingestionClient.CreateAuthentication(ingestionClient.NewApiCreateAuthenticationRequest(
&ingestion.AuthenticationCreate{
Type: ingestion.AUTHENTICATIONTYPE_BASIC,
Type: ingestion.AUTHENTICATION_TYPE_BASIC,
Name: fmt.Sprintf("my-authentication-%d", time.Now().Unix()),
Input: ingestion.AuthInput{
AuthBasic: &ingestion.AuthBasic{
Expand Down
2 changes: 1 addition & 1 deletion playground/go/insights.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func testInsights(appID, apiKey string) int {

events := insights.NewInsightsEvents([]insights.EventsItems{
*insights.ClickedObjectIDsAsEventsItems(insights.NewClickedObjectIDs("myEvent",
insights.CLICKEVENT_CLICK,
insights.CLICK_EVENT_CLICK,
"test_index",
[]string{"myObjectID"},
"myToken",
Expand Down
4 changes: 3 additions & 1 deletion playground/go/personalization.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"time"

"github.com/algolia/algoliasearch-client-go/v4/algolia/personalization"
"github.com/algolia/algoliasearch-client-go/v4/algolia/utils"
)

func testPersonalization(appID, apiKey string) int {
Expand All @@ -17,8 +18,9 @@ func testPersonalization(appID, apiKey string) int {
defer cancel()

// it will fail expectedly because of the very short timeout to showcase the context usage.
deleteUserProfileResponse, err := personalizationClient.DeleteUserProfileWithContext(ctx,
deleteUserProfileResponse, err := personalizationClient.DeleteUserProfile(
personalizationClient.NewApiDeleteUserProfileRequest("userToken"),
utils.WithContext(ctx),
)
if err != nil {
fmt.Printf("request error with DeleteUserProfile: %v\n", err)
Expand Down
7 changes: 3 additions & 4 deletions playground/go/recommend.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"

"github.com/algolia/algoliasearch-client-go/v4/algolia/recommend"
"github.com/algolia/algoliasearch-client-go/v4/algolia/utils"
)

func testRecommend(appID, apiKey string) int {
Expand All @@ -22,11 +21,11 @@ func testRecommend(appID, apiKey string) int {
params := &recommend.GetRecommendationsParams{
Requests: []recommend.RecommendationsRequest{
{
RecommendationsQuery: &recommend.RecommendationsQuery{
Model: recommend.RECOMMENDATIONMODELS_BOUGHT_TOGETHER,
BoughtTogetherQuery: &recommend.BoughtTogetherQuery{
Model: recommend.FBT_MODEL_BOUGHT_TOGETHER,
ObjectID: "test_query",
IndexName: "test_index",
Threshold: utils.PtrInt32(0),
Threshold: 0,
},
},
},
Expand Down
Loading

0 comments on commit d511b4b

Please sign in to comment.