-
Notifications
You must be signed in to change notification settings - Fork 13
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
extend ListServices api to filter by running services, closes #496 #499
Conversation
ilgooz
commented
Sep 25, 2018
•
edited
Loading
edited
- coreapi.Service type now has IsRunning field, relevant APIs accordingly updated to set this value.
- update dev-core script.
- update database API to filter services by id, add more tests.
* coreapi.Service type know has IsRunning field, relevant APIs accordingly updated to set this value. * update dev-core script. * update database API to filter services by id, add more tests.
some options about setting isRunning field on Service proto:
|
api/api.go
Outdated
@@ -9,18 +10,23 @@ import ( | |||
type API struct { | |||
db *database.ServiceDB | |||
container *container.Container | |||
cfg *config.Config |
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.
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.
yes, it is better to not access config inside container package. in this case we access it from api package.
actually i'd rather doing all this initilazitions in the core package and propagate it down to initialization of grpc server & api. this way we can reuse everything.
api/api_test.go
Outdated
@@ -10,7 +10,7 @@ import ( | |||
"github.com/stretchr/testify/require" | |||
) | |||
|
|||
const testdbname = "db.test" | |||
const testdbname = "/tmp/db.test" |
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.
What is the purpose of changing the path?
Not every OS (windows for example) has /tmp dir (or not every user has access to /tmp dir)
Also if you want tmp dir it's better to use https://golang.org/pkg/os/#TempDir combine with filepath.Join then const path
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.
changes reverted from this PR
database/service_db.go
Outdated
@@ -64,7 +65,8 @@ func (db *ServiceDB) unmarshal(id string, value []byte) (*service.Service, error | |||
} | |||
|
|||
// All returns every service in database. | |||
func (db *ServiceDB) All() ([]*service.Service, error) { | |||
// If ids > 0, it'll only return services with matching ids. |
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.
It's better to keep the functionality of All
as it's was by original.
You can add an GetByIDs or similar method, to keep API more transparent
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.
done
api/api.go
Outdated
} | ||
|
||
// Option is a configuration func for MESG. | ||
type Option func(*API) | ||
|
||
// New creates a new API with given options. | ||
func New(db *database.ServiceDB, options ...Option) (*API, error) { | ||
a := &API{db: db} | ||
func New(options ...Option) (*API, error) { |
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.
The API should be in parameter here, it's a required arguments so it has to be here. If we call New()
without any options (what most developers will do without knowing the codebase) we will have some crash in the code.
Of course you add the error in the end but what's the point to remove a required argument and add a error, it will just be more confusing. I like the pattern to use options but for what is optional and not the stuff required, it doesn't make sense.
Also and more important, let's keep the pull requests simple. This has nothing to do here, it's a pull request about extending the API why do we have some stuff in the database. Especially that this modifications has been done in another pull request that was just merged today and stayed open for more than a week so for this kind of things it better to talk about this in the other PR and not try to include that in a non related PR.
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.
changes reverted from this PR
5da3a2f
to
ba843cb
Compare
ba843cb
to
fe429fa
Compare
lets discuss #499 (comment) |
546cd0b
to
fc2a760
Compare
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 like the part to have the status for the API but I don't think we should do a filter like that. We will need to have a filter for this and maybe for name after or the task or whatever so let's not rush on a feature that is not really necessary and will block us.
Also the part to remove the services when we stop the core is something that the cli should not do but the core itself should when it exits.
I think we should do the part for the status of the service but the part for the filter we should take some time to make this reusable kind of like docker manage it's filters and for the part of deleting the services when we stop, this in the end should not even be in the cli so we don't need this api to only have the running services and most of the things in this PR will no longer be needed like the config for example in the API struct
interface/grpc/core/list_services.go
Outdated
|
||
var errs xerrors.Errors | ||
|
||
for i := 0; i < servicesLen; i++ { |
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 see this pattern once more - publish errors (also nil) and read it from channel to synchronize finishing of goroutines.
Think of using WaitGroup , because they are standard go pattern of sync gorouteines.
Check out an example with a channel:
- buffered - https://play.golang.org/p/l0gW2g-xIR8
- unbuffered - https://play.golang.org/p/ou9ZWoyT3PE
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.
+1 for the wait group, I think it makes the code more readable than a for that is waiting for some events in the chan.
@krhubert I don't get the difference between the buffered and unbuffered version. I would go myself on the first one, what will be the advantage of using the second 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.
thanks, i cannot see an advantage of using WaitGroup here except using range syntax while receiving from errC which makes readability slightly better. also check std package example.
lets give a decision about which way to go. i'm neutral about this, i see that using range has an upside for readability but it also introduces more code.
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.
The example you gave it's slightly different. Here they don't wait for goroutines to finish but provide timeout for TLSHandshake execution. WIthout timeout, there will be no point to put TLSHandshake inside goroutine.
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.
yes, i agree that it is slightly different and using only chans seems the easiest way for that case. they run the code inside 2 goroutines for sure and there is a possibility for both of them to complete. lets also check 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 also suggest to use a WaitGroup to close the chan and use a simple range
to iterate over the errors. (this example from @krhubert https://play.golang.org/p/l0gW2g-xIR8)
I suggest to avoid the classic for i := 0; i < len(arr); i++ {
and anything that directly deal with index on array. It's a source of error.
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.
do three of you have an agreement on this? please like this comment, i'll switch to WaitGroup if i see likes >= 2. :)
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.
About the second example, the code is inside the test package and it's quite old.
8e69d43b32b src/net/net_test.go (Brad Fitzpatrick 2016-09-27 20:50:57 +0000 451) for i := 0; i < 2; i++ {
8e69d43b32b src/net/net_test.go (Brad Fitzpatrick 2016-09-27 20:50:57 +0000 452) if err := <-errc; err != nil {
8e69d43b32b src/net/net_test.go (Brad Fitzpatrick 2016-09-27 20:50:57 +0000 453) t.Fatal(err)
8e69d43b32b src/net/net_test.go (Brad Fitzpatrick 2016-09-27 20:50:57 +0000 454) }
8e69d43b32b src/net/net_test.go (Brad Fitzpatrick 2016-09-27 20:50:57 +0000 455) }
Maybe there are no strict reviews for tests or maybe you can allow a little bit not standard code in tests. I don't know, but ...
Such cases of errc usage are only 20 in the whole codebase (and 14 of them are for tests).
➜ net git:(master) gogrep 'err := <-err' | wc -l
20
➜ net git:(master) gogrep 'err := <-err' | grep _test.go | wc -l
14
It may happen for everyone to produce not "optimal" code. And about your code - the solution is perfectly fine and it works. But it's not the go way - what I mean by that - over the time go developers used to some patterns. WaitGroup is one of it. It just feels more natural for others if they see the pattern like this because everyone used to it and recognize it.
The other example is much simpler from today:
const (
A int = 1
B int = 2
)
The code works and it's nothing wrong with it, but it looks wired because everyone used to
const (
A int = 1
B = 2
)
There are some patterns that everyone understands and it's preferable to use them (for example Option
for optional arguments :))
Last one, WaitGroup is not a solution for all such cases (as you saw with timeout chan)
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.
thank you for the research! i still think that using err chans to wait end of the goroutines is not an anti-pattern but i'm ok with the two ways.
… fully implemented for mocks
5f276bc
to
186b264
Compare
6cebf8b
to
b7d151d
Compare
/cc @ilgooz |
70dd27c
to
f0bae70
Compare
I also agree with this. I'm seeing this PR as intermediate one. Of course, it'd be better if we did first move the related logic from cli to daemon. Maybe, lets merge this as it is and within another PR, we can rm the filter from api and move the logic to daemon. |
My point was that we don't actually even need the filter, let's not do it if we know that we will do it differently in another step, let's think the best way to do it and then we can implement it. I would remove this part and only keep in the the status on the service api |
@antho1404 you're right |
This pull request has been mentioned on MESG Community. There might be relevant details there: https://forum.mesg.com/t/caputre-stdout-in-command-package/70/1 |
This pull request has been mentioned on MESG Community. There might be relevant details there: https://forum.mesg.com/t/caputre-stdout-in-command-package/70/2 |
good to review |
in progress |
good to review |
deleted @krhubert's comment by mistake, it was about removing extra lines while initializing api.API in tests. so, posting this as a reminder. |