Description
Client/server versioning
I think we need a way for the client (browser) and server to
recognize when they are running different code-versions.
@catmando describes the problem here in the context of mobile apps.
This ticket is meant to describe the same problem for the case of a plain browser/server app
because I believe the two cases (mobile vs browser/server) will need two slightly different
solutions.
Scenario
- Browser loads the app
- User clicks buttons, submits forms etc.
- Server is updated while client app instances are still open. For example a model-attribute is changed from String to integer
Problems
- Messages from the outdated clients will no longer be understood by the Server
- Messages from the modified server will no longer be understood by the client
⚠️ Messages from before the update may still be enqueued in either direction.
Proposed Solution
Gladly I think/hope the solution can be relatively simple:
- Add a version-attribute to all messages that are exchanged
- Before processing a message either on the server- or client-side, compare the version to the locally running code-version and if they don't match:
- Discard the message
- Invoke an "Outdated Client"-handler on the client
The handler
By default the handler could do something simple like:
def outdated_client_handler
if ENV == 'production'
alert 'Your client is outdated, will refresh'
browser.location.reload()
else
# Do nothing by default in development, as to
# not interfere with hot-reloading
end
end
It should be overridable by the developer, as most people
will want to customise the behaviour - adjust the message that is displayed, etc.
The version string
By default I would suggest to auto-generate this String at
compile-time as a hash over all files in app/*
.
This should result in the outdated_client-handler to fire
whenever anything is modified.
This behaviour needs to be overridable, too, as most people
likely don't want to force their users to reload for every change.
In a production context it will often be desirable to use a manually
maintained version number instead, or to limit the hashing to
a subset of the codebase (e.g. app/model/*
).
Final remarks
Thanks for reading! :)
The above is based on my (still limited) understanding of the
hyperstack-internals. I hope it can help towards a good solution
for the problem but there may be things I'm missing or better
alternative approaches. All comments & discussion welcome!