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
Added filter option to ipfs-cluster-ctl status
#627
Conversation
5716d8c
to
0d2fb75
Compare
Would you know why? |
0d2fb75
to
20b13f7
Compare
api/rest/client/methods.go
Outdated
@@ -136,9 +136,13 @@ func (c *defaultClient) Status(ci cid.Cid, local bool) (api.GlobalPinInfo, error | |||
} | |||
|
|||
// StatusAll gathers Status() for all tracked items. | |||
func (c *defaultClient) StatusAll(local bool) ([]api.GlobalPinInfo, error) { | |||
// If valid filter value is provided, it would fetch only those status information | |||
// where status is matching the filter value |
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.
missing full stop
api/rest/client/methods.go
Outdated
// If valid filter value is provided, it would fetch only those status information | ||
// where status is matching the filter value | ||
// Valid filter values are tracker status type, an alias of tracker status type | ||
// (queued or error), comma separated list of track status type and/or it aliases |
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.
missing full stop
api/rest/restapi.go
Outdated
if local == "true" { | ||
var pinInfos []types.PinInfoSerial | ||
|
||
err := api.rpcClient.Call("", |
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.
While changing this function, can you update api.rpcClient.Call
to api.rpcClient.CallContext
and pass in the Request context r.Context()
.
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.
Also can you fix the multilining of the function call so that params aren't on the same line as parens.
api/rest/restapi.go
Outdated
} else { | ||
var pinInfos []types.GlobalPinInfoSerial | ||
err := api.rpcClient.Call("", |
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.
Same as above.
cmd/ipfs-cluster-ctl/main.go
Outdated
tracker status type and/or it aliases ("error,pinning") | ||
On passing invalid filter value no status information will be shown | ||
List of tracker status types | ||
https://github.com/ipfs/ipfs-cluster/blob/319c41cbf195b0453b8d1987991280d3121bac93/api/types.go#L66 |
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 point using the commit url, as we will have to update this url every time we update the list. May as well just put all the filter values here and add a comment in api/types
to remind people that if they add to the list of filters, they need to update this comment with the new values.
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.
You can loop and pretty print that list here. An invalid filter should throw an error (catching it both in the client (to avoid making a request for nothing) and in the server side (for people that doesn't use our client)).
Because the --filter argument takes a value. It's not just a boolean flag. |
api/rest/restapi.go
Outdated
@@ -669,27 +669,74 @@ func (api *API) allocationHandler(w http.ResponseWriter, r *http.Request) { | |||
} | |||
} | |||
|
|||
func match(filters []string, status string) bool { | |||
for _, filter := range filters { |
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.
We should convert to TrackerStatus
(TrackerStatusFromString()
) and compare with the original and not strings. The filter is a user-supplied string, so it should be checked for validity. We should probably move this function to api/types.go
too. We will need to match API functionality in the Go API exposed by the main component (different PR).
Additionally, maybe worth to convert TrackerStatus from iota
to 1 << iota
and have TrackerStatusError = TrackerStatusPinError | TrackerStatusUnpinError | TrackerStatusClusterError
and so on.. thoughts @lanzafame ? we did this with PinType
and I think things were ok, it should not break anything since TrackerStatus is not persisted anywhere.
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.
We should convert to TrackerStatus (TrackerStatusFromString()) and compare with the original and not strings.
Can't do this with aliases such as error
or queued
We will need to match API functionality in the Go API exposed by the main component
Don't understand this.
Do you mean this code ? https://github.com/ipfs/ipfs-cluster/blob/17599dac639cf6fd70343c72c24b7a8f037c733f/rpc_api.go#L111-L123
and https://github.com/ipfs/ipfs-cluster/blob/17599dac639cf6fd70343c72c24b7a8f037c733f/cluster.go#L753-L763
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.
@hsanjuan @lanzafame All comments addressed, except this one
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.
I mean https://github.com/ipfs/ipfs-cluster/blob/master/api/types.go#L582.
It would look like (untested):
diff --git a/api/types.go b/api/types.go
index 1234d09..bc3f426 100644
--- a/api/types.go
+++ b/api/types.go
@@ -34,7 +34,7 @@ var logger = logging.Logger("apitypes")
// TrackerStatus values
const (
// IPFSStatus should never take this value
- TrackerStatusBug TrackerStatus = iota
+ TrackerStatusBug TrackerStatus = 1 << iota
// The cluster node is offline or not responding
TrackerStatusClusterError
// An error occurred pinning
@@ -60,6 +60,12 @@ const (
TrackerStatusSharded
)
+// Composite TrackerStatus
+const (
+ TrackerStatusError = TrackerSTatusClusterError | TrackerStatusPinError | TrackerStatusUnpinError
+ TrackerStatusQueued = TrackerStatusPinQueued | TrackerStatusUnpinQueued
+)
+
// TrackerStatus represents the status of a tracked Cid in the PinTracker
type TrackerStatus int
@@ -75,6 +81,8 @@ var trackerStatusString = map[TrackerStatus]string{
TrackerStatusRemote: "remote",
TrackerStatusPinQueued: "pin_queued",
TrackerStatusUnpinQueued: "unpin_queued",
+ TrackerStatusError: "error",
+ TrackerStatusQueued: "queued",
}
api/rest/restapi_test.go
Outdated
|
||
// Test with filter | ||
var resp3 []api.GlobalPinInfoSerial | ||
makeGet(t, rest, url(rest)+"/pins?filter=queue", &resp3) |
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 be "queued" ?
cmd/ipfs-cluster-ctl/main.go
Outdated
|
||
When the --filter is passed, it will only fetch the peer information | ||
where status of the pin matches with the filter value. | ||
Valid filter values are tracker status types("pinned", "pin_error", "unpinning" etc), |
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.
just list the values
cmd/ipfs-cluster-ctl/main.go
Outdated
`, | ||
ArgsUsage: "[CID]", | ||
Flags: []cli.Flag{ | ||
localFlag(), | ||
cli.StringFlag{ | ||
Name: "filter", | ||
Usage: "Comma seperated list of type tracker status and their aliases", |
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.
Comma-separated list of filters.
The list of acceptable values are on the command help which is printed with the command a few lines over this.
What is https://github.com/ipfs/ipfs-cluster/blob/master/sharness/t0025-ctl-status-report-commands.sh for ? It has more than tests for just |
api/types.go
Outdated
@@ -93,6 +93,36 @@ func TrackerStatusFromString(str string) TrackerStatus { | |||
return TrackerStatusBug | |||
} | |||
|
|||
func IsFilterValid(filter string) bool { |
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.
Adding Queued and Error to TrackerStatus, this should be a oneliner like TrackerStatusFromString(filter) != TrackerStatusBug
. Also, probably better to convert to TrackerStatus first and then call a func (st TrackerStatus) IsValid() bool
cmd/ipfs-cluster-ctl/main.go
Outdated
List of tracker status types | ||
https://github.com/ipfs/ipfs-cluster/blob/319c41cbf195b0453b8d1987991280d3121bac93/api/types.go#L66 | ||
Valid filter values are tracker status types(full list of tracker status | ||
types includes "bug", "cluster_error", "pin_error", "unpin_error", "pinned", |
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.
Please build this list programatically. You can add a helper function in api
which loops the trackerStatusString
and returns a list of valid status strings.
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 that we have bit-flag TrackerStatuses, we can use bitwise comparsion to do matching:
// Match returns true if the tracker status matches the given filter.
// For example TrackerStatusPinError will match TrackerStatusPinError and TrackerStatusError
func (ts TrackerStatus) Match(filter TrackerStatus) bool {
return ts & f > 0
}
api/types.go
should not deal or operate with string versions of TrackerStatus.
api/rest
will need:
- A method to convert a query string in the form of "filter1,filter2,filter3" to TrackerStatus (worth removing whitespaces from the string before splitting). The filter is built the filter as the bitwise OR of the parsed values (
ts1 || ts2 || ts3
) - Use
api.TrackerStatusFromString(pinInfo.Status).Match(filter)
in the method filtering globalPinInfos.
This saves the most-inner loop which compares each Status to each filter value because now all the filter values can be represented as a single thing. Thus the complexity of this method is not exponentially worse with every extra filter value.
License: MIT Signed-off-by: Paul Jewell <sona1111@zoho.com>
License: MIT Signed-off-by: Paul Jewell <sona1111@zoho.com>
-Fixed logic issue in match condition of 'filterStatus' function -Added and verified success of test provided by @lanzafame -Attempted to condense code and apply other cleanup provided by @lanzafame License: MIT Signed-off-by: Paul Jewell <sona1111@zoho.com>
Added filter option to `ipfs-cluster-ctl status` When the --filter is passed, it will only fetch the peer information where status of the pin matches with the filter value. Valid filter values are tracker status types(i.e., "pinned", "pin_error", "unpinning" etc), an alias of tracker status type (i.e., "queued" or "error"), comma separated list of tracker status type and/or it aliases(i.e., "error,pinning") On passing invalid filter value no status information will be shown In particular, the filter would remove elements from []GlobalPinInfo when none of the peers in GlobalPinInfo match the filter. If one peer in the GlobalPinInfo matches the filter, the whole object is returned, including the information for the other peers which may or not match it. filter option works on statusAll("GET /pins"). For fetching pin status for a CID("GET /pins/<cid>"), filter option would have no effect Fixes #445 License: MIT Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Added clients tests Fixes #445 License: MIT Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Added a fail case where an invalid filter is passed in. Update `api.rpcClient.Call` to `api.rpcClient.CallContext` and pass in the Request context r.Context() so that context can be cancelled when the request is cancelled by caller Fixes #445 License: MIT Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Passing `make check` Fixes #445 License: MIT Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Improved matching of filters and tracker status Fixes #445 License: MIT Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
License: MIT Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
0ace1a8
to
70db2a0
Compare
Optimized filter to tracker status matching by using bitwise comparisions License: MIT Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
70db2a0
to
706558c
Compare
License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
@kishansagathiya I have ended wrapping this up. Please check my last commits. Sorry, it was difficult to figure out the details and realize of some small issues without actually messing with it myself. |
I have not tested this much though, would be grateful if you can check things still work as expected. |
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.
OK Tested locally,
However I have a small comment, let me know what you think about that. I will change it accordingly and fix tests.
License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
434ee5c
to
ab29c79
Compare
api/types_test.go
Outdated
@@ -29,7 +29,7 @@ var testPeerID6, _ = peer.IDB58Decode("QmR8Vu6kZk7JvAN2rWVWgiduHatgBq2bb15Yyq8RR | |||
func TestTrackerFromString(t *testing.T) { | |||
testcases := []string{"undefined", "cluster_error", "pin_error", "unpin_error", "pinned", "pinning", "unpinning", "unpinned", "remote"} | |||
for i, tc := range testcases { | |||
if TrackerStatusFromString(tc).String() != TrackerStatus(1<<uint(i)).String() { | |||
if tc != TrackerStatus(1<<uint(i)).String() && tc != TrackerStatus(0).String() { |
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.
I had already fixed this
@kishansagathiya please don't force push on 1) branches worked on by multiple people 2) In progress non-trivial reviews. It makes it difficult to follow up on changes. |
I'm going to force-push the original branch on top, the last commit should be reverted anyway. |
License: MIT Signed-off-by: Hector Sanjuan <code@hector.link>
Sorry! I just realized I had not fixed that test after all. Should be better now. :/ |
@hsanjuan All checks have passed including travis pr check, somehow here it was showing pending(I have seen this happening before). Anyway I have restarted hopefully, that problem wont appear again. |
@hsanjuan finally after two reruns, phew! |
Hmm yeah, every few weeks I spend a couple of days figuring out why tests have become flaky. Maybe it's time for a new round. |
When the --filter is passed, it will only fetch the peer information
where status of the pin matches with the filter value.
Valid filter values are tracker status types(i.e., "pinned",
"pin_error", "unpinning" etc), an alias of tracker status type (i.e.,
"queued" or "error"), comma separated list of tracker status type
and/or it aliases(i.e., "error,pinning")
On passing invalid filter value no status information will be shown
In particular, the filter would remove elements from []GlobalPinInfo
when none of the peers in GlobalPinInfo match the filter. If one peer
in the GlobalPinInfo matches the filter, the whole object is returned,
including the information for the other peers which may or not match it.
filter option works on statusAll("GET /pins"). For fetching pin status
for a CID("GET /pins/"), filter option would have no effect
Continueing from #478
Fixes #445