-
-
Notifications
You must be signed in to change notification settings - Fork 144
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
get_pushrule::Response has incompatible PushRule type #53
Comments
A PR to implement this would be appreciated. EDIT: I implemented the above suggestion. Now the only thing left to do is define that enum in ruma-common and convert ruma-client-api to use it. |
Anyone working on this one? Let me try 🙂 |
So right now There's also And all of them refer to the same spec, correct?
Looking at the spec, it seems the presence of conditions and patterns depends on the rule's kind. So we could replace all the types with an enum like this: enum PushRuleKind {
Override { conditions },
Content { pattern },
Room,
Sender,
Underride { conditions },
} Does this make sense? One thing I'm not sure about is that the spec seemingly allows for any default rules to have conditions. Not sure if it's possible to have default rules other than those in the spec, but the spec does have a default content rule |
We definitely want to remove the more general definition with optional fields and use an enum of |
The solution here may just be to get rid of the need for an enum altogether by splitting the relevant endpoints into multiple one's? Actually we could also have sth. like that and still expose one endpoint publically I think, but explaining that here would be too much work right now (I'm on mobile). Will investigate in the coming days. |
My knowledge of the context is limited, but I think having Is it important that |
Possibly. I don't see why that would be 'dangerous' though.
I don't see why they would use different types. Not sure what you mean with the trait. |
Bad wording, sorry D: The worst possible outcome I can think of would be having to make a breaking change and refactor dependent code, without the spec itself making a breaking change. Say, if the That would be a bit easier if we had a separate type for each rule kind, plus So not at all critical, but a nice to have. Though this could be just me overengineering if this part of the spec doesn't change all that often... |
I think we'll have to do some trickery to avoid breaking changes in the future either way. Even if the spec just renames something, we'd want to follow that, and they surely won't consider that a breaking change but for us it would clearly be if we mirrored the change directly. I do feel like you're overengineering this. I am probably doing the same by thinking about splitting the GET endpoint into three, one for each kind of push rule (though that would prevent some invalid things such as returning a rule with a pattern for a kind of rule where that's illegal, and sidestep any deserialization issues... 😅). |
Haha, oh well. Is there a minimal improvement we can do now, without knowing what the best design is? We could, as @timokoesters suggested, replace Something like this? enum ruma_client_api::push::PushRule {
Override(ConditionalPushRule),
Content(PatternedPushRule),
Room(PushRule),
Sender(PushRule),
Underride(ConditionalPushRule),
} But I haven't looked into how hard this would be to serialize. Hmm, is serialization always this tricky? I wonder if it would make sense to have a separate set of simple, less strict types used only for serialization. |
I was thinking more of enum AnyPushRule {
Normal(PushRule),
Patterned(PatternedPushRule),
Conditional(ConditionalPushRule),
} Serialization should be trivial, it should just be The way this would probably be implemented is by having a private catch-all struct like the current |
@Kinrany Hey, it's been a while. Are you still planning to finish your work on this? |
Oh yeah. I should have probably said something, sorry. Couldn't find the time last weekend, but the next one should be fine. Still not sure about using just three enum variants. But the hardest part here is deserialization, and I have no idea what the implementation is going to look like before I try, so I have nothing to say about that for now :) Hmm, does it block anything, or are you just asking to make sure issues don't get stale? :0 |
I wrote this before:
And still think that this would probably be the easiest way to solve this.
It's not blocking anything, was just wondering whether you were stuck / not interested anymore or sth. like that. |
Yep, shouldn't be too hard, just comparatively hard. I just have to see for myself what exactly this is going to look like :D |
Right, so I'm not sure how exactly deserialization should work here, given that we must allow extra properties for backwards compatibility reasons. It's impossible to deserialize Hmm, can we get rid of the three variants completely and just make these two properties optional? Alternatively we must deserialize into different types depending on the kind of push rule we expect. |
Okay, it seems like you didn't understand the implementation strategy I proposed before. Let me phrase it in terms of some code: pub enum AnyPushRule {
// definition from your (now closed) PR
// ...
}
// notice: not public
#[derive(Deserialize)]
struct PushRuleDeHelper {
// definition with `Option`al properties, like the existing ruma_client_api::r0::push::PushRule
// ...
}
impl<'de> Deserialize<'de> for AnyPushRule {
fn deserialize<D>(deserializer: D) -> Result<AnyPushRule, D::Error>
where
D: Deserializer<'de>,
{
let rule = match PushRuleDeHelper::deserialize(deserializer)?;
match (rule.conditions.is_some(), rule.pattern.is_some()) {
(true, true) => Err(D::Error::custom(/* ... */)),
(true, false) => Ok(Self::Conditional(ConditionalPushRule { actions: rule.actions, /* ... */ })),
// ...
}
}
} @Kinrany Does that make sense? If it does, feel free to update your existing PR to it and re-open, that's probably less work than starting from scratch. |
The helper struct does make sense, yeah. My confusion is about the behavior we need here, not the implementation. AFAIK the spec does not guarantee the absence of So perhaps the correct thing to do is to have a struct with optional fields for deserialization (same as |
Well, you're right about that. Splitting the endpoint in three also messes with otherwise backwards-compatible changes. How about this then: Move the existing |
Yep, will do 🙂 |
ruma::api::client::r0::push::get_pushrule::Response takes a ruma::api::client::r0::push::PushRule, which is not compatible with any of the pushrule types defined in ruma::events::push_rules. IMO there should be an enum over all pushrule types and get_pushrule::Response returns that enum.
The text was updated successfully, but these errors were encountered: