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

Saving datamodel along with list of changed fields and previous values #899

Merged
merged 16 commits into from
Feb 14, 2023

Conversation

olemartinorg
Copy link
Contributor

@olemartinorg olemartinorg commented Feb 7, 2023

Description

Note: This requires backend support, which has not arrived yet. See the related issues for more details.

When saving, we currently pass along a best-effort indication of which component ID performed the operation, but this is not sufficient info for the backend at times, and we can't guarantee that we send in the correct component ID here (because saving to the backend isn't, and shouldn't be tied 1-1 to saving in a component).

The way this works is that is queries a 'feaureset' endpoint in the start of the application runtime (which currently returns a 404 on all backend versions). If that endpoint responds, with an object like {"multiPartSave": true}, subsequent save operations will be a multipart PUT request with two parts (dataModel and previousValues). The dataModel part is the same as what we saved before, while previousValues will be a key-value object of dot-notation keys, along with the previous values for all changed data model paths (or null if the value did not exist before). The former X-DataField and X-ComponentId headers are not passed along in a multipart request, and should be considered deprecated.

Related Issue(s)

Backend implementation (currently missing):

Verification

  • Manual testing
    • I have tested these changes manually
    • Creator of the original issue (or service owner) has been contacted for manual testing
    • No testing done/necessary
  • Automated tests
    • Unit test(s) have been added
    • Cypress E2E test(s) have been added
    • No automatic tests are needed here
    • I want someone to help me make some tests
  • User documentation @ altinn-studio-docs
    • Has been updated
    • No changes/updates needed (no user-facing or developer-facing features here, but the backend implementation should be documented)
  • Changes/additions to component properties
    • Changes are reflected in both src/layout/layout.d.ts and layout.schema.v1.json, and these are all backwards-compatible
    • No changes made
  • Support in Altinn Studio
    • Issue(s) created for support in Studio
    • This change/feature does not require any changes to Altinn Studio
  • Sprint board
    • The original issue (or this PR itself) has been added to the Team Apps project and to the current sprint board

Ole Martin Handeland added 11 commits January 30, 2023 13:45
…ports (this will let us feature-toggle and deliver functionality that depend on future backend features).
…art request, making it possible to test this functionality before backend support arrives.
…to save data before the previous one has ended. This could cause corruption or loss of data, and we can't guarantee the server-side responds to it correctly either. Using takeEvery instead of takeLatest, as takeLatest will abort a saga (effectively ignoring the 303 response back from the server).
…a state and update it when there are changes made to it
…y. It now makes sue to check that every request is fired, and that adding rows with data (and our nested group with preSelectedOptionsId) is saved correctly. This uncovered a lot of edge-cases!
@olemartinorg olemartinorg added the kind/product-feature Pull requests containing new features label Feb 7, 2023
@olemartinorg olemartinorg mentioned this pull request Feb 7, 2023
14 tasks
…it tests that submitting form data behaves differently in the cases of 3 different app types (stateful, stateless and anonymous stateless). This also happens to match exactly with our 3 major cypress test apps, so we know we have code coverage for these lines. The test also does a bad job at testing exactly what the difference between these 3 cases is expected to be (it just asserts that the code behaves the way it used to). While we have ample cypress test coverage for the new functionality, and no other cypress tests broke, the exact implementation changed - and I refuse to keep maintaining the implementation twice (in both the straight-forward implementation and the test that describes the implementation almost line-by-line).
…er (just that everything is consistent in the end). Also adding workaround for checkboxes order (as it does not properly support arrays just yet).
@olemartinorg olemartinorg marked this pull request as ready for review February 7, 2023 19:28
@ivarne
Copy link
Member

ivarne commented Feb 7, 2023

The former X-DataField and X-ComponentId headers are not passed along in a multipart request, and should be considered deprecated.

These headers is not used by the library, but directly by apps. Apps will likely just break silently in a way that is unlikely to be covered by tests and often makes schemas impossible to complete or cause issues with invalid data being submitted. Can you try to explain why these can't be kept for backwards compatibility?

edit
As we probably need a new IDataProcessing interface in order to leverage this new functionality, we might be able to let the /features endpoint report that it supports multipart only if the old interface isn't used in the app. That way the old IDataProcessing interface will get the X-DataField and X-ComponentId headers, while the new interface will not get it.

@olemartinorg
Copy link
Contributor Author

Yup. I don't know all the details, so I'm leaning on people who do. I also suggested in the linked issue for a backend implementation that this should be optional/opt-in: Altinn/app-lib-dotnet/issues/187

With that said, I can elaborate on the reason I believe those headers should be deprecated; I really want to go in a direction where saving data is more asynchronous than it is right now. Let's say you have a spotty internet connection - I would want saving to occur whenever it is possible (but requiring a stable connection for things like triggers, and actual final submits). Right now, we run save requests all the time, and if one of them fails, the entire app crashes. The assumption that "changing something in one component == one save request" is broken, IMO - and getting rid of it now can let us decouple this code in app-frontend in the future. I've written more about this in #506 and #555. Also here: #339 (comment)

@ivarne
Copy link
Member

ivarne commented Feb 7, 2023

I totally agree with your plans 👍😍. The current semantics is just as annoying to me too.

I just think we need to be very careful about breaking backwards compatibility, and preferably have some kind of safety. Maybe we can just search gitea for the names of the headers and open issues in the probably very small number of apps that uses the functionality?

@ivarne
Copy link
Member

ivarne commented Feb 7, 2023

Haha, and it seems like I read the issues in the wrong order. You explained the issue pretty well in in the app-lib-dotnet issue😳

@olemartinorg
Copy link
Contributor Author

I did a quick search in my folder of about ~341 apps deployed on prod and tt02, and only 5 of them seem to use the headers at the moment. Or, really just 3 (some were deployed in multiple environments and were counted multiple times because of that). So probably not a big problem. But yeah, I agree that should be wary of breaking backwards compatibility. Though, this won't come into effect unless you upgrade the nuget packages - and we have fairly well-established documentation for what you need to be aware of when upgrading those.

Ole Martin Handeland added 3 commits February 9, 2023 22:39
@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 9, 2023

SonarCloud Quality Gate failed.    Quality Gate failed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

4.3% 4.3% Coverage
0.0% 0.0% Duplication

Copy link
Member

@bjosttveit bjosttveit left a comment

Choose a reason for hiding this comment

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

Nice work 👨‍🔧

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/product-feature Pull requests containing new features
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Repeating groups: ProcessDataWrite mangler info om hva som har trigget eventet
3 participants