Skip to content

898 save app state version 4 #1048

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

Closed
wants to merge 5 commits into from

Conversation

chlebowa
Copy link
Contributor

@chlebowa chlebowa commented Jan 12, 2024

Extension of #1011

Five key objects are copied to the app session's userData: slices_global, filtered_data_list, mapping_matrix, snapshot_history, and state_history.
These objects can now be used and modified from any module.

There are multiple implementation within this one draft. Use the SHAs to checkout the one you want to see.

first implementation (f987c04)

Introduced a function set_intermodule_objects that sets these objects in the scope of a module:

  • checks if an object exists in session
  • if YES, assigns a copy in module environment (by reference)
  • if NO, creates the object
    This function is dirty as all hell, it depends on state and has side effects. Possibly is buggy.

set_intermodule_objects is called in filter manager, snapshot manager, and state manager so that the key objects can be created and used. Passing them as arguments is no longer necessary.
Note this is discouraged by shiny but perhaps it will allow us to do some things otherwise impossible.

The problem with the first implementation is that set_intermodule_objects contains all routines for setting the key objects and thus the default value of the key objects is separated from the module that uses it. It would be better if they (the routine and the module) can be kept in one file. Therefore, a need arises for a way to send such routines to a place where they can be accessed by all modules.

second implementation (3f79bb2)

Introduced a dedicated setter function for every key object (five in total). These setter functions work much like set_intermodule_objects in the first implementation. They are defined in the same file as the modules in which the key object is created, along with all necessary utility functions for better maintainability.

Introduced R6 class GlobalSetter as a hub for the setter functions.
The GlobalSetter class has two methods:

  • $add_setter: register function that sets global object
  • $set_global: call setter function to set global object
    A singleton GlobalSetter, GS is created in the package namespace (assignment is made in zzz.R). From there it be accessed by all modules.
    Every module can register a setter function for the key objects that it creates in GS. Every module can use GS to call a setter function.

ISSUES

  • update*Input is still a problem.
  • application opened from bookmark still lacks the most recent bookmark (itself)

@chlebowa chlebowa added the core label Jan 12, 2024
@chlebowa chlebowa requested a review from gogonzo January 12, 2024 18:02
@chlebowa chlebowa linked an issue Jan 12, 2024 that may be closed by this pull request
@gogonzo gogonzo self-assigned this Mar 4, 2024
Copy link
Contributor

@gogonzo gogonzo left a comment

Choose a reason for hiding this comment

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

This class unnecessary complicated the whole process of setting userData$. userData is a singleton itself (on the session level) and doesn't need extra class to handle the process.
GlobalSetter doesn't make it more robust as setter_ functions are vulnerable. See the comment insetter_mapping_matrix.

I suggest to remove GlobalSetter and fix setter_xyz to use formal arguments instead of dynGet. Apart from this, utilization of userData is reasonable. Alternatively I can imagine R6 TealSingleton class to control mapping/snapshot/states and whatever exist i a future. However, I would keep it simple now to at least have a POC of bookmarking.

Comment on lines +320 to +321
filtered_data_list <- dynGet("filtered_data_list")
slices_global <- dynGet("slices_global")
Copy link
Contributor

Choose a reason for hiding this comment

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

Seemingly independent function requires always to be called in the environment where filtered_data_list and slices_global exists (or will exist in the moment of a evaluation). This is not just unsafe but also too complicated.

Copy link
Contributor Author

@chlebowa chlebowa Mar 4, 2024

Choose a reason for hiding this comment

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

Seemingly independent function

Where did you get that idea? 😆
All of this is extremely impure but If we are to share objects between modules, there is no way to do it in a pure way.

Comment on lines +323 to +325
} else {
sesh$userData$mapping_matrix
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Existence of GlobalSetter complicates this as well. Optimally function setter_mapping_matrix should be called once and it shouldn't check whether values are set or not.

Suggested change
} else {
sesh$userData$mapping_matrix
}

@gogonzo gogonzo closed this Mar 28, 2024
@gogonzo gogonzo deleted the 898_save_app_state4@main branch March 28, 2024 15:37
@github-actions github-actions bot locked and limited conversation to collaborators Mar 28, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Research] Ability to save and restore the state of teal app
2 participants