-
Notifications
You must be signed in to change notification settings - Fork 186
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
Evaluation with FlagTagsOperator to match any or all tags #408
Evaluation with FlagTagsOperator to match any or all tags #408
Conversation
@@ -1311,6 +1311,14 @@ definitions: | |||
x-omitempty: true | |||
items: | |||
type: string | |||
flagTagsOperator: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw, this doc is generated, you can move the change to https://github.com/checkr/flagr/blob/master/swagger/index.yaml#L518, and then run make gen
to get the same result
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I wasn't sure how this work
pkg/handler/eval.go
Outdated
|
||
fs := cache.GetByTags(evalContext.FlagTags) | ||
fs := cache.GetByTags(evalContext.FlagTags, operator) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for readability, I think you can just pass the evalContext.FlagTagsOperator
as *string
to cache.GetByTags
, and then check if if operator == nil || *operator == models.EvaluationBatchRequestFlagTagsOperatorANY
there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks reads better
pkg/handler/eval_cache.go
Outdated
if !ok { | ||
// clear as no flags | ||
results = map[uint]*entity.Flag{} | ||
continue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the tag is not there, I think should we just return nil
here given the ALL
operator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're totally right
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But is it correct to return nil or should we return an empty list?
pkg/handler/eval_cache.go
Outdated
missingFIDs := []uint{} | ||
for fID := range results { | ||
if fSet[fID] == nil { | ||
missingFIDs = append(missingFIDs, fID) | ||
} | ||
} | ||
for _, fID := range missingFIDs { | ||
delete(results, fID) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about one pass of the keys in results, and just delete the keys not the current fSet?
for fID := range results {
if _, ok := fSet[fID]; !ok {
delete(results, fID)
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, I wasn't sure if in Go is possible to modify a slice while iterating it. Changing it for sure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
related topic https://stackoverflow.com/questions/23229975/is-it-safe-to-remove-selected-keys-from-map-within-a-range-loop, I also learned that delete
marks the keys as deleted, thus safe to keep iterating.
af774ce
to
756a071
Compare
I've applied all your feedback as that makes a lot of sense and simplify the solution. Thanks for the review |
Codecov Report
@@ Coverage Diff @@
## master #408 +/- ##
==========================================
- Coverage 82.99% 81.90% -1.09%
==========================================
Files 27 27
Lines 1752 1603 -149
==========================================
- Hits 1454 1313 -141
+ Misses 214 211 -3
+ Partials 84 79 -5
Continue to review full report at Codecov.
|
pkg/handler/eval_cache.go
Outdated
results[fID] = f | ||
} | ||
} else { | ||
if len(results) > 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one more thing to optimize is that you can return early when len(results) == 0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, after each delete loop we check if there is still any match to continue or return early.
756a071
to
8377d3a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉
👍 I'll try to remember thanks for the pointer
…On Tue, Oct 13, 2020, 5:51 PM Zhuojie Zhou ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In pkg/handler/eval_cache.go
<#408 (comment)>:
> + missingFIDs := []uint{}
+ for fID := range results {
+ if fSet[fID] == nil {
+ missingFIDs = append(missingFIDs, fID)
+ }
+ }
+ for _, fID := range missingFIDs {
+ delete(results, fID)
+ }
related topic
https://stackoverflow.com/questions/23229975/is-it-safe-to-remove-selected-keys-from-map-within-a-range-loop,
I also learned that delete marks the keys as deleted, thus safe to keep
iterating.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#408 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAACVLRWCEQSDP3XQJUMK53SKRZRFANCNFSM4SJYHM5Q>
.
|
Finding flags to be evaluated using tags allow to pass ANY/ALL tag matching as operator
Description
Just support a new enum value
ANY
orALL
to determine which flags matches the tags the default isANY
.ALL
just filter out results applying tags one after the other.Motivation and Context
The main idea of the change is to allow to pass
flagsTagsOperator
on batch evaluation requests so we can handle scenarios where each tag used to describe the flags are independent so we could want to match flags which contains all the tags passed. Currently, tags are considered as any tag in the flags make the match.We have tags determining the ownership of the flags, and some teams group flags inside other tags and we have some generic rules to naming it.
owner:team-name
batch:batch-name
So as could be collisions on the names between teams we think that adding a match all operator for tags solve this easily to just evaluate on those flags matching all the tags provided. This is opt in as the default behaviour is the same as before.
How Has This Been Tested?
I've added a couple of tests in the codebase to describe the new behaviour
Types of changes
Checklist: