diff --git a/cmd/api/handler/stats.go b/cmd/api/handler/stats.go index 7f9e1c07..53fb0063 100644 --- a/cmd/api/handler/stats.go +++ b/cmd/api/handler/stats.go @@ -570,6 +570,8 @@ func (sh StatsHandler) Tvs(c echo.Context) error { // @Tags stats // @ID stats-tvs-series // @Param timeframe path string true "Timeframe" Enums(day, month) +// @Param from query integer false "Time from in unix timestamp" mininum(1) +// @Param to query integer false "Time to in unix timestamp" mininum(1) // @Produce json // @Success 200 {array} responses.SeriesItem // @Failure 400 {object} Error @@ -581,7 +583,11 @@ func (sh StatsHandler) TvsSeries(c echo.Context) error { return badRequestError(c, err) } - tvs, err := sh.repo.TvsSeries(c.Request().Context(), storage.Timeframe(req.Timeframe)) + tvs, err := sh.repo.TvsSeries( + c.Request().Context(), + storage.Timeframe(req.Timeframe), + storage.NewSeriesRequest(req.From, req.To)) + if err != nil { return handleError(c, err, sh.nsRepo) } @@ -597,5 +603,7 @@ func (sh StatsHandler) TvsSeries(c echo.Context) error { } type tvsSeriesRequest struct { - Timeframe string `example:"hour" param:"timeframe" swaggertype:"string" validate:"required,oneof=day month"` + Timeframe string `example:"hour" param:"timeframe" swaggertype:"string" validate:"required,oneof=day month"` + From int64 `example:"1692892095" query:"from" swaggertype:"integer" validate:"omitempty,min=1"` + To int64 `example:"1692892095" query:"to" swaggertype:"integer" validate:"omitempty,min=1"` } diff --git a/cmd/api/handler/stats_test.go b/cmd/api/handler/stats_test.go index 2b26707a..bd3744b1 100644 --- a/cmd/api/handler/stats_test.go +++ b/cmd/api/handler/stats_test.go @@ -616,7 +616,7 @@ func (s *StatsTestSuite) TestTvsSeries() { c.SetParamValues(string(tf)) s.stats.EXPECT(). - TvsSeries(gomock.Any(), tf). + TvsSeries(gomock.Any(), tf, gomock.Any()). Return([]storage.SeriesItem{ { Time: testTime, diff --git a/internal/storage/mock/stats.go b/internal/storage/mock/stats.go index b4846914..b948cbfb 100644 --- a/internal/storage/mock/stats.go +++ b/internal/storage/mock/stats.go @@ -515,18 +515,18 @@ func (c *MockIStatsTvsCall) DoAndReturn(f func(context.Context) (decimal.Decimal } // TvsSeries mocks base method. -func (m *MockIStats) TvsSeries(ctx context.Context, timeframe storage.Timeframe) ([]storage.SeriesItem, error) { +func (m *MockIStats) TvsSeries(ctx context.Context, timeframe storage.Timeframe, req storage.SeriesRequest) ([]storage.SeriesItem, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TvsSeries", ctx, timeframe) + ret := m.ctrl.Call(m, "TvsSeries", ctx, timeframe, req) ret0, _ := ret[0].([]storage.SeriesItem) ret1, _ := ret[1].(error) return ret0, ret1 } // TvsSeries indicates an expected call of TvsSeries. -func (mr *MockIStatsMockRecorder) TvsSeries(ctx, timeframe any) *MockIStatsTvsSeriesCall { +func (mr *MockIStatsMockRecorder) TvsSeries(ctx, timeframe, req any) *MockIStatsTvsSeriesCall { mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TvsSeries", reflect.TypeOf((*MockIStats)(nil).TvsSeries), ctx, timeframe) + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TvsSeries", reflect.TypeOf((*MockIStats)(nil).TvsSeries), ctx, timeframe, req) return &MockIStatsTvsSeriesCall{Call: call} } @@ -542,13 +542,13 @@ func (c *MockIStatsTvsSeriesCall) Return(arg0 []storage.SeriesItem, arg1 error) } // Do rewrite *gomock.Call.Do -func (c *MockIStatsTvsSeriesCall) Do(f func(context.Context, storage.Timeframe) ([]storage.SeriesItem, error)) *MockIStatsTvsSeriesCall { +func (c *MockIStatsTvsSeriesCall) Do(f func(context.Context, storage.Timeframe, storage.SeriesRequest) ([]storage.SeriesItem, error)) *MockIStatsTvsSeriesCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockIStatsTvsSeriesCall) DoAndReturn(f func(context.Context, storage.Timeframe) ([]storage.SeriesItem, error)) *MockIStatsTvsSeriesCall { +func (c *MockIStatsTvsSeriesCall) DoAndReturn(f func(context.Context, storage.Timeframe, storage.SeriesRequest) ([]storage.SeriesItem, error)) *MockIStatsTvsSeriesCall { c.Call = c.Call.DoAndReturn(f) return c } diff --git a/internal/storage/postgres/stats.go b/internal/storage/postgres/stats.go index 32caa599..7bfe0a68 100644 --- a/internal/storage/postgres/stats.go +++ b/internal/storage/postgres/stats.go @@ -438,7 +438,7 @@ func (s Stats) Tvs(ctx context.Context) (tvs decimal.Decimal, err error) { return } -func (s Stats) TvsSeries(ctx context.Context, timeframe storage.Timeframe) (response []storage.SeriesItem, err error) { +func (s Stats) TvsSeries(ctx context.Context, timeframe storage.Timeframe, req storage.SeriesRequest) (response []storage.SeriesItem, err error) { query := s.db.DB().NewSelect() switch timeframe { @@ -452,6 +452,13 @@ func (s Stats) TvsSeries(ctx context.Context, timeframe storage.Timeframe) (resp return nil, errors.Errorf("unexpected timeframe %s", timeframe) } + if !req.From.IsZero() { + query = query.Where("time >= ?", req.From) + } + if !req.To.IsZero() { + query = query.Where("time < ?", req.To) + } + err = query.Order("time desc"). Limit(100). Scan(ctx, &response) diff --git a/internal/storage/stats.go b/internal/storage/stats.go index 4fd52002..3b614786 100644 --- a/internal/storage/stats.go +++ b/internal/storage/stats.go @@ -182,5 +182,5 @@ type IStats interface { Change24hBlockStats(ctx context.Context) (response Change24hBlockStats, err error) MessagesCount24h(ctx context.Context) ([]CountItem, error) Tvs(ctx context.Context) (decimal.Decimal, error) - TvsSeries(ctx context.Context, timeframe Timeframe) ([]SeriesItem, error) + TvsSeries(ctx context.Context, timeframe Timeframe, req SeriesRequest) ([]SeriesItem, error) }