Skip to content
This repository has been archived by the owner on Feb 7, 2024. It is now read-only.

Add DefaultShell as required by #69 #106

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

contrun
Copy link

@contrun contrun commented Jul 13, 2018

Added a DefaultShell function to return a default shell and error as required by issue 69.

shell.go Outdated
urls = append(urls, "/ip4/127.0.0.1/tcp/5001", "https://ipfs.io")

// do not repeat encountered addresses
encountered := map[string]bool{}
Copy link
Member

Choose a reason for hiding this comment

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

The idiom is to just use map[string]struct{} and check for presence.

Copy link
Author

Choose a reason for hiding this comment

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

Thank you for your advise. I will revise it to use map[string]struct{}.

shell.go Outdated
@@ -84,6 +84,42 @@ func NewShellWithClient(url string, c *gohttp.Client) *Shell {
}
}

// Get shell from environmental variables, default api path or gateway.
func DefaultShell() (*Shell, error) {
Copy link
Member

Choose a reason for hiding this comment

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

It would be nice to use a sync.Once and cache the default client. Thoughts?

Copy link
Author

Choose a reason for hiding this comment

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

Will DefaultShell be called more than once? I think people will normally call it for one shot.

Copy link
Member

Choose a reason for hiding this comment

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

I can see people calling DefaultShell().DoThing() quite often.

shell.go Outdated
@@ -84,6 +84,42 @@ func NewShellWithClient(url string, c *gohttp.Client) *Shell {
}
}

// Get shell from environmental variables, default api path or gateway.
Copy link
Member

Choose a reason for hiding this comment

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

We should spell out exactly how we pick the default shell.

Copy link
Author

Choose a reason for hiding this comment

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

What do you think if I add some functions which respectively obtain new shells from environmental variables, default gateway and the api file. I think the order of shells to try in the function DefautlShell is sensible, as normally the environmental variables are explicitly set by the user and I have tried to use gateway as the the last resort.

Copy link
Member

Choose a reason for hiding this comment

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

Sounds good to me.

@Stebalien Stebalien self-assigned this Jul 13, 2018
@Stebalien
Copy link
Member

Thanks!

add functions to obtain new shells from environmental variables, default gateway and the default api file.
Copy link
Member

@Stebalien Stebalien left a comment

Choose a reason for hiding this comment

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

I'd prefer to:

  1. Reduce the API surface. That is, don't expose anything we don't actually need to expose.
  2. Reuse NewLocalShell where possible. NewLocalShell should probably be modified to use IPFS_API if set.

After thinking about it for a bit, we should probably be a little less smart. That is,

  1. If IPFS_API is set, use it regardless.
  2. If an appropriate API file exists, use it regardless.
  3. Otherwise, use ipfs.io.

This way:

  1. The behavior is completely unsurprising.
  2. We don't need to perform any checks. We could still leave a constructor that checks the API endpoint but we wouldn't need one.

I'd rather error out than pick the wrong API endpoint (e.g., if my local one is down).

shell.go Outdated
func DefaultShell() *Shell {
// Load once and cache working default shell address
defaultShellAddrLoadOnce.Do(defaultShell)
return NewShell(defaultShellAddr)
Copy link
Member

Choose a reason for hiding this comment

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

I'd just reuse the same shell. Its thread-safe and, really, we want to reuse the http client.

Also, that'd get rid of the need for DefaultShellWithCheck.

Copy link
Author

@contrun contrun Jul 17, 2018

Choose a reason for hiding this comment

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

If the apifile does exist, but an error occurred while reading the apifile, should we just return nil? This will also be surprising, as people will see unexpected panic. In this extreme case, should we just call panic?

Copy link
Member

Choose a reason for hiding this comment

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

Hm. Yeah, that's unfortunate. We shouldn't panic. We could:

  1. Return nil.
  2. Return an error (stashing it somewhere). That makes the API a bit more difficult to use but that's probably not that much of an issue.
  3. Return a special shell that always fails? Probably a bad idea.

I'd prefer 2.

Copy link
Author

Choose a reason for hiding this comment

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

Do you mind clarify where should I put the error?

Copy link
Member

Choose a reason for hiding this comment

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

Put it in a variable, guarded by a sync.Once.

Copy link
Author

Choose a reason for hiding this comment

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

I did not add a sync.Once to reading api file. For the time being, reading api file will only be called by NewLocalShell, which is already guarded by a sync.Once. Sorry for the delay. I had a really busy week on some earthly bussiness.

Copy link
Member

Choose a reason for hiding this comment

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

No need to apologize for delays, there's no rush on this.

shell.go Outdated
}
}
}
return nil, errors.New(fmt.Sprintf("No working server in %v", urls))
Copy link
Member

Choose a reason for hiding this comment

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

I'd just return nil instead of an error (the error isn't very useful).

shell.go Outdated
@@ -84,6 +92,94 @@ func NewShellWithClient(url string, c *gohttp.Client) *Shell {
}
}

// Load all shell urls with error checking
func NewShellWithCheck(urls ...string) (*Shell, error) {
Copy link
Member

Choose a reason for hiding this comment

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

Maybe TryNewShell? Not happy with the name but can't think of a better one.

Anyways, this should probably have some more documentation (the description doesn't explain what "error checking" means and would otherwise lead me to believe that it returns a slice of shells).

B YI added 2 commits July 28, 2018 12:02
Try to reuse NewLocalShell to return a local Shell
add DefaultShell to return a shell from default api address
add test functions to NewLocalShell, DefaultShell and TryNewShell
@Stebalien
Copy link
Member

Sorry to drag this out... I'm a bit worried that the current naming will confuse users:

  1. NewLocalShell returns a reused, potentially non-local shell.
  2. DefaultShell doesn't check the API file, env, etc.

I'd have two functions:

  1. LocalShell that does everything the current LocalShell does except that it doesn't check the gateway.
  2. DefaultShell that calls LocalShell and, if no local shell exists (we can check for a special ErrNoShell error), it falls back on a gateway shell.

Thoughts?


If you're short on time, I can make these changes myself. I hate changing direction on people like this.

@contrun
Copy link
Author

contrun commented Aug 28, 2018

I think we have different perspectives. For me, all I have to do is adding something that works, while you will be maintaining the code for a long time. You gotta be especailly careful when maintaining a public api. I understand your points. I think they are very valid, and I really appreciate your comments. Unfortunately, currently I do not have much time. I may have sometime this weekend. If you have time currently, please feel free to change it.

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.

2 participants