Skip to content
This repository has been archived by the owner on Sep 3, 2021. It is now read-only.

Compute changed keys in pull and mutate #341

Merged
merged 9 commits into from
Apr 29, 2021
Merged

Conversation

arv
Copy link
Contributor

@arv arv commented Apr 22, 2021

Return the changed keys in mutation commits and maybe end pull.

Towards rocicorp/replicache#63

We now return the touched keys in subscribe queries.

We also returned the changed keys in mutation commits and maybe end pull.

Towards rocicorp/replicache#63
Copy link
Contributor Author

@arv arv left a comment

Choose a reason for hiding this comment

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

I think this needs a few rounds of polish review but I think it is ready to start looking at

src/embed/connection.rs Outdated Show resolved Hide resolved
src/db/read.rs Outdated Show resolved Hide resolved
}

/// Returns the keys that are different between two maps.
pub fn diff<'a>(a: &'a Self, b: &'a Self) -> Result<Vec<String>, FromUtf8Error> {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

One optimization I didn't do is to create key ranges of this... we can do that later.

@aboodman
Copy link
Contributor

🎉

One question right off:

We now return the touched keys in subscribe queries.

It seems like the JS would already have the information it needs here? It know what keys are being requested and the scan parameters.

@arv
Copy link
Contributor Author

arv commented Apr 22, 2021

It seems like the JS would already have the information it needs here? It know what keys are being requested and the scan parameters.

That is true. My reason for moving this to Rust was code reuse in future non JS SDK but maybe that was a bad call? At one point I even wanted to keep track of the subscriptions in Rust but due to multiple tabs I moved the storage up to js.

@aboodman
Copy link
Contributor

aboodman commented Apr 22, 2021 via email

@arv
Copy link
Contributor Author

arv commented Apr 22, 2021

It's up to you. If you find it easy enough to work in Rust, I don't care. I
just don't want hypothetical desire to work on other platforms in the
future to slow us down at all now. If you find yourself fighting with rust,
and it's easy to move it out to JS, do it.

Doing it in JS to see how much complexity it removes.

@arv arv changed the title Minimize subscription refire Compute diff pulling and mutating Apr 22, 2021
@arv arv changed the title Compute diff pulling and mutating Compute diff in pull and mutate Apr 22, 2021
Some(pending_val) => match self.base_get(key) {
Some(base_val) => {
if pending_val != base_val {
keys.push(String::from_utf8(key.clone())?);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do the conversion to utf8 here?

prolly::Map keys are [u8] so I would expect its diff API to be expressed in those terms too.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sad to copy/allocate all the strings. Did you consider attempt returning references to the data already in the map? Not sure if it's worth the complexity...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Needs to be copied later so I copied it earlier since it made the code simpler. I can think a bit more about this to see if it makes sense to go [u8] all the way to JS

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Going to do this in another PR

src/prolly/map.rs Outdated Show resolved Hide resolved
src/prolly/map.rs Outdated Show resolved Hide resolved
src/db/read.rs Outdated
}
}

pub type Subscription = Arc<RwLock<SubscriptionInner>>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we actually need concurrent mutability of this data? I'm very concerned about the proliferation of locks in our code as it will made deadlock increasingly difficult to avoid.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In theory we do not need locks because JS and Wasm is single threaded but I don't think Rust would allow that.

The following case needs "concurrent" access.

rep.subscribe(tx => 
  Promise.all([tx.get('a'), tx.get('b')])
);

I do not see how this could deadlock but it is always a good thing to keep in mind.

Copy link
Contributor

Choose a reason for hiding this comment

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

At least some of the proliferation of locks in the rust code is due to rust not allowing inner mutability without them. Where in another language we wouldn't bother putting a lock around a thing that we know is not going to be accessed concurrently, rust makes us.

src/db/read.rs Outdated Show resolved Hide resolved
src/embed/connection.rs Show resolved Hide resolved
src/embed/types.rs Outdated Show resolved Hide resolved
src/prolly/map.rs Outdated Show resolved Hide resolved
src/sync/pull.rs Outdated Show resolved Hide resolved
src/sync/pull.rs Outdated Show resolved Hide resolved
@arv arv changed the title Compute diff in pull and mutate Compute changed keys in pull and mutate Apr 27, 2021
src/sync/pull.rs Outdated
@@ -1203,6 +1297,7 @@ mod tests {
intervening_sync: false,
exp_replay_ids: vec![],
exp_err: None,
exp_changed_keys: ChangedKeysMap::new(),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@phritz It seems like this test are all about nop mutations and pulls? I was looking for a rust/wasm test that does pull with changes but I guess we didn't need to test this before?

src/sync/pull.rs Show resolved Hide resolved
Copy link
Contributor Author

@arv arv left a comment

Choose a reason for hiding this comment

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

Ready for realz. PTAL

Some(pending_val) => match self.base_get(key) {
Some(base_val) => {
if pending_val != base_val {
keys.push(String::from_utf8(key.clone())?);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Going to do this in another PR

@arv arv requested a review from aboodman April 29, 2021 18:58
@arv arv merged commit 0e54241 into rocicorp:main Apr 29, 2021
@arv arv deleted the subscribe-track branch April 29, 2021 20:21
Copy link
Contributor

@phritz phritz left a comment

Choose a reason for hiding this comment

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

I gave this a careful reading and it looks great! Only a couple minor comments.

src/embed/types.rs Show resolved Hide resolved
src/sync/pull.rs Show resolved Hide resolved
src/sync/pull.rs Show resolved Hide resolved
src/sync/types.rs Show resolved Hide resolved
arv added a commit that referenced this pull request May 6, 2021
Followup to #341
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants