Skip to content
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

fix: Improving the state serialization to URL #387

Merged
merged 1 commit into from
Apr 4, 2020

Conversation

dkozar
Copy link
Contributor

@dkozar dkozar commented Apr 3, 2020

Related issues and PRs

Description

Current de/serialization is messy and I feel we're not in control. Serialization methods are communicating with browser history and window.location. This makes those methods hard to test.

Additionally, the params property is being passed into serialization method, whereas in reality it wasn't really needed. I've removed it from the serialization methods altogether.

In order to separate the concerns, I've split the serialization process into 3 layers:

  1. communicating with browser history and window location
  2. repacking the state to DTO that will be serialized
  3. actual serialization of the DTO to string

I wrote unit tests for each layer. I believe this is puts us back in control.

Note: The functionality didn't change, so if you merge it there will be no visible change. But the serialization process will be easier to follow, and changes to each level will be trivial (unified type schema, JSURL)

Testing

Load the app in a browser, change parameters, reload the page and check if all the parameters are properly persisted.

@vercel
Copy link

vercel bot commented Apr 3, 2020

This pull request is being automatically deployed with ZEIT Now (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: https://zeit.co/covid19-scenarios/covid19-scenarios/l6r7w6z3j
✅ Preview: https://covid19-scenarios-git-fork-dkozar-fix-improved-serialization.covid19-scenarios.now.sh

@jsmith
Copy link
Contributor

jsmith commented Apr 3, 2020

I see that you added back the params parameter. I'm pretty this data is needed since the data in scenarioState is actually stale for about 1 seconds after changing a parameter. You can test this by changing a parameter and quickly pressing enter!

Comment on lines +64 to +77
// part of the application state to be persisted in the URL
export interface PersistedState {
current: string
data: ScenarioData
}

// format of the application state persisted in the URL
export interface PersistedStateDto {
current: string
population: PopulationData
epidemiological: EpidemiologicalData
simulation: SimulationData
containment: TimeSeries
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you are adding this I think it would be a good point to address the fact that current is irrelevant. What do you think we should do?

Copy link
Contributor Author

@dkozar dkozar Apr 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be irrelevant if the user customized some params. But in general, it isn't.

I think current should still be send over the wire (via URL). Because, if i want to select one of the existing, default scenarios (say "Croatia") and I want to send the link to someone, they should see "Croatia" selected in the dropdown.

Basically, we need to persist all the state needed to reconstruct the current screen. Without persisting current you can't do that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm it might not be irrelevant to the user who is sharing their parameters (ie. when they don't modify any params like you said) but the value is irrelevant upon deserialization. It's true that removing current will make it so we can't reconstruct an identical screen but doing so is not technically correct (the state is being initialized from the URL parameters, not the scenario defaults).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then we should really consider not to have the scenario as a dropdown.

We should really have a "Load existing scenario" button, which opens a popup window with a number of scenarios to load: #397

@dkozar
Copy link
Contributor Author

dkozar commented Apr 3, 2020

I see that you added back the params parameter. I'm pretty this data is needed since the data in scenarioState is actually stale for about 1 seconds after changing a parameter. You can test this by changing a parameter and quickly pressing enter!

Let's do something about it! 😃

I don't think there should be any stale data. Are there any performance concerns with serialization? I'm not sure (please confirm/deny), but running the algorithm is a performance bottleneck, and not the serialization? Could we mentally separate these two?

The object we're serializing is not huge. I've never seen performance problems with this object size.

I think along these lines:

  • we could/should serialize (and update the URL) upon each parameter change (whenever the user touches parameters)
  • we should call the actual algorithm only after the debounced interval

@@ -71,9 +71,10 @@ async function runSimulation(
const caseCounts: EmpiricalData = countryCaseCountData[params.population.cases] || []
const containment: TimeSeries = intervalsToTimeSeries(params.containment.mitigationIntervals)

// serializeScenarioToURL(scenarioState, params)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the line I mean! I don't think we can remove params since it contains the non-stale data being used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand, just commented above. To me it seems we're doing something wrong and should look at the problem from another angle.

@dkozar
Copy link
Contributor Author

dkozar commented Apr 3, 2020

Please note that this "constant serialization" to URL (upon each param change) is needed later. I'm about to address the "true history" issue: #346

So, all the changes need to immediately be pushed to browser history, and the user could use the browser Back button to get the previous set of values. But that doesn't mean that - if the user does this quickly - we'll call the algorithm each and every time and kill the browser. The call to the algorithm will stay debounced!

If we're not doing it this way (i.e. if we introduce some debouncing to writing to the URL) - this opens a can of worms, in terms that the final state will not be predictable and the user won't be sure what changes did persist and which hasn't. Going Back will not be deterministic.

By "constant serialization" I mean:

  • in auto mode: upon user touching any of the params
  • in normal mode: upon user clicking the Run button

@dkozar dkozar force-pushed the fix/improved-serialization branch from 7af25ee to fe2e999 Compare April 4, 2020 00:19
@ivan-aksamentov
Copy link
Member

@dkozar Thanks Danko. The restructuring is indeed useful.
Even if there are sync problems, I think we cannot make it even more broken that it is now. Merging.

@ivan-aksamentov ivan-aksamentov merged commit 7770306 into neherlab:master Apr 4, 2020
@dkozar dkozar deleted the fix/improved-serialization branch April 4, 2020 23:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants