-
Notifications
You must be signed in to change notification settings - Fork 10
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
Create MapSet[T] and ImmutableMapSet[T] types and change Entity.Parents to be a ImmutableMapSet[EntityUID] #40
Conversation
3740e46
to
88889b6
Compare
@@ -13,13 +13,6 @@ import ( | |||
// the Entity (it must be the same as the UID within the Entity itself.) | |||
type Entities map[EntityUID]*Entity | |||
|
|||
// An Entity defines the parents and attributes for an EntityUID. |
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 extracted this because I always have trouble remembering where the heck this struct is defined.
88889b6
to
68fb91c
Compare
@@ -1,68 +1,68 @@ | |||
package cedar | |||
package cedar_test |
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.
This is good hygiene. None of the tests in this file need to interact with any private bits in the package.
authorize_test.go
Outdated
UID: cuzco, | ||
Parents: []EntityUID{types.NewEntityUID("parent", "bob")}, | ||
Parents: cedar.NewEntityUIDSetFromSlice([]cedar.EntityUID{cedar.NewEntityUID("parent", "bob")}), |
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.
Here's an example of the breaking change.
I'll admit that it's a bit of a mouthful...
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.
Maybe receive a variadic, to cut out the []cedar.EntityUID{
? Though TBH, may not matter too much since it's going to be usually handled via JSON marshalling.
Maybe the words FromSlice
aren't really needed.
authorize_test.go
Outdated
UID: cuzco, | ||
Parents: []EntityUID{types.NewEntityUID("team", "osiris")}, | ||
Parents: cedar.NewEntityUIDSetFromSlice([]cedar.EntityUID{cedar.NewEntityUID("team", "osiris")}), |
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.
Another example.
authorize_test.go
Outdated
UID: dropTable, | ||
Parents: []EntityUID{types.NewEntityUID("scary", "stuff")}, | ||
Parents: cedar.NewEntityUIDSetFromSlice([]cedar.EntityUID{cedar.NewEntityUID("scary", "stuff")}), |
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.
A couple more examples here and on line 212.
authorize_test.go
Outdated
Entities: cedar.Entities{ | ||
cedar.NewEntityUID("Resource", "table"): &cedar.Entity{ | ||
UID: cedar.NewEntityUID("Resource", "table"), | ||
Parents: cedar.NewEntityUIDSetFromSlice([]cedar.EntityUID{cedar.NewEntityUID("Parent", "id")}), |
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.
The last example in this file
88d6d96
to
4cf812d
Compare
…nvenience functions around a map[T]struct{} Signed-off-by: Patrick Jakubowski <patrick.jakubowski@strongdm.com>
Signed-off-by: Patrick Jakubowski <patrick.jakubowski@strongdm.com>
…g]struct{} for annotation names Signed-off-by: Patrick Jakubowski <patrick.jakubowski@strongdm.com>
…} for record keys Signed-off-by: Patrick Jakubowski <patrick.jakubowski@strongdm.com>
…} for detecting unbound or unused variables Signed-off-by: Patrick Jakubowski <patrick.jakubowski@strongdm.com>
4cf812d
to
32380ba
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.
A lot of little nitpicks here, glad to discuss. Great improvement to a lot of stuff!
…ropriately, and return pointers to underscore risk of copy by value Signed-off-by: Patrick Jakubowski <patrick.jakubowski@strongdm.com>
Signed-off-by: Patrick Jakubowski <patrick.jakubowski@strongdm.com>
Signed-off-by: Patrick Jakubowski <patrick.jakubowski@strongdm.com>
Signed-off-by: Patrick Jakubowski <patrick.jakubowski@strongdm.com>
Signed-off-by: Patrick Jakubowski <patrick.jakubowski@strongdm.com>
Signed-off-by: Patrick Jakubowski <patrick.jakubowski@strongdm.com>
…oolean Intersects Signed-off-by: Patrick Jakubowski <patrick.jakubowski@strongdm.com>
Signed-off-by: Patrick Jakubowski <patrick.jakubowski@strongdm.com>
Signed-off-by: Patrick Jakubowski <patrick.jakubowski@strongdm.com>
3db1c9a
to
c0c3981
Compare
I think having a consistent JSON marshaller is important because having things change randomly is really annoying and can cause unnecessary updates happen when a diff is detected by something somewhere. In the case of JSON marshaling, I don't think performance is the key metric. So I think what you could do is get a Marshal of the bytes of all the values. Then sort those slices of bytes, then emit the "[a,b,c]" in that order.
I thought the Entity.Parents was going to be immutable? I agree that having |
} | ||
for _, k := range fe.Parents { | ||
fe.Parents.Iterate(func(k types.EntityUID) bool { |
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.
This is fine, but as a point of interest, I wonder if using a closure causes an allocation.
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.
Looks good, a few minor tweaks would be nice.
Signed-off-by: Patrick Jakubowski <patrick.jakubowski@strongdm.com>
Signed-off-by: Patrick Jakubowski <patrick.jakubowski@strongdm.com>
Signed-off-by: Patrick Jakubowski <patrick.jakubowski@strongdm.com>
038608e
to
e796ce2
Compare
Issue #, if available: None
Description of changes:
This PR adds a generic
MapSet[T]
andImmutableMapSet[T]
for all the places we want the semantics of a set but are annoyed by the inconvenience of using themap[T]struct{}
idiom in Go.In particular, the parents of an
Entity
have set semantics. With the current slice-based implementation, time complexity of the evaluation ofin
is linear. Utilizing aImmutableMapSet[EntityUID]
instead gives us constant time complexity on average, which is better. That being said, for small sets, that constant time is actually slightly greater than the time it takes to perform a linear search. I will consider addressing that in a future PR, but for now I'm happy to just have set semantics forEntity
parents.The
ImmutableMapSet[EntityUID]
is projected publicly through thetypes
package asEntityUIDSet
, with appropriate constructors also projected. For now, at least, I thought it prudent not to allow external users to import and useMapSet[T]
directly.I've also replaced any existing internal usages of
map[T]struct{}
in the module withMapSet[T]
orImmutableMapSet[T]
as appropriate.Important notes:
MapSet[T]
has no ordering guarantees. This applies toMarshalJSON
as well, meaning there's no predictable JSON encoding for a givenSet
. Instead of usingcomparable
, we could invent anItem
interface that embedscomparable
and also has aLess()
method, but then this set couldn't easily be used for native types likestring
, which feels like a pretty lame drawback.MapSet
is implemented ininternal
and therefore can't be directly imported by external users, theEntity.Parents
is now of typeMapSet[EntityUID]
and therefore changes to theMapSet[T]
interface should be considered breaking changes. I'm open to feedback on a better way to structure this. I considered puttingMapSet
intypes
, but thought that might be confusing...especially because I have some desire to extract anImmutableHashSet
out oftypes.Set
in the future.