Skip to content

Conversation

@khanhtc1202
Copy link
Member

@khanhtc1202 khanhtc1202 commented Mar 11, 2022

What this PR does / why we need it:

This PR adds filter logic which is used in the Find interface. Previously, I planned to make filter logic as part of collection logic and implement it for each model kind. Since the filter logic accepts Filter.Field (a string) as its input. If we make that filter logic as part of collections, we may have to use reflect to list up struct's fields name as string, it's complicated and not worth it. In this PR, instead of making filter logic as part of collections, it will be addressed in filedb layer, with a more generic interface map[string]interface{} as the input entity.

We still accept filter logic in collections (if exists) and only use this generic filter logic in case the collection does not implement the filterable interface.

Which issue(s) this PR fixes:

Fixes #

Does this PR introduce a user-facing change?:

NONE

@pipecd-bot
Copy link
Collaborator

COVERAGE

Code coverage for golang is 32.54%. This pull request increases coverage by 0.14%.

File Function Base Head Diff
pkg/app/piped/cloudprovider/ecs/task.go FindArtifactVersions -- 100.00% +100.00%
pkg/app/piped/planner/ecs/ecs.go determineVersions -- 0.00% +0.00%
pkg/datastore/filedb/filter.go compare -- 68.97% +68.97%
pkg/datastore/filedb/filter.go makeSliceOfInterfaces -- 85.71% +85.71%
pkg/datastore/filedb/filter.go filter 0.00% 0.00% +0.00%
pkg/app/piped/cloudprovider/ecs/task.go parseContainerImage 0.00% 100.00% +100.00%
pkg/app/piped/planner/ecs/ecs.go Planner.Plan 0.00% 0.00% +0.00%

@pipecd-bot
Copy link
Collaborator

COVERAGE

Code coverage for golang is 32.54%. This pull request increases coverage by 0.14%.

File Function Base Head Diff
pkg/app/piped/cloudprovider/ecs/task.go FindArtifactVersions -- 100.00% +100.00%
pkg/app/piped/planner/ecs/ecs.go determineVersions -- 0.00% +0.00%
pkg/datastore/filedb/filter.go compare -- 68.97% +68.97%
pkg/datastore/filedb/filter.go makeSliceOfInterfaces -- 85.71% +85.71%
pkg/app/piped/cloudprovider/ecs/task.go parseContainerImage 0.00% 100.00% +100.00%
pkg/app/piped/planner/ecs/ecs.go Planner.Plan 0.00% 0.00% +0.00%
pkg/datastore/filedb/filter.go filter 0.00% 0.00% +0.00%

@khanhtc1202 khanhtc1202 changed the title [WIP] Add filedb filter logic Add filedb filter logic Mar 14, 2022
@pipecd-bot
Copy link
Collaborator

COVERAGE

Code coverage for golang is 32.78%. This pull request increases coverage by 0.38%.

File Function Base Head Diff
pkg/app/piped/cloudprovider/ecs/task.go FindArtifactVersions -- 100.00% +100.00%
pkg/app/piped/planner/ecs/ecs.go determineVersions -- 0.00% +0.00%
pkg/datastore/datastore.go IsNumericOperator -- 100.00% +100.00%
pkg/datastore/filedb/filter.go compare -- 77.50% +77.50%
pkg/datastore/filedb/filter.go makeSliceOfInterfaces -- 100.00% +100.00%
pkg/datastore/filedb/filter.go convertCamelToSnake -- 100.00% +100.00%
pkg/app/piped/planner/ecs/ecs.go Planner.Plan 0.00% 0.00% +0.00%
pkg/datastore/filedb/filter.go filter 0.00% 75.00% +75.00%
pkg/app/piped/cloudprovider/ecs/task.go parseContainerImage 0.00% 100.00% +100.00%

@pipecd-bot
Copy link
Collaborator

COVERAGE

Code coverage for golang is 32.78%. This pull request increases coverage by 0.38%.

File Function Base Head Diff
pkg/app/piped/cloudprovider/ecs/task.go FindArtifactVersions -- 100.00% +100.00%
pkg/app/piped/planner/ecs/ecs.go determineVersions -- 0.00% +0.00%
pkg/datastore/datastore.go IsNumericOperator -- 100.00% +100.00%
pkg/datastore/filedb/filter.go compare -- 77.50% +77.50%
pkg/datastore/filedb/filter.go makeSliceOfInterfaces -- 100.00% +100.00%
pkg/datastore/filedb/filter.go convertCamelToSnake -- 100.00% +100.00%
pkg/app/piped/cloudprovider/ecs/task.go parseContainerImage 0.00% 100.00% +100.00%
pkg/app/piped/planner/ecs/ecs.go Planner.Plan 0.00% 0.00% +0.00%
pkg/datastore/filedb/filter.go filter 0.00% 75.00% +75.00%

Comment on lines +107 to +117
os, err := makeSliceOfInterfaces(operand)
if err != nil {
return false, fmt.Errorf("operand error: %w", err)
}

for _, o := range os {
if o == val {
return true, nil
}
}
return false, nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nits, it would be better to make this implementation a function and return directory.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's not that different since the logic to return is different between cases 🤔

@pipecd-bot
Copy link
Collaborator

COVERAGE

Code coverage for golang is 32.78%. This pull request increases coverage by 0.38%.

File Function Base Head Diff
pkg/app/piped/cloudprovider/ecs/task.go FindArtifactVersions -- 100.00% +100.00%
pkg/app/piped/planner/ecs/ecs.go determineVersions -- 0.00% +0.00%
pkg/datastore/datastore.go Operator.IsNumericOperator -- 100.00% +100.00%
pkg/datastore/filedb/filter.go compare -- 77.50% +77.50%
pkg/datastore/filedb/filter.go makeSliceOfInterfaces -- 100.00% +100.00%
pkg/datastore/filedb/filter.go convertCamelToSnake -- 100.00% +100.00%
pkg/app/piped/planner/ecs/ecs.go Planner.Plan 0.00% 0.00% +0.00%
pkg/datastore/filedb/filter.go filter 0.00% 72.73% +72.73%
pkg/app/piped/cloudprovider/ecs/task.go parseContainerImage 0.00% 100.00% +100.00%

@knanao
Copy link
Member

knanao commented Mar 14, 2022

Nice!
/lgtm

case int, int8, int16, int32, int64:
valNum = reflect.ValueOf(v).Int()
case uint, uint8, uint16, uint32:
valNum = reflect.ValueOf(v).Int()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
valNum = reflect.ValueOf(v).Int()
valNum = int64(reflect.ValueOf(v).Uint())

Sorry for the lack of explanation.
if the underlying type is uint, Int() will be panic(https://pkg.go.dev/reflect#Value.Int). So calling Uint() and then casting to int is better.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, thanks for explanation 👍

@pipecd-bot pipecd-bot removed the lgtm label Mar 14, 2022
@pipecd-bot
Copy link
Collaborator

COVERAGE

Code coverage for golang is 32.78%. This pull request increases coverage by 0.38%.

File Function Base Head Diff
pkg/app/piped/cloudprovider/ecs/task.go FindArtifactVersions -- 100.00% +100.00%
pkg/app/piped/planner/ecs/ecs.go determineVersions -- 0.00% +0.00%
pkg/datastore/datastore.go Operator.IsNumericOperator -- 100.00% +100.00%
pkg/datastore/filedb/filter.go compare -- 77.50% +77.50%
pkg/datastore/filedb/filter.go makeSliceOfInterfaces -- 100.00% +100.00%
pkg/datastore/filedb/filter.go convertCamelToSnake -- 100.00% +100.00%
pkg/app/piped/planner/ecs/ecs.go Planner.Plan 0.00% 0.00% +0.00%
pkg/datastore/filedb/filter.go filter 0.00% 72.73% +72.73%
pkg/app/piped/cloudprovider/ecs/task.go parseContainerImage 0.00% 100.00% +100.00%

@Hosshii
Copy link
Member

Hosshii commented Mar 14, 2022

It looks good to me 👍
/lgtm

Comment on lines +51 to +52
// TODO: Handle nested field name such as SyncState.Status.
return false, datastore.ErrUnsupported
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idea: Or to be simple, we can avoid using nested fields by double storing the SyncState_Status in the Application model.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, I planned to make logic like flatten nested json and do filter logic on the output map. But you're right, we may avoid complexity by unuse nested fields query. Will think about it and address with another PR 🙏

Match(e interface{}, filters []datastore.ListFilter) (bool, error)
}

func filter(col datastore.Collection, e interface{}, filters []datastore.ListFilter) (bool, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return fast when there was no filter to avoid unneeded marshaling.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch 💯

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed by fad8615 🙏

@pipecd-bot pipecd-bot removed the lgtm label Mar 15, 2022
@pipecd-bot
Copy link
Collaborator

TODO

The following ISSUES will be created once got merged. If you want me to skip creating the issue, you can use /todo skip command.

Details

1. Handle nested field name such as SyncState.Status.

// TODO: Handle nested field name such as SyncState.Status.
return false, datastore.ErrUnsupported
}

This was created by todo plugin since "TODO:" was found in fad8615 when #3389 was merged. cc: @khanhtc1202.

Comment on lines +38 to +46
// remarshal entity as map[string]interface{} struct.
raw, err := json.Marshal(e)
if err != nil {
return false, err
}
var omap map[string]interface{}
if err := json.Unmarshal(raw, &omap); err != nil {
return false, err
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any way to deal with the entity struct directly instead of remarshal like this?
I feel that we are having many marshal-unmarshal around this part.

Copy link
Member Author

@khanhtc1202 khanhtc1202 Mar 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To iterate throw struct and get field name as string, we only have using reflect or remarshal it to map[string]interface{} for now. I tried to do filter before first unmarshal (from object parts to object full data) but it does not work, since in some cases, the fields' values are stored duplicated between object parts, which make it's required to merge (unmarshal all object parts and build the whole object) once, then filter based on the data fulfilled object.

Besides, I read around the JSON marshal logic of the standard lib, and looks like it's called good/fast enough compare with others marshaling packages. So for now, I guess, I would like to make a try this method. If it's too costly this way, I will reconsider using reflect package or such. Wdyt?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally agree about that. Let's give it a try and see how it work. 👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks 🙌

@pipecd-bot
Copy link
Collaborator

COVERAGE

Code coverage for golang is 32.79%. This pull request increases coverage by 0.38%.

File Function Base Head Diff
pkg/app/piped/cloudprovider/ecs/task.go FindArtifactVersions -- 100.00% +100.00%
pkg/app/piped/planner/ecs/ecs.go determineVersions -- 0.00% +0.00%
pkg/datastore/datastore.go Operator.IsNumericOperator -- 100.00% +100.00%
pkg/datastore/filedb/filter.go compare -- 77.50% +77.50%
pkg/datastore/filedb/filter.go makeSliceOfInterfaces -- 100.00% +100.00%
pkg/datastore/filedb/filter.go convertCamelToSnake -- 100.00% +100.00%
pkg/app/piped/cloudprovider/ecs/task.go parseContainerImage 0.00% 100.00% +100.00%
pkg/app/piped/planner/ecs/ecs.go Planner.Plan 0.00% 0.00% +0.00%
pkg/datastore/filedb/filter.go filter 0.00% 70.83% +70.83%

@nghialv
Copy link
Member

nghialv commented Mar 15, 2022

Nice. Let's merge and see how it work.
Thank you.

/approve

@pipecd-bot
Copy link
Collaborator

APPROVE

This pull request is APPROVED by nghialv.

Approvers can cancel the approval by writing /approve cancel in a comment. Any additional commits also will change this pull request to be not-approved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants