-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Support serializable toolbar #1432
Support serializable toolbar #1432
Conversation
Codecov Report
@@ Coverage Diff @@
## main #1432 +/- ##
==========================================
- Coverage 85.73% 84.93% -0.81%
==========================================
Files 35 38 +3
Lines 1893 2004 +111
Branches 273 280 +7
==========================================
+ Hits 1623 1702 +79
- Misses 190 219 +29
- Partials 80 83 +3
Continue to review full report at Codecov.
|
In order to support the toolbar persisting stats, we need to move away from calling record_stats with non-primitives.
Removes storing the entire toolbar in the Store.
220373f
to
3fb2745
Compare
@tapaswenipathak tagging you here. Feel free to create a new PR or continue working off of this one. |
|
||
Provided to support future store mechanisms overriding a panel's content. | ||
""" | ||
return stats |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are these two methods complete?
deserialize_stats
serialize_stats
|
||
def deserialize(data): | ||
return json.loads(data) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are these two methods complete?
serialize()
deserialize()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
|
||
@classmethod | ||
def delete(cls, store_id): | ||
raise NotImplementedError |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should these four be implemented?
ids()
exists()
set()
delete()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not here. BaseStore is the interface for the API. The subclasses of BaseStore will have different implementations.
except KeyError: | ||
data = None | ||
return {} if data is None else deserialize(data) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are these two method definitions complete?
save_panel()
panel()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
@@ -43,7 +43,7 @@ | |||
</td> | |||
<td class="djdt-actions"> | |||
<form method="get" action="{% url 'djdt:history_sidebar' %}"> | |||
{{ store_context.form }} | |||
{{ history.form }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
store_context
is functionally history
after this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this is likely due to the context for the template changing.
@classmethod | ||
def fetch(cls, store_id): | ||
return cls._store.get(store_id) | ||
get_store().set(self.store_id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now i would:
return import_string(dt_settings.get_config()["TOOLBAR_STORE_CLASS"])
are these edits/changes functional and complete?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function store
here is more the verb case of "store". What's happening is that we want to store this version of the toolbar into the storage mechanism. The naming could be improved.
This is going to be replaced by the work associated with https://github.com/orgs/jazzband/projects/9/ @matthiask can you review those high level tasks and let me know what context I'm missing? When these parts are picked up, they should be converted to issues. Though perhaps I should do that now? |
@tim-schilling Thanks for starting this! I think we should check if we can use the cache framework instead of writing our own store classes; we should document that you're supposed to use a cache which supports cross-process caching and maybe warn if users use e.g. the local memory or dummy cache backend. I'm sure that the point could be made that this data doesn't belong in a cache but it would mean much less work for us and many many options immediately available for our users. I also think Django Channels is nice to have, not essential -- Django itself comes with async views, middleware and ORM methods. I have used Channels in the past with success and I like it, but supporting Django's own async machinery is surely more important. Re. the serialization framework: Do you think it would be feasible to enforce usage of these methods so that we do not have to support two code paths in the future? I think it would be great if we also added a pending deprecation warning to using current-style panels which do not use serialization at all. (I haven't thought long and hard about these points so I'm not all that sure that we should do what I'm proposing.) |
@matthiask Good point. I'm not sure why I went into specific backends. In reality, it should have been MemoryStore, CacheStore and DatabaseStore. However, I'm happy to start with using the cache, then extending if folks want to.
Another good point. But let's reach for it still. Especially if we get help from GSoC.
Yes, I think we'll drop the double code paths in the future. I don't have a timeline for you, but if you feel we should define one, I'll say 1 year from release we'll drop the deprecated path. |
I totally agree.
I don't think we need a timeline for this, but we should be intentional about it, and communicate clearly that we don't expect to keep both paths indefinitely. Thanks! |
I'm closing this as this approach is largely being dropped. It can still be referred to for inspiration, but it won't be merged in. |
In order to support Channels' non-django request possibilities, we need to start making the toolbar more flexible.In order to support Django Channels out of the box we need to support multiple processes running. This implies serializing the toolbar's data into some type of backend (database, memory, redis, etc). Currently the toolbar stores everything in memory as non-primitives.
My assumption is that we need to serialize the panel's template context into primitives so that it can be stored in any medium between requests and then rendered at some future time (or even stored elsewhere). I could be wrong here, so feel free to push back. I suspect this is going to change the toolbar's internals dramatically.
This should not be merged as it's not complete, but I wanted to get it out there for feedback and to solicit for ideas/alternative options. Currently this PR does the following:
debug_toolbar.store.MemoryStore
)MemoryStore
, but I'm doing it to prove that it does work).Future work:
LocMemCacheStore
DBCacheStore
This relates to #1430 and I hope we can structure it in a way such that it also works for async views in Channels and #1413.