Skip to content

Commit

Permalink
Merge pull request #4975 from jinlinGuan/issue-4948
Browse files Browse the repository at this point in the history
fix: check offset, limit, totalCount before executing query
  • Loading branch information
cloudxxx8 authored Oct 21, 2024
2 parents 82350b2 + b7d163c commit 6ace714
Show file tree
Hide file tree
Showing 25 changed files with 848 additions and 206 deletions.
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

0 comments on commit 6ace714

Please sign in to comment.