sixth version
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
package tinvest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
|
||||
"overnight-trading-bot/internal/domain"
|
||||
)
|
||||
|
||||
type PaperGateway struct {
|
||||
market Gateway
|
||||
fake *FakeGateway
|
||||
}
|
||||
|
||||
func NewPaperGateway(market Gateway) *PaperGateway {
|
||||
return &PaperGateway{market: market, fake: NewFakeGateway()}
|
||||
}
|
||||
|
||||
func (g *PaperGateway) Fake() *FakeGateway {
|
||||
if g.fake == nil {
|
||||
g.fake = NewFakeGateway()
|
||||
}
|
||||
return g.fake
|
||||
}
|
||||
|
||||
func (g *PaperGateway) GetInstrument(ctx context.Context, ticker, classCode string) (domain.Instrument, error) {
|
||||
if g.market != nil {
|
||||
return g.market.GetInstrument(ctx, ticker, classCode)
|
||||
}
|
||||
return g.Fake().GetInstrument(ctx, ticker, classCode)
|
||||
}
|
||||
|
||||
func (g *PaperGateway) GetCandles(ctx context.Context, instrumentUID string, interval string, from, to time.Time) ([]domain.Candle, error) {
|
||||
if g.market != nil {
|
||||
return g.market.GetCandles(ctx, instrumentUID, interval, from, to)
|
||||
}
|
||||
return g.Fake().GetCandles(ctx, instrumentUID, interval, from, to)
|
||||
}
|
||||
|
||||
func (g *PaperGateway) GetOrderBook(ctx context.Context, instrumentUID string, depth int32) (domain.OrderBook, error) {
|
||||
if g.market != nil {
|
||||
return g.market.GetOrderBook(ctx, instrumentUID, depth)
|
||||
}
|
||||
return g.Fake().GetOrderBook(ctx, instrumentUID, depth)
|
||||
}
|
||||
|
||||
func (g *PaperGateway) GetTradingStatus(ctx context.Context, instrumentUID string) (domain.TradingStatus, error) {
|
||||
if g.market != nil {
|
||||
return g.market.GetTradingStatus(ctx, instrumentUID)
|
||||
}
|
||||
return g.Fake().GetTradingStatus(ctx, instrumentUID)
|
||||
}
|
||||
|
||||
func (g *PaperGateway) PostLimitOrder(ctx context.Context, accountID, instrumentUID string, side domain.Side, lots int64, price decimal.Decimal, clientOrderID string) (domain.Order, error) {
|
||||
return g.Fake().PostLimitOrder(ctx, accountID, instrumentUID, side, lots, price, clientOrderID)
|
||||
}
|
||||
|
||||
func (g *PaperGateway) CancelOrder(ctx context.Context, accountID, orderID string) error {
|
||||
return g.Fake().CancelOrder(ctx, accountID, orderID)
|
||||
}
|
||||
|
||||
func (g *PaperGateway) GetOrderState(ctx context.Context, accountID, orderID string) (domain.Order, error) {
|
||||
return g.Fake().GetOrderState(ctx, accountID, orderID)
|
||||
}
|
||||
|
||||
func (g *PaperGateway) GetActiveOrders(ctx context.Context, accountID string) ([]domain.Order, error) {
|
||||
return g.Fake().GetActiveOrders(ctx, accountID)
|
||||
}
|
||||
|
||||
func (g *PaperGateway) GetPortfolio(ctx context.Context, accountID string) (domain.Portfolio, error) {
|
||||
return g.Fake().GetPortfolio(ctx, accountID)
|
||||
}
|
||||
|
||||
func (g *PaperGateway) GetOperations(ctx context.Context, accountID string, from, to time.Time) ([]domain.Operation, error) {
|
||||
return g.Fake().GetOperations(ctx, accountID, from, to)
|
||||
}
|
||||
|
||||
func (g *PaperGateway) GetServerTime(ctx context.Context) (time.Time, error) {
|
||||
if g.market != nil {
|
||||
return g.market.GetServerTime(ctx)
|
||||
}
|
||||
return g.Fake().GetServerTime(ctx)
|
||||
}
|
||||
+84
-58
@@ -23,24 +23,26 @@ import (
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
Token string
|
||||
AccountID string
|
||||
Endpoint string
|
||||
AppName string
|
||||
RetryCount int
|
||||
RetryBackoff time.Duration
|
||||
Logger *slog.Logger
|
||||
Token string
|
||||
AccountID string
|
||||
Endpoint string
|
||||
AppName string
|
||||
RequestTimeout time.Duration
|
||||
RetryCount int
|
||||
RetryBackoff time.Duration
|
||||
Logger *slog.Logger
|
||||
}
|
||||
|
||||
type RealGateway struct {
|
||||
client *investgo.Client
|
||||
instruments *investgo.InstrumentsServiceClient
|
||||
marketData *investgo.MarketDataServiceClient
|
||||
orders *investgo.OrdersServiceClient
|
||||
operations *investgo.OperationsServiceClient
|
||||
users *investgo.UsersServiceClient
|
||||
retryAttempts int
|
||||
retryBackoff time.Duration
|
||||
client *investgo.Client
|
||||
instruments *investgo.InstrumentsServiceClient
|
||||
marketData *investgo.MarketDataServiceClient
|
||||
orders *investgo.OrdersServiceClient
|
||||
operations *investgo.OperationsServiceClient
|
||||
users *investgo.UsersServiceClient
|
||||
requestTimeout time.Duration
|
||||
retryAttempts int
|
||||
retryBackoff time.Duration
|
||||
}
|
||||
|
||||
func NewRealGateway(ctx context.Context, opts Options) (*RealGateway, error) {
|
||||
@@ -58,14 +60,15 @@ func NewRealGateway(ctx context.Context, opts Options) (*RealGateway, error) {
|
||||
return nil, err
|
||||
}
|
||||
return &RealGateway{
|
||||
client: client,
|
||||
instruments: client.NewInstrumentsServiceClient(),
|
||||
marketData: client.NewMarketDataServiceClient(),
|
||||
orders: client.NewOrdersServiceClient(),
|
||||
operations: client.NewOperationsServiceClient(),
|
||||
users: client.NewUsersServiceClient(),
|
||||
retryAttempts: opts.RetryCount,
|
||||
retryBackoff: opts.RetryBackoff,
|
||||
client: client,
|
||||
instruments: client.NewInstrumentsServiceClient(),
|
||||
marketData: client.NewMarketDataServiceClient(),
|
||||
orders: client.NewOrdersServiceClient(),
|
||||
operations: client.NewOperationsServiceClient(),
|
||||
users: client.NewUsersServiceClient(),
|
||||
requestTimeout: opts.RequestTimeout,
|
||||
retryAttempts: opts.RetryCount,
|
||||
retryBackoff: opts.RetryBackoff,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -80,8 +83,10 @@ func (g *RealGateway) GetInstrument(ctx context.Context, ticker, classCode strin
|
||||
if err := ctx.Err(); err != nil {
|
||||
return domain.Instrument{}, err
|
||||
}
|
||||
resp, err := retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.EtfResponse, error) {
|
||||
return g.instruments.EtfByTicker(ticker, classCode)
|
||||
resp, err := requestWithTimeout(ctx, g.requestTimeout, func() (*investgo.EtfResponse, error) {
|
||||
return retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.EtfResponse, error) {
|
||||
return g.instruments.EtfByTicker(ticker, classCode)
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return domain.Instrument{}, err
|
||||
@@ -108,8 +113,10 @@ func (g *RealGateway) GetCandles(ctx context.Context, instrumentUID string, inte
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.GetCandlesResponse, error) {
|
||||
return g.marketData.GetCandles(instrumentUID, candleInterval(interval), from, to, pb.GetCandlesRequest_CANDLE_SOURCE_EXCHANGE, 0)
|
||||
resp, err := requestWithTimeout(ctx, g.requestTimeout, func() (*investgo.GetCandlesResponse, error) {
|
||||
return retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.GetCandlesResponse, error) {
|
||||
return g.marketData.GetCandles(instrumentUID, candleInterval(interval), from, to, pb.GetCandlesRequest_CANDLE_SOURCE_EXCHANGE, 0)
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -136,8 +143,10 @@ func (g *RealGateway) GetOrderBook(ctx context.Context, instrumentUID string, de
|
||||
if err := ctx.Err(); err != nil {
|
||||
return domain.OrderBook{}, err
|
||||
}
|
||||
resp, err := retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.GetOrderBookResponse, error) {
|
||||
return g.marketData.GetOrderBook(instrumentUID, depth)
|
||||
resp, err := requestWithTimeout(ctx, g.requestTimeout, func() (*investgo.GetOrderBookResponse, error) {
|
||||
return retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.GetOrderBookResponse, error) {
|
||||
return g.marketData.GetOrderBook(instrumentUID, depth)
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return domain.OrderBook{}, err
|
||||
@@ -155,8 +164,10 @@ func (g *RealGateway) GetTradingStatus(ctx context.Context, instrumentUID string
|
||||
if err := ctx.Err(); err != nil {
|
||||
return domain.TradingStatusUnknown, err
|
||||
}
|
||||
resp, err := retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.GetTradingStatusResponse, error) {
|
||||
return g.marketData.GetTradingStatus(instrumentUID)
|
||||
resp, err := requestWithTimeout(ctx, g.requestTimeout, func() (*investgo.GetTradingStatusResponse, error) {
|
||||
return retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.GetTradingStatusResponse, error) {
|
||||
return g.marketData.GetTradingStatus(instrumentUID)
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return domain.TradingStatusUnknown, err
|
||||
@@ -181,17 +192,19 @@ func (g *RealGateway) PostLimitOrder(ctx context.Context, accountID, instrumentU
|
||||
if err != nil {
|
||||
return domain.Order{}, err
|
||||
}
|
||||
resp, err := retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.PostOrderResponse, error) {
|
||||
return g.orders.PostOrder(&investgo.PostOrderRequest{
|
||||
InstrumentId: instrumentUID,
|
||||
Quantity: lots,
|
||||
Price: quotation,
|
||||
Direction: direction,
|
||||
AccountId: accountID,
|
||||
OrderType: pb.OrderType_ORDER_TYPE_LIMIT,
|
||||
OrderId: clientOrderID,
|
||||
TimeInForce: pb.TimeInForceType_TIME_IN_FORCE_DAY,
|
||||
PriceType: pb.PriceType_PRICE_TYPE_CURRENCY,
|
||||
resp, err := requestWithTimeout(ctx, g.requestTimeout, func() (*investgo.PostOrderResponse, error) {
|
||||
return retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.PostOrderResponse, error) {
|
||||
return g.orders.PostOrder(&investgo.PostOrderRequest{
|
||||
InstrumentId: instrumentUID,
|
||||
Quantity: lots,
|
||||
Price: quotation,
|
||||
Direction: direction,
|
||||
AccountId: accountID,
|
||||
OrderType: pb.OrderType_ORDER_TYPE_LIMIT,
|
||||
OrderId: clientOrderID,
|
||||
TimeInForce: pb.TimeInForceType_TIME_IN_FORCE_DAY,
|
||||
PriceType: pb.PriceType_PRICE_TYPE_CURRENCY,
|
||||
})
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
@@ -204,18 +217,23 @@ func (g *RealGateway) CancelOrder(ctx context.Context, accountID, orderID string
|
||||
if err := ctx.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
return withRetry(ctx, g.retryAttempts, g.retryBackoff, func() error {
|
||||
_, err := g.orders.CancelOrder(accountID, orderID, nil)
|
||||
return err
|
||||
_, err := requestWithTimeout(ctx, g.requestTimeout, func() (struct{}, error) {
|
||||
return struct{}{}, withRetry(ctx, g.retryAttempts, g.retryBackoff, func() error {
|
||||
_, err := g.orders.CancelOrder(accountID, orderID, nil)
|
||||
return err
|
||||
})
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (g *RealGateway) GetOrderState(ctx context.Context, accountID, orderID string) (domain.Order, error) {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return domain.Order{}, err
|
||||
}
|
||||
resp, err := retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.GetOrderStateResponse, error) {
|
||||
return g.orders.GetOrderState(accountID, orderID, pb.PriceType_PRICE_TYPE_CURRENCY, nil)
|
||||
resp, err := requestWithTimeout(ctx, g.requestTimeout, func() (*investgo.GetOrderStateResponse, error) {
|
||||
return retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.GetOrderStateResponse, error) {
|
||||
return g.orders.GetOrderState(accountID, orderID, pb.PriceType_PRICE_TYPE_CURRENCY, nil)
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return domain.Order{}, err
|
||||
@@ -227,8 +245,10 @@ func (g *RealGateway) GetActiveOrders(ctx context.Context, accountID string) ([]
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.GetOrdersResponse, error) {
|
||||
return g.orders.GetOrders(accountID, nil)
|
||||
resp, err := requestWithTimeout(ctx, g.requestTimeout, func() (*investgo.GetOrdersResponse, error) {
|
||||
return retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.GetOrdersResponse, error) {
|
||||
return g.orders.GetOrders(accountID, nil)
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -245,8 +265,10 @@ func (g *RealGateway) GetPortfolio(ctx context.Context, accountID string) (domai
|
||||
if err := ctx.Err(); err != nil {
|
||||
return domain.Portfolio{}, err
|
||||
}
|
||||
resp, err := retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.PortfolioResponse, error) {
|
||||
return g.operations.GetPortfolio(accountID, pb.PortfolioRequest_RUB)
|
||||
resp, err := requestWithTimeout(ctx, g.requestTimeout, func() (*investgo.PortfolioResponse, error) {
|
||||
return retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.PortfolioResponse, error) {
|
||||
return g.operations.GetPortfolio(accountID, pb.PortfolioRequest_RUB)
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return domain.Portfolio{}, err
|
||||
@@ -258,11 +280,13 @@ func (g *RealGateway) GetOperations(ctx context.Context, accountID string, from,
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.OperationsResponse, error) {
|
||||
return g.operations.GetOperations(&investgo.GetOperationsRequest{
|
||||
AccountId: accountID,
|
||||
From: from,
|
||||
To: to,
|
||||
resp, err := requestWithTimeout(ctx, g.requestTimeout, func() (*investgo.OperationsResponse, error) {
|
||||
return retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.OperationsResponse, error) {
|
||||
return g.operations.GetOperations(&investgo.GetOperationsRequest{
|
||||
AccountId: accountID,
|
||||
From: from,
|
||||
To: to,
|
||||
})
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
@@ -319,8 +343,10 @@ func (g *RealGateway) GetServerTime(ctx context.Context) (time.Time, error) {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
resp, err := retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.GetInfoResponse, error) {
|
||||
return g.users.GetInfo()
|
||||
resp, err := requestWithTimeout(ctx, g.requestTimeout, func() (*investgo.GetInfoResponse, error) {
|
||||
return retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.GetInfoResponse, error) {
|
||||
return g.users.GetInfo()
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
|
||||
@@ -62,3 +62,27 @@ func retryValue[T any](ctx context.Context, attempts int, interval time.Duration
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func requestWithTimeout[T any](ctx context.Context, timeout time.Duration, fn func() (T, error)) (T, error) {
|
||||
if timeout <= 0 {
|
||||
return fn()
|
||||
}
|
||||
callCtx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
type result struct {
|
||||
value T
|
||||
err error
|
||||
}
|
||||
done := make(chan result, 1)
|
||||
go func() {
|
||||
value, err := fn()
|
||||
done <- result{value: value, err: err}
|
||||
}()
|
||||
select {
|
||||
case res := <-done:
|
||||
return res.value, res.err
|
||||
case <-callCtx.Done():
|
||||
var zero T
|
||||
return zero, callCtx.Err()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,16 @@ func TestWithRetryRetriesUntilSuccess(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRequestWithTimeoutReturnsDeadline(t *testing.T) {
|
||||
_, err := requestWithTimeout(context.Background(), time.Millisecond, func() (int, error) {
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
return 1, nil
|
||||
})
|
||||
if !errors.Is(err, context.DeadlineExceeded) {
|
||||
t.Fatalf("err=%v, want DeadlineExceeded", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithRetryStopsOnContextCancel(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
|
||||
+38
-25
@@ -43,17 +43,19 @@ func (g *SandboxGateway) PostLimitOrder(ctx context.Context, accountID, instrume
|
||||
if err != nil {
|
||||
return domain.Order{}, err
|
||||
}
|
||||
resp, err := retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.PostOrderResponse, error) {
|
||||
return g.sandbox.PostSandboxOrder(&investgo.PostOrderRequest{
|
||||
InstrumentId: instrumentUID,
|
||||
Quantity: lots,
|
||||
Price: quotation,
|
||||
Direction: direction,
|
||||
AccountId: accountID,
|
||||
OrderType: pb.OrderType_ORDER_TYPE_LIMIT,
|
||||
OrderId: clientOrderID,
|
||||
TimeInForce: pb.TimeInForceType_TIME_IN_FORCE_DAY,
|
||||
PriceType: pb.PriceType_PRICE_TYPE_CURRENCY,
|
||||
resp, err := requestWithTimeout(ctx, g.requestTimeout, func() (*investgo.PostOrderResponse, error) {
|
||||
return retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.PostOrderResponse, error) {
|
||||
return g.sandbox.PostSandboxOrder(&investgo.PostOrderRequest{
|
||||
InstrumentId: instrumentUID,
|
||||
Quantity: lots,
|
||||
Price: quotation,
|
||||
Direction: direction,
|
||||
AccountId: accountID,
|
||||
OrderType: pb.OrderType_ORDER_TYPE_LIMIT,
|
||||
OrderId: clientOrderID,
|
||||
TimeInForce: pb.TimeInForceType_TIME_IN_FORCE_DAY,
|
||||
PriceType: pb.PriceType_PRICE_TYPE_CURRENCY,
|
||||
})
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
@@ -66,18 +68,23 @@ func (g *SandboxGateway) CancelOrder(ctx context.Context, accountID, orderID str
|
||||
if err := ctx.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
return withRetry(ctx, g.retryAttempts, g.retryBackoff, func() error {
|
||||
_, err := g.sandbox.CancelSandboxOrder(accountID, orderID)
|
||||
return err
|
||||
_, err := requestWithTimeout(ctx, g.requestTimeout, func() (struct{}, error) {
|
||||
return struct{}{}, withRetry(ctx, g.retryAttempts, g.retryBackoff, func() error {
|
||||
_, err := g.sandbox.CancelSandboxOrder(accountID, orderID)
|
||||
return err
|
||||
})
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (g *SandboxGateway) GetOrderState(ctx context.Context, accountID, orderID string) (domain.Order, error) {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return domain.Order{}, err
|
||||
}
|
||||
resp, err := retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.GetOrderStateResponse, error) {
|
||||
return g.sandbox.GetSandboxOrderState(accountID, orderID)
|
||||
resp, err := requestWithTimeout(ctx, g.requestTimeout, func() (*investgo.GetOrderStateResponse, error) {
|
||||
return retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.GetOrderStateResponse, error) {
|
||||
return g.sandbox.GetSandboxOrderState(accountID, orderID)
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return domain.Order{}, err
|
||||
@@ -89,8 +96,10 @@ func (g *SandboxGateway) GetActiveOrders(ctx context.Context, accountID string)
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.GetOrdersResponse, error) {
|
||||
return g.sandbox.GetSandboxOrders(accountID)
|
||||
resp, err := requestWithTimeout(ctx, g.requestTimeout, func() (*investgo.GetOrdersResponse, error) {
|
||||
return retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.GetOrdersResponse, error) {
|
||||
return g.sandbox.GetSandboxOrders(accountID)
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -107,8 +116,10 @@ func (g *SandboxGateway) GetPortfolio(ctx context.Context, accountID string) (do
|
||||
if err := ctx.Err(); err != nil {
|
||||
return domain.Portfolio{}, err
|
||||
}
|
||||
resp, err := retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.PortfolioResponse, error) {
|
||||
return g.sandbox.GetSandboxPortfolio(accountID, pb.PortfolioRequest_RUB)
|
||||
resp, err := requestWithTimeout(ctx, g.requestTimeout, func() (*investgo.PortfolioResponse, error) {
|
||||
return retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.PortfolioResponse, error) {
|
||||
return g.sandbox.GetSandboxPortfolio(accountID, pb.PortfolioRequest_RUB)
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return domain.Portfolio{}, err
|
||||
@@ -120,11 +131,13 @@ func (g *SandboxGateway) GetOperations(ctx context.Context, accountID string, fr
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.OperationsResponse, error) {
|
||||
return g.sandbox.GetSandboxOperations(&investgo.GetOperationsRequest{
|
||||
AccountId: accountID,
|
||||
From: from,
|
||||
To: to,
|
||||
resp, err := requestWithTimeout(ctx, g.requestTimeout, func() (*investgo.OperationsResponse, error) {
|
||||
return retryValue(ctx, g.retryAttempts, g.retryBackoff, func() (*investgo.OperationsResponse, error) {
|
||||
return g.sandbox.GetSandboxOperations(&investgo.GetOperationsRequest{
|
||||
AccountId: accountID,
|
||||
From: from,
|
||||
To: to,
|
||||
})
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user