-
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
Make start and stop functions blocking #181
Conversation
Codecov Report
@@ Coverage Diff @@
## dev #181 +/- ##
==========================================
+ Coverage 69.16% 69.51% +0.35%
==========================================
Files 58 58
Lines 1216 1263 +47
==========================================
+ Hits 841 878 +37
- Misses 303 309 +6
- Partials 72 76 +4
Continue to review full report at Codecov.
|
…ul for unit test.
container/container.go
Outdated
for { | ||
currentStatus, err := ContainerStatus(namespace) | ||
if err != nil { | ||
return err |
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 would use some break
here in order to make sure that we always exit the for loop, it's a bit easier to 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.
Because of the new context of the for
and the creation of currentStatus
, err
is also created. So if I use break
, I'm pretty sure the err will not be assign to the return err
.
If I write, the following code, go says err is shadowed during return
on the return
.
for {
currentStatus, err := ContainerStatus(namespace)
if err != nil {
return
That's why I think if I use the break, the error will also be shadowed.
So there are 2 solutions.
The first one is to use return err
as it's already the case.
The second is to created currentStatus
and then assign the value:
var currentStatus StatusType
currentStatus, err = ContainerStatus(namespace)
if err != nil {
break
}
@antho1404 What solution do you think it's the best?
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 personally use the second solution all the time, we should definitely avoid shadowed variable it's the kind of things that can create bugs easily.
container/service_options.go
Outdated
@@ -71,7 +74,12 @@ func (options *ServiceOptions) swarmPorts() (ports []swarm.PortConfig) { | |||
return | |||
} | |||
|
|||
func (options *ServiceOptions) swarmMounts() (mounts []mount.Mount) { | |||
func (options *ServiceOptions) swarmMounts(force bool) (mounts []mount.Mount) { | |||
// hack for preventing mount when in CircleCI |
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.
A bit hacky, I would add a comment TOFIX just to make sure that we can find this again when the CI allow to mount directories
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.
Comment updated
container/type.go
Outdated
@@ -8,3 +12,13 @@ const ( | |||
STOPPED StatusType = 1 | |||
RUNNING StatusType = 2 | |||
) | |||
|
|||
// TimeoutError represents an error of timeout |
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 think this is not a really good way to have errors I like the fact that we have the details in the error message but i'm sure we can do it better, I would just use something like that directly
errors.New(Timeout reached after " + e.duration.String() + " for ressource " + e.name)
or maybe have a function
func timeoutError(duration, resource) error {
return errors.New(Timeout reached after " + e.duration.String() + " for ressource " + e.name)
}
or just a constant with generic error message but like that we can compare this error in the tests for example.
const TimeoutError = errors.New("Timeout error on container action")
This is a bit too much and confusing because you don't even return an 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.
It's the classic way to create new errors in go and be able to compare. Eg with type casting:
_, ok := err.(*TimeoutError)
https://blog.golang.org/error-handling-and-go
On the contrary, I think we should start creating custom error than using the default one with just a custom description. It will be way easier to debug.
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.
In the case of the TimeoutError
, we can imagine than the CLI could decide to do a retry and then wait again.
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 just feels like a lot of code just for a simple error that could be done in one constant but ok, let's follow the guidelines
service/start.go
Outdated
wg.Add(1) | ||
go func(service *Service, d dependencyDetails, name string, i int) { | ||
serviceID, errStart := dependency.Start(service, d, networkID) | ||
mutex.Lock() |
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'm not sure a mutex is needed here because in this code we have different goroutine that access different index so there is no reason to have conflicts but still is not something bad to do
service/start.go
Outdated
if err != nil { | ||
return | ||
} | ||
err = container.WaitForContainerStatus(namespace, container.RUNNING, time.Minute) //TODO: be careful with timeout |
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.
a minute is really long. If it was in the cli it might be ok but for an internal function I think it's definitely too long
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 timeout you think is ok?
Otherwise, we could pass the timeout duration as a parameter of the Start
and Stop
function.
service/stop.go
Outdated
if errStop != nil && err == nil { | ||
err = errStop | ||
} | ||
mutex.Unlock() |
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 remark here about using defer
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 here i don't see why there is a mutex, in the map it makes sense because it's not thread safe if two threads want to write on the same index but with the error I don't think there is any problems
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.
Updated to use defer.
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 reason for the mutex is the err
comparison in the if
:
if .... err == nil {
service/stop.go
Outdated
return | ||
} | ||
err = container.StopService([]string{namespace, dependencyName}) | ||
err = container.WaitForContainerStatus(namespace, container.STOPPED, time.Minute) //TODO: be careful with timeout |
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.
again probably too long one minute
There is no update on the changelog we should add a line on how this will change the user experience |
…-start-stop # Conflicts: # container/container_test.go
Changelog updated. |
still have some errors from codeclimate |
I'm merging even with the codeclimate issues. I don't know how to fix it in a simple way.. |
Add
WaitForContainerStatus
funcIt's using a
time.Sleep
to block the thread. Should I start a go routine that will sleep and on the main block with a waitgroup? I think thetime.Sleep
is enoughUpdate Daemon start
Update Daemon stop
Update daemon commands
Update Service start
It's using a
WaitGroup
to wait for all dependencies to start.It's also using a
mutex
to editserviceIDs
array that is shared between the goroutines.Update Service stop
It's using a
WaitGroup
to wait for all dependencies to stop.Update service commands