Server Version Toggling #145
-
This is a placeholder for specification of the version toggling feature Proposal:
<ServerVersionSwitch>
<ServerVersionCase version=">=2.34">
<ModernComponent />
</ServerVersionCase>
<ServerVersionCase > {/* fallback for older versions */}
<LegacyComponent />
</ServerVersionCase>
</ServerVersionSwitch> The modern and legacy components could also be |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 1 reply
-
I was thinking of the api toggling or feature toggling I dont know what is the best name for it yet. After talking with @HendrikThePendric, reading though others apps that currently are “togglers” and simply thinking of how this would work on a bigger scale I feel is a good idea over all and as it has been mentioned it will definitely decrease our effort in maintaining the 4 different versions and also help us release in a more lean fashion. I also am seeing how this would work with an API that is being extended. In other words I can imagine how this would work when from v1 of the API we jump to the v2 where a feature such as “Search” functionality is being enabled. The place I am having hard time to imagine is on when the api has breaking changes sort to say. Such as renaming of an object key value or similar. I would like to introduce a concrete example where you might help me understand our strategies better or simply fire off a discussion. The Birthday Examplev1Lets say we having
The frontend application consumes the response and displays the first name and last name on the UI using the v2Now in the v2 of the API we starting support a new “feature”. The feature is that the
Perhaps in the In the frontend we would say something like this. Pseudocode alert. 🚨
v3Finally we are having a v3 of the API.
Now we are having a more complex problem to solve by having the same API endpoint returning different keys of objects between v2 and v3 versions. How would we solve this kind of situation gracefully? [1] What I mean by service is a function that only fetches and returns a promise. Something between these lines.
Perhaps very simplistically put but I hope one can get the idea. Maybe to answer myself one idea that comes into my head is this concept of backend for frontend (BFF) that I have been hearing some time ago. Several conference talks about it. Specifically one by some Netflix people that I could dig up is this one. But I am more interested in hearing other people's thoughts than on my own. |
Beta Was this translation helpful? Give feedback.
-
Some great ideas above 🎉 . I'll first add a few points that relate to those and then also add some considerations/ideas of my own.. Toggling using Components VS helper functionsI really like the idea of using components for doing this. For me the biggest advantages would be a) semantics, and b) the ability to lazy load these and reduce bundle size. On the other hand, I feel like having some helper functions in place would make things a bit more flexible since you could use these not only in JSX but elsewhere too. Possibly we could make these components very simple and extract most of the logic in some hooks, which we could then also expose. Probably using components + hooks will provide enough flexibility. The only thing is that quite a lot of apps I know have some dedicated js module that abstracts API calls into functions, and then these functions are called from redux action-thunks. Since hooks are only meant to be executed from a component or from another hook, this will probably produce some challenges. Probably nothing major though. Using version numbers VS functionality-names to toggleMy current approach for feature toggling has always been to have one dedicated file/folder for the "feature-queries", and I have always been exporting these "feature-queries" as functions with names relating to the functionality in question, and not the version number. See this example from the messaging-app: export function supportsAttachments(dhis2CoreVersion) {
return dhis2CoreVersion > 30
} My main motivation for this approach was long-term maintenance. Suppose I haven't touched an app for a while, and I return to it. If I encountered some logic that essentially said "if the server supports attachments, show the attachment components", I would feel pretty comfortable with that. However, if I saw "if the server is >=31, show the attachment components", I would probably end up looking into the reason for this logic being in place and wasting a bit of time. So, when I saw the example of switching based on the version number itself, I initially thought it was a bad idea. But thinking about this, and the additional moving parts we'd have to introduce, some more, I think we can probably provide some info about which versions introduce/break what at some other point. As such version number based switching is probably fine. Perhaps the components could even support both a Introducing a sanitisation layerThis could be a good solution for ironing out API inconsistencies across versions, but I also have some reservations about this:
Some of my own thoughts below.... Version toggle lifecycleI already brought this up in Slack, but think it'd be good to have it here too. We need to consider the following:
So in principle, each app could remain fairly constant in terms of complexity. Sometimes feature toggling code will needs to be introduced, but other times it can be removed. However, if we don't have a system in place to detect when we can remove old feature toggles, the risk of the app slowly growing into a complex monster is very real. Just to illustrate, I think the messaging-app example above is very on point: attachment-support was introduced in v32, and our lowest supported version currently is v32. So I actually should have removed this feature-toggle by now, but as you can see it's still the 😊 . So it's very clear we need some mechanism for reminding us to remove things. Some rough ideas about what I think we need in our appsI'm not sure about that sanitisation layer yet, so not taking that into account. Currently I am thinking that we probably need this:
const { hasFeature, hasBreakingChange } = useFeatureToggleContext()
if (!hasFeature('attachments')) {
return null
} else {
return <AttachmentButtons />
} Some additional note:
|
Beta Was this translation helpful? Give feedback.
-
Another point: The reason why we (mainly @varl and I) preferred un-versioned calls (at the time) was that it completely removes to need to update the api version as releases are produced. I can see why the maintainers of the webapi would expect apps to always do versioned calls to the api though. FYI: We also tried doing versioned calls to the minor version of the current dhis2-core instance. I believe we did that in the usage-analytics-app, we'd do one un-versioned GET to get the system-info resource to read the minor version number, and after that we'd use that in the |
Beta Was this translation helpful? Give feedback.
-
See https://jira.dhis2.org/browse/LIBS-245 for the epic which will implement this functionality.
|
Beta Was this translation helpful? Give feedback.
See https://jira.dhis2.org/browse/LIBS-245 for the epic which will implement this functionality.