-
Notifications
You must be signed in to change notification settings - Fork 40
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
Undo persistence #252
base: master
Are you sure you want to change the base?
Undo persistence #252
Conversation
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 really like parts of this PR. It simplifies the existing code relating to passing the undoing operator in several places, a shortcoming of the current codebase which suggests a need for a change like this. The undoing operator is useful information to persist, and besides display purposes, it could support future feature expansions such as rolling back undone punishments as well.
All that said, the breaking changes must be resolved. We have a firm commitment to API stability. The typical way to add backwards-compatible API is with method overloads and new options and builder objects. An "UndoOptions" for Punishment#undoPunishment would be suitable, and through it the undoing operator and reason could be set. In terms of relevant API enhancements, we should also consider expanding the selection API to optionally retrieve undoing information, using a left join on the undo table.
Moreover, the synchronization protocol cannot be broken, because the plugin must support incremental updates of multiple instances. Changing the synchronization protocol is possible but must be done in compatible phases.
Lastly though certainly not leastly, requiring undo reasons is untenable, both from a feature standpoint and backwards compatibility concerns. The undo reason must be made into an optional flag, and this should be reflected too in the API.
I agree, breaking API shouldn't be done, so I un-broke the API and made the old methods all valid by method overloading with defaults, althought I deprecated the old methods. I think this is an easy low maintenance solution. Where this might break is with the requirement for undo reasons not being required. They are not now, instead replaced with a default reason when calling the old (now deprecated) API. The unpunish command though simply uses the reason rules from the punish command, making a reason either required, substituting a default or using an empty reason. I think for command usage this is perfectly fine. |
Regarding the synchronization protocol: I didn't make any changes to it. From what I understand the synchronization protocol works like a push-to-pull message, sending other servers just the punishment id and type to retrieve the punishment from the database. |
The API design needs some work here. "Low maintenance" solutions are really high maintenance if not enough effort is put into the original API design. As I mentioned, I really like this PR, because it addresses a hole in the current feature set and opens up a lot of possibilities. However, that doesn't mean we can simply slap on undo information to the API. That the undoing operator and reason are optional should be reflected in the API. The old methods do not need to be deprecated. Additionally, API users should be able to supply an undoing operator but not an undo reason. This will need to be reflected in the database schema too. I also think that using the console operator is not an appropriate default. Users will have legacy punishments without undo information, and therefore we will need to accomodate a concept of an unknown undoing operator in the API. The relational design you have constructed is well architectured and lets us add undo information where it is available. There's no need to coax existing API usage, however, into supplying the console operator as a filler undo operator. What I recommend for this PR's API design is to modify Here's an example of what I mean: public interface RevocationOrder {
// Modifies this revocation order and returns itself
// Clears the reason if one is set
RevocationOrder operator(Operator operator);
// Modifies this revocation order and returns itself
// Sets the operator and undo reason
RevocationOrder operatorAndReason(Operator operator, String reason);
// Clears the operator and undo reason
RevocationOrder clearOperatorAndReason();
// .. everything else
} As for public interface Punishment {
// Convenience method to keep the API approachable
default ReactionStage<Boolean> undoPunishment() {
return undo().undoPunishment();
}
UndoBuilder undo();
// Older methods deprecated
}
public interface UndoBuilder {
// Clears the reason if one is set
UndoBuilder operator(Operator operator);
// Sets the operator and undo reason
UndoBuilder operatorAndReason(Operator operator, String reason);
// Clears the operator and undo reason
UndoBuilder clearOperatorAndReason();
UndoBuilder enforcementOptions(EnforcementOptions enforcementOptions);
ReactionStage<Boolean> undoPunishment();
// Fetches an updated punishment object that includes undo information
// Can be implemented by using undoPunishment() then constructing an updated punishment object
ReactionStage<Punishment> undoAndGetPunishment();
}
We can't copy the logic from the punish commands because it would be a breaking change. Users will expect the old command behavior and may have automated systems in place that execute commands. Requiring undo reasons contradicts our versioning policy: https://docs.libertybans.org/#/Versioning-and-Support-Policies?id=server-side-usage |
I currently have little time to work on this, so if anybody else is interested in taking over this feature, please feel free to do so. |
I'll begin working on this again. |
Note: I made this PR mostly out of personal need and I likely don't have the time to add missing tests, fix code smells or make breaking API changes backwards compatible. I still wanted to open the PR in case someone else is interested in taking this and making it palatable for a public release.
This PR adds undo persistence.
When a punishment is undone, the following information is stored:
A new table is added called
libertybans_undone
which stores relevant undo information, the simple history schema also includes undo information.There are currently breaking API changes, I made a reason and an undo operator a requirement for undoing a punishment.
I'm not sure if it works completely, but I have not noticed any problems from unit/integration tests or ingame testing. I will still do more testing and fix broken functionality.