// Copyright 2022 Huawei Technologies Co.,Ltd. // // Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package invoker import ( "time" "github.com/huaweicloud/huaweicloud-sdk-go-v3/core" "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth" "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/def" "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/exchange" "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker/retry" ) type RetryChecker func(interface{}, error) bool type BaseInvoker struct { Exchange *exchange.SdkExchange client *core.HcHttpClient request interface{} meta *def.HttpRequestDef headers map[string]string retryTimes int retryChecker RetryChecker backoffStrategy retry.Strategy } func NewBaseInvoker(client *core.HcHttpClient, request interface{}, meta *def.HttpRequestDef) *BaseInvoker { exch := &exchange.SdkExchange{ ApiReference: &exchange.ApiReference{ Method: meta.Method, Path: meta.Path, }, Attributes: make(map[string]interface{}), } return &BaseInvoker{ Exchange: exch, client: client, request: request, meta: meta, headers: make(map[string]string), } } func (b *BaseInvoker) ReplaceCredentialWhen(fun func(auth.ICredential) auth.ICredential) *BaseInvoker { b.client.WithCredential(fun(b.client.GetCredential())) return b } // Deprecated: This function will be removed in the future version, use AddHeaders instead. func (b *BaseInvoker) AddHeader(headers map[string]string) *BaseInvoker { return b.AddHeaders(headers) } func (b *BaseInvoker) AddHeaders(headers map[string]string) *BaseInvoker { if headers != nil { for k, v := range headers { b.headers[k] = v } } return b } func (b *BaseInvoker) WithRetry(retryTimes int, checker RetryChecker, backoffStrategy retry.Strategy) *BaseInvoker { b.retryTimes = retryTimes b.retryChecker = checker b.backoffStrategy = backoffStrategy return b } func (b *BaseInvoker) Invoke() (interface{}, error) { if b.retryTimes == 0 || b.retryChecker == nil { return b.client.SyncInvokeWithExtraHeaders(b.request, b.meta, b.Exchange, b.headers) } var execTimes int var resp interface{} var err error for { resp, err = b.client.SyncInvokeWithExtraHeaders(b.request, b.meta, b.Exchange, b.headers) execTimes++ if execTimes > b.retryTimes || !b.retryChecker(resp, err) { break } delay := b.backoffStrategy.ComputeDelayBeforeNextRetry(int32(execTimes)) if delay > 0 { time.Sleep(time.Duration(delay) * time.Millisecond) } } return resp, err }