emilhe / dash-extensions

The dash-extensions package is a collection of utility functions, syntax extensions, and Dash components that aim to improve the Dash development experience
https://www.dash-extensions.com/
MIT License
409 stars 57 forks source link

Delete of Serverside objects when key is regenerated #323

Open Lxstr opened 2 months ago

Lxstr commented 2 months ago

As described in the docs using Serverside() creates a new key for the data each time a callback is run. However, the old piece of data remains in the redis storage until it expires or redis fills up and starts emptying itself. The issue is that redis may start emptying data of other users whos data has not expired. You also can't tell if you genuinly do need more redis storage to accomodate a greater number of users.

The whole issue would be solved if it's possible to automatically delete the old key/value when a new key is generated.

I would be happy to PR but I can't find where this code is implemented.

matt-sd-watson commented 2 months ago

This looks like it's similar to my previous issue: https://github.com/emilhe/dash-extensions/issues/302

In short, you should be able to overwrite the previous key if you keep the key string consistent for all of the callbacks where the same Serverside object is returned, like this:

return Serverside(data, key="constant_key")

Keeping the string key constant will produce one constant pickle object that is overwritten any time a callback updates the particular Serverside object.

Lxstr commented 2 months ago

Hi Matt thanks for the idea, is that still going to use a unique key for different sessions/users? Or will it literally use that key for every user

matt-sd-watson commented 2 months ago

I wouldn't think about users so much as callback invocations. So for example, you could set up your application so that multiple users will access one instance of your application, so there will be multiple user requests for a session instance. In that case, you should not use the constant key and let the keys uniquely generate each time the callback is invoked, because otherwise the application will overwrite another user's data with the newest callback invocation, potentially from a different user. I don't see a way around this if multiple users will share an instance/session.

Conversely, you could somehow enforce that each user gets a separate instance (i.e. each user gets a new containerized application), and in that case you can use the constant keys because you know that only one user is invoking the callbacks for a particular session. In my application, we have the CLI option to toggle this on or off.

marcstern14 commented 2 months ago

I am dealing with trying to understand the implications of fixed keys as well (#314). In my application, I have been using fixed keys mostly successfully, which makes me think that each user is invoking a unique session. However, because I am using Serverside() I often experience "missing data" if I open up the website the next day, and need to refresh to get the data to load. Any thoughts on this behavior @matt-sd-watson? Is there a clever way to implement FileSystemStorage cleanup without running a separate job since my application lives inside a docker container?

Lxstr commented 3 weeks ago

So a proposed solution for different users (also more secure than local host maybe for static keys?):

Setting the storage with Serverside(data, session={lambda: session.sid}, key="data-store") on a component with id="data-store" would set a cache key of "{session.id}-data-store"

However, I would not want dash-extensions to store the key in local storage as it now has the session id:

Key                   Value
data-store  "SERVERSIDE_{"backend_uid": "RedisBackend", "key": "87sdghfoib3k083ip"}"

Should be:

Key                   Value
data-store  "SERVERSIDE_{"backend_uid": "RedisBackend"}"

Retrieving would be some kind of decorator that calls the session id function and appends it to get the key it needs to retrieve from.