Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: check offset, limit, totalCount before executing query #4975

Merged
merged 1 commit into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 29 additions & 10 deletions internal/core/data/application/event.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (C) 2020 IOTech Ltd
// Copyright (C) 2020-2024 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0

Expand All @@ -21,6 +21,7 @@ import (

"github.com/edgexfoundry/edgex-go/internal/core/data/container"
"github.com/edgexfoundry/edgex-go/internal/pkg/correlation"
"github.com/edgexfoundry/edgex-go/internal/pkg/utils"

"github.com/google/uuid"
)
Expand Down Expand Up @@ -188,10 +189,16 @@ func (a *CoreDataApp) DeleteEventsByDeviceName(deviceName string, dic *di.Contai
// AllEvents query events by offset and limit
func (a *CoreDataApp) AllEvents(offset int, limit int, dic *di.Container) (events []dtos.Event, totalCount uint32, err errors.EdgeX) {
dbClient := container.DBClientFrom(dic.Get)
eventModels, err := dbClient.AllEvents(offset, limit)
if err == nil {
totalCount, err = dbClient.EventTotalCount()
totalCount, err = dbClient.EventTotalCount()
if err != nil {
return events, totalCount, errors.NewCommonEdgeXWrapper(err)
}
cont, err := utils.CheckCountRange(totalCount, offset, limit)
if !cont {
return []dtos.Event{}, totalCount, err
}

eventModels, err := dbClient.AllEvents(offset, limit)
if err != nil {
return events, totalCount, errors.NewCommonEdgeXWrapper(err)
}
Expand All @@ -208,10 +215,16 @@ func (a *CoreDataApp) EventsByDeviceName(offset int, limit int, name string, dic
return events, totalCount, errors.NewCommonEdgeX(errors.KindContractInvalid, "name is empty", nil)
}
dbClient := container.DBClientFrom(dic.Get)
eventModels, err := dbClient.EventsByDeviceName(offset, limit, name)
if err == nil {
totalCount, err = dbClient.EventCountByDeviceName(name)
totalCount, err = dbClient.EventCountByDeviceName(name)
if err != nil {
return events, totalCount, errors.NewCommonEdgeXWrapper(err)
}
cont, err := utils.CheckCountRange(totalCount, offset, limit)
if !cont {
return []dtos.Event{}, totalCount, err
}

eventModels, err := dbClient.EventsByDeviceName(offset, limit, name)
if err != nil {
return events, totalCount, errors.NewCommonEdgeXWrapper(err)
}
Expand All @@ -225,10 +238,16 @@ func (a *CoreDataApp) EventsByDeviceName(offset int, limit int, name string, dic
// EventsByTimeRange query events with offset, limit and time range
func (a *CoreDataApp) EventsByTimeRange(startTime int64, endTime int64, offset int, limit int, dic *di.Container) (events []dtos.Event, totalCount uint32, err errors.EdgeX) {
dbClient := container.DBClientFrom(dic.Get)
eventModels, err := dbClient.EventsByTimeRange(startTime, endTime, offset, limit)
if err == nil {
totalCount, err = dbClient.EventCountByTimeRange(startTime, endTime)
totalCount, err = dbClient.EventCountByTimeRange(startTime, endTime)
if err != nil {
return events, totalCount, errors.NewCommonEdgeXWrapper(err)
}
cont, err := utils.CheckCountRange(totalCount, offset, limit)
if !cont {
return []dtos.Event{}, totalCount, err
}

eventModels, err := dbClient.EventsByTimeRange(startTime, endTime, offset, limit)
if err != nil {
return events, totalCount, errors.NewCommonEdgeXWrapper(err)
}
Expand Down
140 changes: 83 additions & 57 deletions internal/core/data/application/reading.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (C) 2021-2023 IOTech Ltd
// Copyright (C) 2021-2024 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0

Expand All @@ -18,6 +18,7 @@ import (
"github.com/edgexfoundry/go-mod-core-contracts/v3/models"

"github.com/edgexfoundry/edgex-go/internal/core/data/container"
"github.com/edgexfoundry/edgex-go/internal/pkg/utils"
)

var asyncPurgeReadingOnce sync.Once
Expand All @@ -37,18 +38,21 @@ func ReadingTotalCount(dic *di.Container) (uint32, errors.EdgeX) {
// AllReadings query events by offset, and limit
func AllReadings(offset int, limit int, dic *di.Container) (readings []dtos.BaseReading, totalCount uint32, err errors.EdgeX) {
dbClient := container.DBClientFrom(dic.Get)
readingModels, err := dbClient.AllReadings(offset, limit)
if err == nil {
readings, err = convertReadingModelsToDTOs(readingModels)
if err == nil {
totalCount, err = dbClient.ReadingTotalCount()
}
totalCount, err = dbClient.ReadingTotalCount()
if err != nil {
return readings, totalCount, errors.NewCommonEdgeXWrapper(err)
}
cont, err := utils.CheckCountRange(totalCount, offset, limit)
if !cont {
return []dtos.BaseReading{}, totalCount, err
}

readingModels, err := dbClient.AllReadings(offset, limit)
if err != nil {
return readings, totalCount, errors.NewCommonEdgeXWrapper(err)
}
return readings, totalCount, nil
readings, err = convertReadingModelsToDTOs(readingModels)
return readings, totalCount, err
}

// ReadingsByResourceName query readings with offset, limit, and resource name
Expand All @@ -57,18 +61,22 @@ func ReadingsByResourceName(offset int, limit int, resourceName string, dic *di.
return readings, totalCount, errors.NewCommonEdgeX(errors.KindContractInvalid, "resourceName is empty", nil)
}
dbClient := container.DBClientFrom(dic.Get)
readingModels, err := dbClient.ReadingsByResourceName(offset, limit, resourceName)
if err == nil {
readings, err = convertReadingModelsToDTOs(readingModels)
if err == nil {
totalCount, err = dbClient.ReadingCountByResourceName(resourceName)
}

totalCount, err = dbClient.ReadingCountByResourceName(resourceName)
if err != nil {
return readings, totalCount, errors.NewCommonEdgeXWrapper(err)
}
cont, err := utils.CheckCountRange(totalCount, offset, limit)
if !cont {
return []dtos.BaseReading{}, totalCount, err
}

readingModels, err := dbClient.ReadingsByResourceName(offset, limit, resourceName)
if err != nil {
return readings, totalCount, errors.NewCommonEdgeXWrapper(err)
}
return readings, totalCount, nil
readings, err = convertReadingModelsToDTOs(readingModels)
return readings, totalCount, err
}

// ReadingsByDeviceName query readings with offset, limit, and device name
Expand All @@ -77,35 +85,42 @@ func ReadingsByDeviceName(offset int, limit int, name string, dic *di.Container)
return readings, totalCount, errors.NewCommonEdgeX(errors.KindContractInvalid, "name is empty", nil)
}
dbClient := container.DBClientFrom(dic.Get)
readingModels, err := dbClient.ReadingsByDeviceName(offset, limit, name)
if err == nil {
readings, err = convertReadingModelsToDTOs(readingModels)
if err == nil {
totalCount, err = dbClient.ReadingCountByDeviceName(name)
}

totalCount, err = dbClient.ReadingCountByDeviceName(name)
if err != nil {
return readings, totalCount, errors.NewCommonEdgeXWrapper(err)
}
cont, err := utils.CheckCountRange(totalCount, offset, limit)
if !cont {
return []dtos.BaseReading{}, totalCount, err
}

readingModels, err := dbClient.ReadingsByDeviceName(offset, limit, name)
if err != nil {
return readings, totalCount, errors.NewCommonEdgeXWrapper(err)
}
return readings, totalCount, nil
readings, err = convertReadingModelsToDTOs(readingModels)
return readings, totalCount, err
}

// ReadingsByTimeRange query readings with offset, limit and time range
func ReadingsByTimeRange(start int64, end int64, offset int, limit int, dic *di.Container) (readings []dtos.BaseReading, totalCount uint32, err errors.EdgeX) {
dbClient := container.DBClientFrom(dic.Get)
readingModels, err := dbClient.ReadingsByTimeRange(start, end, offset, limit)
if err == nil {
readings, err = convertReadingModelsToDTOs(readingModels)
if err == nil {
totalCount, err = dbClient.ReadingCountByTimeRange(start, end)
}
totalCount, err = dbClient.ReadingCountByTimeRange(start, end)
if err != nil {
return readings, totalCount, errors.NewCommonEdgeXWrapper(err)
}
cont, err := utils.CheckCountRange(totalCount, offset, limit)
if !cont {
return []dtos.BaseReading{}, totalCount, err
}

readingModels, err := dbClient.ReadingsByTimeRange(start, end, offset, limit)
if err != nil {
return readings, totalCount, errors.NewCommonEdgeXWrapper(err)
}
return readings, totalCount, nil
readings, err = convertReadingModelsToDTOs(readingModels)
return readings, totalCount, err
}

func convertReadingModelsToDTOs(readingModels []models.Reading) (readings []dtos.BaseReading, err errors.EdgeX) {
Expand Down Expand Up @@ -136,18 +151,21 @@ func ReadingsByResourceNameAndTimeRange(resourceName string, start int64, end in
return readings, totalCount, errors.NewCommonEdgeX(errors.KindContractInvalid, "resourceName is empty", nil)
}
dbClient := container.DBClientFrom(dic.Get)
readingModels, err := dbClient.ReadingsByResourceNameAndTimeRange(resourceName, start, end, offset, limit)
if err == nil {
readings, err = convertReadingModelsToDTOs(readingModels)
if err == nil {
totalCount, err = dbClient.ReadingCountByResourceNameAndTimeRange(resourceName, start, end)
}
totalCount, err = dbClient.ReadingCountByResourceNameAndTimeRange(resourceName, start, end)
if err != nil {
return readings, totalCount, errors.NewCommonEdgeXWrapper(err)
}
cont, err := utils.CheckCountRange(totalCount, offset, limit)
if !cont {
return []dtos.BaseReading{}, totalCount, err
}

readingModels, err := dbClient.ReadingsByResourceNameAndTimeRange(resourceName, start, end, offset, limit)
if err != nil {
return readings, totalCount, errors.NewCommonEdgeXWrapper(err)
}
return readings, totalCount, nil
readings, err = convertReadingModelsToDTOs(readingModels)
return readings, totalCount, err
}

// ReadingsByDeviceNameAndResourceName query readings with offset, limit, device name and its associated resource name
Expand All @@ -160,18 +178,21 @@ func ReadingsByDeviceNameAndResourceName(deviceName string, resourceName string,
}

dbClient := container.DBClientFrom(dic.Get)
readingModels, err := dbClient.ReadingsByDeviceNameAndResourceName(deviceName, resourceName, offset, limit)
if err == nil {
readings, err = convertReadingModelsToDTOs(readingModels)
if err == nil {
totalCount, err = dbClient.ReadingCountByDeviceNameAndResourceName(deviceName, resourceName)
}
totalCount, err = dbClient.ReadingCountByDeviceNameAndResourceName(deviceName, resourceName)
if err != nil {
return readings, totalCount, errors.NewCommonEdgeXWrapper(err)
}
cont, err := utils.CheckCountRange(totalCount, offset, limit)
if !cont {
return []dtos.BaseReading{}, totalCount, err
}

readingModels, err := dbClient.ReadingsByDeviceNameAndResourceName(deviceName, resourceName, offset, limit)
if err != nil {
return readings, totalCount, errors.NewCommonEdgeXWrapper(err)
}
return readings, totalCount, nil
readings, err = convertReadingModelsToDTOs(readingModels)
return readings, totalCount, err
}

// ReadingsByDeviceNameAndResourceNameAndTimeRange query readings with offset, limit, device name, its associated resource name and specified time range
Expand All @@ -184,18 +205,21 @@ func ReadingsByDeviceNameAndResourceNameAndTimeRange(deviceName string, resource
}

dbClient := container.DBClientFrom(dic.Get)
readingModels, err := dbClient.ReadingsByDeviceNameAndResourceNameAndTimeRange(deviceName, resourceName, start, end, offset, limit)
if err == nil {
readings, err = convertReadingModelsToDTOs(readingModels)
if err == nil {
totalCount, err = dbClient.ReadingCountByDeviceNameAndResourceNameAndTimeRange(deviceName, resourceName, start, end)
}
totalCount, err = dbClient.ReadingCountByDeviceNameAndResourceNameAndTimeRange(deviceName, resourceName, start, end)
if err != nil {
return readings, totalCount, errors.NewCommonEdgeXWrapper(err)
}
cont, err := utils.CheckCountRange(totalCount, offset, limit)
if !cont {
return []dtos.BaseReading{}, totalCount, err
}

readingModels, err := dbClient.ReadingsByDeviceNameAndResourceNameAndTimeRange(deviceName, resourceName, start, end, offset, limit)
if err != nil {
return readings, totalCount, errors.NewCommonEdgeXWrapper(err)
}
return readings, totalCount, nil
readings, err = convertReadingModelsToDTOs(readingModels)
return readings, totalCount, err
}

// ReadingsByDeviceNameAndResourceNamesAndTimeRange query readings with offset, limit, device name, its associated resource name and specified time range
Expand All @@ -209,19 +233,21 @@ func ReadingsByDeviceNameAndResourceNamesAndTimeRange(deviceName string, resourc
if len(resourceNames) > 0 {
readingModels, totalCount, err = dbClient.ReadingsByDeviceNameAndResourceNamesAndTimeRange(deviceName, resourceNames, start, end, offset, limit)
} else {
readingModels, err = dbClient.ReadingsByDeviceNameAndTimeRange(deviceName, start, end, offset, limit)
if err == nil {
totalCount, err = dbClient.ReadingCountByDeviceNameAndTimeRange(deviceName, start, end)
totalCount, err = dbClient.ReadingCountByDeviceNameAndTimeRange(deviceName, start, end)
if err != nil {
return readings, totalCount, errors.NewCommonEdgeXWrapper(err)
}
if cont, err := utils.CheckCountRange(totalCount, offset, limit); !cont {
return []dtos.BaseReading{}, totalCount, err
}
readingModels, err = dbClient.ReadingsByDeviceNameAndTimeRange(deviceName, start, end, offset, limit)
}

if err == nil {
readings, err = convertReadingModelsToDTOs(readingModels)
}
if err != nil {
return readings, totalCount, errors.NewCommonEdgeXWrapper(err)
}
return readings, totalCount, nil
readings, err = convertReadingModelsToDTOs(readingModels)
return readings, totalCount, err
}

// AsyncPurgeReading purge readings and related events according to the retention capability.
Expand Down
8 changes: 4 additions & 4 deletions internal/core/data/controller/http/event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,7 @@ func TestAllEvents(t *testing.T) {
dbClientMock.On("EventTotalCount").Return(totalCount, nil)
dbClientMock.On("AllEvents", 0, 20).Return(events, nil)
dbClientMock.On("AllEvents", 1, 1).Return([]models.Event{events[1]}, nil)
dbClientMock.On("AllEvents", 4, 1).Return([]models.Event{}, errors.NewCommonEdgeX(errors.KindEntityDoesNotExist, "query objects bounds out of range.", nil))
dbClientMock.On("AllEvents", 4, 1).Return([]models.Event{}, errors.NewCommonEdgeX(errors.KindRangeNotSatisfiable, "query objects bounds out of range.", nil))
app := application.NewCoreDataApp(dic)
dic.Update(di.ServiceConstructorMap{
container.DBClientInterfaceName: func(get di.Get) interface{} {
Expand All @@ -643,7 +643,7 @@ func TestAllEvents(t *testing.T) {
}{
{"Valid - get events without offset and limit", "", "", false, 3, totalCount, http.StatusOK},
{"Valid - get events with offset and limit", "1", "1", false, 1, totalCount, http.StatusOK},
{"Invalid - offset out of range", "4", "1", true, 0, 0, http.StatusNotFound},
{"Invalid - offset out of range", "4", "1", true, 0, 0, http.StatusRequestedRangeNotSatisfiable},
}
for _, testCase := range tests {
t.Run(testCase.name, func(t *testing.T) {
Expand Down Expand Up @@ -710,7 +710,7 @@ func TestAllEventsByDeviceName(t *testing.T) {
dbClientMock.On("EventsByDeviceName", 0, 5, testDeviceA).Return([]models.Event{events[0], events[1]}, nil)
dbClientMock.On("EventsByDeviceName", 0, 5, testDeviceB).Return([]models.Event{events[2]}, nil)
dbClientMock.On("EventsByDeviceName", 1, 1, testDeviceA).Return([]models.Event{events[1]}, nil)
dbClientMock.On("EventsByDeviceName", 4, 1, testDeviceB).Return([]models.Event{}, errors.NewCommonEdgeX(errors.KindEntityDoesNotExist, "query objects bounds out of range.", nil))
dbClientMock.On("EventsByDeviceName", 4, 1, testDeviceB).Return([]models.Event{}, errors.NewCommonEdgeX(errors.KindRangeNotSatisfiable, "query objects bounds out of range.", nil))
app := application.NewCoreDataApp(dic)
dic.Update(di.ServiceConstructorMap{
container.DBClientInterfaceName: func(get di.Get) interface{} {
Expand All @@ -736,7 +736,7 @@ func TestAllEventsByDeviceName(t *testing.T) {
{"Valid - get events with deviceName - deviceA", "0", "5", testDeviceA, false, 2, totalCountDeviceA, http.StatusOK},
{"Valid - get events with deviceName - deviceB", "0", "5", testDeviceB, false, 1, totalCountDeviceB, http.StatusOK},
{"Valid - get events with offset and no labels", "1", "1", testDeviceA, false, 1, totalCountDeviceA, http.StatusOK},
{"Invalid - offset out of range", "4", "1", testDeviceB, true, 0, 0, http.StatusNotFound},
{"Invalid - offset out of range", "4", "1", testDeviceB, true, 0, 0, http.StatusRequestedRangeNotSatisfiable},
{"Invalid - get events without deviceName", "0", "10", "", true, 0, 0, http.StatusBadRequest},
}
for _, testCase := range tests {
Expand Down
Loading
Loading