-
Notifications
You must be signed in to change notification settings - Fork 251
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
Depreciated legacy tree map #963
Conversation
@@ -18,6 +20,7 @@ use crate::IntoStorageKey; | |||
/// - `above`/`below`: O(log(N)) | |||
/// - `range` of K elements: O(Klog(N)) | |||
/// | |||
#[deprecated(since = "4.1.0", note = "Use tree_map::TreeMap instead")] |
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.
Unfortunately, it's not that simple. Just swapping to use this type is a state-breaking change. At least the note should indicate this.
Also, the tree_map
module is not exposed, so you might want to change this to say near_sdk::collections::TreeMap
instead.
Optionally, this PR could introduce some migration of the old collection to the new one as a method, for example something like LegacyTreeMap::to_tree_map(&self)
or something like this and then this comment can point to this to make the migration easy. This is less important, though, as I presume no one is really using this and if they absolutely want it, they can just ignore the deprecation warnings
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.
So many mistakes in one line!
An issue I'm having with this migration code is that it appears to be hitting the gas limit after successive runs. How should I go about resetting the gas limit after each run? The gas limit also seems very low, it seems to fall over with 100 elements, is that to be expected or am I doing something stupid? |
// We read this into the heap first so one can use the same prefix without getting into trouble | ||
let elements: Vec<(K, V)> = self.into_iter().collect(); | ||
let mut tm = super::TreeMap::new(prefix); | ||
for (k,v) in elements.iter() { |
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.
This all happens synchronously, what would be a case that this would solve a race condition that using the iterator directly in the loop wouldn't?
@@ -585,6 +585,16 @@ where | |||
self.save(&n); | |||
self.tree.pop(); | |||
} | |||
|
|||
pub fn to_tree_map<S: IntoStorageKey>(self, prefix: S) -> super::TreeMap<K, V> { |
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.
pub fn to_tree_map<S: IntoStorageKey>(self, prefix: S) -> super::TreeMap<K, V> { | |
pub fn into_tree_map<S: IntoStorageKey>(self, prefix: S) -> super::TreeMap<K, V> { |
Just to follow https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv naming conventions.
Also, would be nice to have a small comment describing this fn
|
||
pub fn to_tree_map<S: IntoStorageKey>(self, prefix: S) -> super::TreeMap<K, V> { | ||
// We read this into the heap first so one can use the same prefix without getting into trouble | ||
let elements: Vec<(K, V)> = self.into_iter().collect(); |
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.
So I'm curious about if this should be clearing the state when doing this conversion.
Seems like if the API is (self) -> Self
it would be intuitive that the storage would be cleared and the new collection would be filled with this data.
Otherwise, we could consider this pattern of not clearing and have the method be something like:
fn copy_to_tree_map(&self, ..) -> super::TreeMap...
with a better name and whatnot.
Also, the other part that might seem opinionated is if the prefix is added as a parameter here. This makes sense if we go the copy route, but if the API is for an owned self
, it might be more intuitive to just remove the prefix and re-use the one from which you're clearing.
To summarize, my intuitions are that this should either:
- Remove the prefix from parameters, re-use and clear the state, put state back in at the same prefix
- Change this API to
&self
and make it clear that the elements are not being removed from storage- Clearly document this fact and make it clear to devs that they should not use the same prefix as before (seems like a footgun and also requires devs to manually
clear
the state of the old collection)
- Clearly document this fact and make it clear to devs that they should not use the same prefix as before (seems like a footgun and also requires devs to manually
- Another option for fun: Just create a
drain
iterator that clears and gives all key-value pairs back. Let the user decide if they want to clear the elements and put it into another collection or to just use the current iterator and use that to just fill another collection- This gives more freedom to migrate this state into other data structures, rather than just the
collections::ltm
->collections::tm
path
- This gives more freedom to migrate this state into other data structures, rather than just the
Seems like it might be good to get another opinion on this. @itegulov, you might be most familiar with these APIs, wdyt?
That sounds expected. This tree-map is very inefficient. I wonder if that's even more reason to do a |
OK I'll remove the migration code until someone asks for it, then we can better understand their use case |
@@ -18,6 +20,10 @@ use crate::IntoStorageKey; | |||
/// - `above`/`below`: O(log(N)) | |||
/// - `range` of K elements: O(Klog(N)) | |||
/// | |||
#[deprecated( | |||
since = "4.1.0", | |||
note = "Use near_sdk::collections::TreeMap, if you have an existing LegacyTreeMap use LegacyTreeMap::to_tree_map to migrate" |
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.
So this comment is out of date now, just remove the comment about migration and this is good
@@ -18,6 +20,7 @@ use crate::IntoStorageKey; | |||
/// - `above`/`below`: O(log(N)) | |||
/// - `range` of K elements: O(Klog(N)) | |||
/// | |||
#[deprecated(since = "4.1.0", note = "Use near_sdk::collections::TreeMap")] |
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.
noting that the since "4.1.0" is a bit unideal, but given we don't really have a plan what will be the next minor/major version, and no one uses this, it's probably fine
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.
So yeah, how do we feel about depreciations? Are the major release only, or do we just do it whenever?
I have the alternative of marking each individual use of legacy tree map in
legacy_tree_map.rs
as depreciated rather than the whole module, but since the whole source file is depreciated I figured it wasn't worth the effort.Resolves #868