Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Dapp refresh #5752

Merged
merged 40 commits into from
Aug 9, 2017
Merged

Dapp refresh #5752

merged 40 commits into from
Aug 9, 2017

Conversation

CraigglesO
Copy link
Contributor

@CraigglesO CraigglesO commented Jun 2, 2017

Closes: #4194

alt1
alt2

If adding or removing a dapp, this will update the list upon:

  • removing a dapp from the dapps folder
  • linking a dapp
  • a 404.

If you want to quickly test it:
git clone https://github.com/paritytech/skeleton mydapp
git cd mydapp

ln -s $PWD/dist $HOME/Library/Application\ Support/io.parity.ethereum/dapps/mydapp
(If you are using windows go to the tutorial... :P)

Click refresh

and to test removal:
cd ~/Library/Application Support/io.parity.ethereum/dapps
or cd /Users/$USER/Library/Application Support/io.parity.ethereum/dapps

rm -rf mydapp

@CraigglesO CraigglesO added the A3-inprogress ⏳ Pull request is in progress. No review needed at this stage. label Jun 2, 2017
@@ -39,7 +40,7 @@ pub struct EndpointInfo {
pub icon_url: String,
}

pub type Endpoints = Arc<BTreeMap<String, Box<Endpoint>>>;
pub type Endpoints = Arc<RwLock<BTreeMap<String, Box<Endpoint>>>>;
Copy link
Contributor

Choose a reason for hiding this comment

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

why add RwLock if it's only read through? doesn't seem to need any lock at all

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, the end goal is to push to the BTreeMap new dapp entries as a js developer adds. Currently you have to restart parity to get the new dapp.

@rphmeier rphmeier added the M4-core ⛓ Core client code / Rust. label Jun 5, 2017
@CraigglesO CraigglesO added A0-pleasereview 🤓 Pull request needs code review. and removed A3-inprogress ⏳ Pull request is in progress. No review needed at this stage. labels Jul 5, 2017
@CraigglesO CraigglesO requested a review from tomusdrw July 5, 2017 06:44
Copy link
Collaborator

@tomusdrw tomusdrw left a comment

Choose a reason for hiding this comment

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

Few grumbles.

dapps/Cargo.toml Outdated
@@ -14,6 +14,7 @@ futures = "0.1"
linked-hash-map = "0.3"
log = "0.3"
parity-dapps-glue = "1.7"
parking_lot = "0.4"
Copy link
Collaborator

Choose a reason for hiding this comment

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

RwLock is re-export in util.

let mut v = Vec::new();
// accumulate the dead dapps
for (k, _) in pages.read().iter() {
if k == "ui" || k == "proxy" || k == WEB_PATH {
Copy link
Collaborator

Choose a reason for hiding this comment

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

That's bad, we should export a list of local filesystem dapps in all_endpoints (for instance return Endpoints and Vec<String>)

if k == "ui" || k == "proxy" || k == WEB_PATH {
continue;
} else if new_pages.contains_key(k) != true {
v.push(k.clone());
Copy link
Collaborator

Choose a reason for hiding this comment

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

If you keep the list of local endpoints the code here can be greately simplified (just let to_remove = old_local.iter().partition(|x| !new_local.contains_key(x)))

// new dapps to be added
for (k, v) in new_pages {
if pages.read().contains_key(&k) != true {
pages.write().insert(k, v);
Copy link
Collaborator

Choose a reason for hiding this comment

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

You should acquire single lock at the top of the function instead of using read()/write() on every iteration.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I must have bad luck, but the reason I used a vector and the reason I use short term locks, (and maybe this is a unique issue to parking_lot) is that if you have a read lock, the write lock will wait indefinitely for the read lock to finish before creating it's own lock. Has no one else run into this?

Copy link
Collaborator

Choose a reason for hiding this comment

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

You should only take one write() lock at the top (you will be able to read from it as well).

Copy link
Contributor

Choose a reason for hiding this comment

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

it's actually a safety feature to deadlock instead of aliasing writeable pointers

Copy link
Contributor Author

@CraigglesO CraigglesO Jul 6, 2017

Choose a reason for hiding this comment

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

Ok, so:
a) if the function is not too complex, it's ok to have a write lock for the time of the function
b) with a write, it can also handle reads (unless handling mutable and immutable in the same instance [.iter()])

Arc::new(RwLock::new(pages))
}

pub fn refresh_local_endpoints(
Copy link
Collaborator

Choose a reason for hiding this comment

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

IMHO this function should be part of Endpoints

@@ -22,6 +22,7 @@ use endpoint::{Endpoint, Handler, EndpointPath};
use {address, handlers};

/// Redirection to UI server.
#[derive(Clone)]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is it needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Didn't clean it after playing with the code -_-

@@ -61,14 +62,16 @@ impl http::RequestMiddleware for Router {
let is_head_request = *req.method() == hyper::Method::Head;

trace!(target: "dapps", "Routing request to {:?}. Details: {:?}", url, req);
let refresh = self.endpoints.clone();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is it cloned here?

@@ -109,6 +112,7 @@ impl http::RequestMiddleware for Router {
=>
{
trace!(target: "dapps", "Resolving to 404.");
refresh.unwrap().refresh_local_dapps();
Copy link
Collaborator

Choose a reason for hiding this comment

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

self.endpoints can be empty so you should unwrap.
It should be just self.endpoints.as_ref().map(|endpoints| endpoints.refresh_local_dapps()).

Even though the dapps are refreshed we should still re-try resolving the request.
Most likely a recursive call should be done here with some additional parameter preventing a refresh again.

@@ -95,6 +95,11 @@ export default class Parity {
.execute('parity_dappsList');
}

dappsRefresh () {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think the RPC method (and JS code) will be useful at all if the router can auto-refresh missing dapps.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah! Thanks for the review! I'll reply when I wake up in a few hours. The JS code just ensures an instant refresh.. otherwise you have to reload the page (+R), and I don't think we should require that. It would be confusing to the end user.

So for instance, if you link a new dapp... how would JS know unless it constantly checked if there was a new one... [When pub-sub is ready, I can change it] but this is incredibly inefficient since the number of times a developer is going to add a new dapp is like... once a month at most?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, I think refreshing the page is actually ok when you add a new dapp. As you said it will happen once a month at most.
IMHO not worth supporting additional RPC method and this additional JS code.

But I don't have very strong opinion on that. Since the code is already there we can probably merge it.

@tomusdrw tomusdrw added A5-grumble 🔥 Pull request has minor issues that must be addressed before merging. and removed A0-pleasereview 🤓 Pull request needs code review. labels Jul 5, 2017
@CraigglesO CraigglesO added A5-grumble 🔥 Pull request has minor issues that must be addressed before merging. and removed A0-pleasereview 🤓 Pull request needs code review. labels Jul 12, 2017
@gavofyork gavofyork added A3-inprogress ⏳ Pull request is in progress. No review needed at this stage. and removed A5-grumble 🔥 Pull request has minor issues that must be addressed before merging. labels Jul 13, 2017
@CraigglesO
Copy link
Contributor Author

CraigglesO commented Jul 15, 2017

The crazy thing is that the bug would only rear it's ugly head some cases. simplify filter push proves that. Anyways, the test cases would freeze on a let mut pages = self.endpoints.write() SOOOO Unless someone knows how to make that stop I'm making it verbose:

pub fn refresh_local_dapps(&self) {
		let mut local = self.local_endpoints.write();
		let new_local = apps::fs::local_endpoints(self.dapps_path.clone(), self.embeddable.clone());
		let (_, to_remove): (Vec<String>, Vec<String>) = local.clone()
			.into_iter()
			.partition(|k| new_local.contains_key(&k.clone()));
		// remove the dead dapps
		for k in to_remove {
			let index = local.iter().position(|x| *x == k).unwrap();
			local.remove(index);
			self.endpoints.write().remove(&k);
		}
		// new dapps to be added
		for (k, v) in new_local {
			if self.endpoints.write().contains_key(&k) != true {
				local.push(k.clone());
				self.endpoints.write().insert(k, v);
			}
		}
	}

@tomusdrw tomusdrw added A1-onice 🌨 Pull request is reviewed well, but should not yet be merged. and removed A3-inprogress ⏳ Pull request is in progress. No review needed at this stage. labels Jul 31, 2017
@tomusdrw
Copy link
Collaborator

Waiting for #6192

dapps/src/lib.rs Outdated
.partition(|k| new_local.contains_key(&k.clone()));
// remove the dead dapps
for k in to_remove {
let index = local.iter().position(|x| *x == k).unwrap();
Copy link
Collaborator

Choose a reason for hiding this comment

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

  1. unwrap -> expect
  2. This makes the function quadratic and we don't really need it here. At the end of the function just replace self.local_endpoints with new_local.keys().collect().

dapps/src/lib.rs Outdated
}
// new dapps to be added
for (k, v) in new_local {
if self.endpoints.read().contains_key(&k) != true {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use !<condition> instead of comparing to bool.

dapps/src/lib.rs Outdated
// new dapps to be added
for (k, v) in new_local {
if self.endpoints.read().contains_key(&k) != true {
local.push(k.clone());
Copy link
Collaborator

Choose a reason for hiding this comment

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

That will be not needed when you do:
*local = new_local.keys().collect()

@@ -110,6 +112,7 @@ impl http::RequestMiddleware for Router {
=>
{
trace!(target: "dapps", "Resolving to 404.");
self.endpoints.as_ref().map(|endpoints| endpoints.clone().refresh_local_dapps());
Copy link
Collaborator

Choose a reason for hiding this comment

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

It should retry resolving the dapp.

tomusdrw and others added 2 commits July 31, 2017 17:00
@tomusdrw tomusdrw added A6-mustntgrumble 💦 Pull request has areas for improvement. The author need not address them before merging. and removed A1-onice 🌨 Pull request is reviewed well, but should not yet be merged. labels Aug 1, 2017
@tomusdrw
Copy link
Collaborator

tomusdrw commented Aug 1, 2017

I believe js/package-lock.json is produced by new NPM, right? I suppose we should finally check that in: @jacogr ?

@tomusdrw tomusdrw added A7-looksgoodcantmerge 🙄 Pull request is reviewed well, but cannot be merged due to conflicts. and removed A6-mustntgrumble 💦 Pull request has areas for improvement. The author need not address them before merging. labels Aug 1, 2017
@tomusdrw tomusdrw added A8-looksgood 🦄 Pull request is reviewed well. and removed A7-looksgoodcantmerge 🙄 Pull request is reviewed well, but cannot be merged due to conflicts. labels Aug 2, 2017
@gavofyork gavofyork merged commit 7d17d77 into master Aug 9, 2017
@gavofyork gavofyork deleted the dapp-refresh branch August 9, 2017 17:06
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A8-looksgood 🦄 Pull request is reviewed well. M4-core ⛓ Core client code / Rust. M6-rpcapi 📣 RPC API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants