-
Notifications
You must be signed in to change notification settings - Fork 5
feat(assets): Add Support for Electrical Component Connections #50
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
base: v0.x.x
Are you sure you want to change the base?
feat(assets): Add Support for Electrical Component Connections #50
Conversation
4f8d31b to
97f65fc
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.
LGTM, but I would improve the API as proposed. With this change not only it can accept lists of IDs, it can also accept tuples, sets, or any iterable, like dict.values() or dict.keys().
0b87c3a to
950965d
Compare
|
|
||
| return [ | ||
| component_connection_from_proto(connection) | ||
| for connection in response.connections |
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.
IIUC this would also collect Nones, is this intended?
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.
True, good catch. I have this in the microgrid API:
return (
conn
for conn in map(
component_connection_from_proto,
response.electrical_component_connections,
)
if conn is not None
)An a more functional alternative 😄
return list(
map(
component_connection_from_proto,
filter(bool, response.electrical_component_connections),
)
)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, good catch.
| ) | ||
| else: | ||
| minor_issues.append( | ||
| "missing operational lifetime, considering it always operational", |
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.
Is this an issue or a valid case?
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.
In the microgrid API is valid, and for now it is always returned without a lifetime, but maybe this needs to change in the future, not sure.
We should probably document in the protobuf files what to expect though. Some of these issues I added them only to be notified if they happened or not because I couldn't find a strict definition.
Once we have a clear definition, we might want to remove them (for example, if it is a defined thing that a missing operational lifetime can happen and then the meaning is it is always operational, we don't need to be whining about it when we see it happen, it will be just noise.
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 already documented in the latest API version: https://github.com/frequenz-floss/frequenz-api-common/blob/300bcb4296d679faa3b2aec33e7ea3d461d90beb/proto/frequenz/api/common/v1alpha8/microgrid/lifetime.proto#L21-L30
Therefore, the phrase "missing operational lifetime, considering it always operational" is technically correct. I do not think it should be classified as an issue though.
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.
is there a reason it is this concise? It's nice to reduce cognitive load of messages, but this is verging on being easily misunderstood.
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.
Therefore, the phrase "missing operational lifetime, considering it always operational" is technically correct. I do not think it should be classified as an issue though.
Yeah, it is is expected behavior it is not an issue and we should remove it, as it will just spam the logs. I will remove it from the microgrid API client too.
is there a reason it is this concise? It's nice to reduce cognitive load of messages, but this is verging on being easily misunderstood.
What are you talking about exactly, what's concise?
| except ValueError as exc: | ||
| major_issues.append( | ||
| f"invalid operational lifetime ({exc}), considering it as missing " | ||
| "(i.e. always operational)", |
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.
Do we want to consider it as operational? If so, I don't see a way how we can detect these cases programatically. Maybe we add a way to check how many major issues were found to understand how reliable the connections are.
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.
Do we want to consider it as operational?
Good question, this was done with the microgrid API in mind, where right now everything is operational all the time basically, but maybe it is not safe to assume it operational.
If so, I don't see a way how we can detect these cases programatically. Maybe we add a way to check how many major issues were found to understand how reliable the connections are.
The question for me is if there is anything we can do (and want to do) programatically. I think in general an error here is a misconfiguration, and the best we can do is tell the user (in this case an error should be logged) so they can fix it.
Then we probably need to try to recover as best as possible, so there is the question if we ignore the connection (consider it non-operational) or we add it (assume it is operational). Both cases will be wrong some times and right some other times, so I guess there is no good answer for this, but maybe ignoring it is more correct, as if one field is wrong, maybe other fields are wrong too.
Or back to your question, what else do you think it can be done by a client if the wrong connection would be passed to the user of the client? Do you envision clients applying some heuristics to try to do a better guess on how to treat a faulty connection?
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.
See here.
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 agree that it makes sense to define missing as always operational. What I am not sure about is whether an invalid lifetime should be accepted and treated as missing. Invalid indicates a user error to me.
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.
Or back to your question, what else do you think it can be done by a client if the wrong connection would be passed to the user of the client? Do you envision clients applying some heuristics to try to do a better guess on how to treat a faulty connection?
I guess my main point would be to have a way to validate whether the graph could be parsed without any issues or not, because atm we only have a warning message. It depends on the use-case if you prefer to have reliable data or better some data. Also you could try to recover it or have fallbacks in place if a problem was detected.
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 think the graph will be constructed from the UI, and there will be no way to construct it in an invalid way, so I guess this code is mostly about really weird situations, memory corruption or something like this, so I think as long as we log an error (I think major issues are logged as warnings now, we might want to reconsider that, or have a separate critical_issues that are logged as errors), it doesn't matter much how we deal with it.
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.
That said, probably if part of a message is broken it would make sense to ignore the whole message instead try to guess fix it.
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 think you removed the wrong "issue", this issue should still be checked and reported (I think it would probably be better to just skip the whole connection object, so return None, if the operational lifetime is invalid. If it is missing, then that's OK, so that issue should not be reported.
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 there is no supported way to construct invalid graphs and it's only weird cases, are these then valid at all? If not, why not just raise an exception in this case?
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 didn't understand the last comment. Maybe we could meet to quickly discuss this.
|
Hmm a bit meta but it I found it a bit cumbersome to read every time "This commit introduced/updates/.." it feels very redundant. Nothing against AI generated if that is the case, but maybe ask it to cut it down a bit? :) |
I send this, I also find the PR description too verbose, to the point that my brain unconsciously tries to skip it. For me something more succinct would be more useful, like:
I think the rest of the details can be read from the PR itself. Maybe you can tweak the instructions to generate PRs/commit messages, which makes me think that maybe it is time to start providing custom instructions, as I guess we can all benefit from having good instructions to produce useful PR/commit messages. |
9e75c3e to
b5e92be
Compare
8c13c17 to
9c89de1
Compare
src/frequenz/client/assets/electrical_component/_connection_proto.py
Outdated
Show resolved
Hide resolved
| except ValueError as exc: | ||
| major_issues.append( | ||
| f"invalid operational lifetime ({exc}), considering it as missing " | ||
| "(i.e. always operational)", |
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 think you removed the wrong "issue", this issue should still be checked and reported (I think it would probably be better to just skip the whole connection object, so return None, if the operational lifetime is invalid. If it is missing, then that's OK, so that issue should not be reported.
daa19b6 to
0045825
Compare
| operational_lifetime: Lifetime | None = None | ||
| """The operational lifetime of the connection.""" |
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 should not accept None, otherwise we need to do special casing here, is better to keep it as it was before, that a Lifetime() is just always operational. Also in user code, if users need to access operational lifetime directly they will need to deal with None as a possibility now.
| operational_lifetime: Lifetime | None = None | |
| """The operational lifetime of the connection.""" | |
| operational_lifetime: Lifetime | |
| """The operational lifetime of the connection.""" |
| if self.operational_lifetime is None: | ||
| return True |
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 self.operational_lifetime is None: | |
| return True |
| """Get the operational lifetime from a protobuf message.""" | ||
| if message.HasField("operational_lifetime"): | ||
| return lifetime_from_proto(message.operational_lifetime) | ||
| return None |
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.
| return None | |
| return Lifetime() |
| """Create a `ComponentConnection` from a protobuf message collecting issues. | ||
| This function is useful when you want to collect issues during the parsing | ||
| of multiple connections, rather than logging them immediately. |
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.
What is actually the motivation for collecting those messages instead of logging them immediately? I wonder why we need this additional complexity.
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.
Flexibility. Doing this actually makes supporting your use case pretty trivial. The client could just return the issues instead of logging them. This code is supposed to go to client-common.
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 this is the idea, then these issues are probably better tracked via enums instead of strings. If you prefer to not do it in this PR then it should come in the next one. Because in the current form we cannot use this endpoint in our trading app.
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.
We can add it in the next one because this implementation should be moved to client-common.
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.
Sounds good!
0045825 to
06dd9d7
Compare
Bumps [actions/labeler](https://github.com/actions/labeler) from 5.0.0 to 6.0.1. - [Release notes](https://github.com/actions/labeler/releases) - [Commits](actions/labeler@8558fd7...634933e) --- updated-dependencies: - dependency-name: actions/labeler dependency-version: 6.0.1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <[email protected]> Signed-off-by: eduardiazf <[email protected]>
Bumps the compatible group with 2 updates: [frequenz-floss/gh-action-nox](https://github.com/frequenz-floss/gh-action-nox) and [frequenz-floss/gh-action-setup-python-with-deps](https://github.com/frequenz-floss/gh-action-setup-python-with-deps). Updates `frequenz-floss/gh-action-nox` from 1.0.0 to 1.0.1 - [Release notes](https://github.com/frequenz-floss/gh-action-nox/releases) - [Commits](frequenz-floss/gh-action-nox@v1.0.0...v1.0.1) Updates `frequenz-floss/gh-action-setup-python-with-deps` from 1.0.0 to 1.0.1 - [Release notes](https://github.com/frequenz-floss/gh-action-setup-python-with-deps/releases) - [Commits](frequenz-floss/gh-action-setup-python-with-deps@v1.0.0...v1.0.1) --- updated-dependencies: - dependency-name: frequenz-floss/gh-action-nox dependency-version: 1.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: compatible - dependency-name: frequenz-floss/gh-action-setup-python-with-deps dependency-version: 1.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: compatible ... Signed-off-by: dependabot[bot] <[email protected]> Signed-off-by: eduardiazf <[email protected]>
Add a new client method to retrieve microgrid electrical components connections. Signed-off-by: eduardiazf <[email protected]>
Adds tests for list_microgrid_electrical_component_connections, covering success, empty results, and error cases to improve reliability. Signed-off-by: eduardiazf <[email protected]>
Updates list_microgrid_electrical_component_connections to accept Iterable[int] for source/destination component IDs. Signed-off-by: eduardiazf <[email protected]>
…ctions To use map/filter for cleaner logic and to skip invalid connections. Signed-off-by: eduardiazf <[email protected]>
missing operational lifetime, considering it always operational Signed-off-by: eduardiazf <[email protected]>
06dd9d7 to
0fa7382
Compare
Summary
Add a new client method to retrieve microgrid electrical components connections. For this a new ComponentConnection class is introduced. The CLI is also extended to add a command to list component-connections, for example:
assets-cli component-connections 123 --source 5 --source 6 --destination 10Resources