-
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
service: service.Start() can block forever #382
Comments
In this case one of the task created by the docker service will never trigger the task and so we will never get the error from that. We need to find a way to get the errors between the creation of the service (that is fine) and before the creation of the task |
future note: add a test afterwards to service/start_test.go func TestX(t *testing.T) {
service := &Service{
Name: "TestServiceDependenciesListensFromSamePort",
Dependencies: map[string]*Dependency{
"test": {
Image: "nginx",
Ports: []string{"80"},
},
"test2": {
Image: "nginx",
Ports: []string{"80"},
},
},
}
fmt.Println(service.Start()) // currently blocks forever
} |
Let's check if the error is still here |
The pbm stills exist |
So, What about adding a timeout on Otherwise, we could add a more sophisticated system that consider a task as error if it didn't change status for let's say 1min. |
Maybe service.Start() should return with an error after first task exited with 1. But keep in mind that this is a very strict rule. Because it requires services to be more logicfull for example a service should not exit with 1 if it cannot connect to its dependency database. It should retry instead. Since docker services are started without an order this might happen. In future we may give more flexibility to users by allowing a config like restart=always for services but for now let's go strict and remove any margin to errors. If we adopt restart=always, it's users' responsibility to check if services are running correctly so we shouldn't block on Start() like we do now. |
I really think we should keep the restart always. It's a really nice feature for the service to restart if any error happen. |
Actually, I have a solution: package service
import (
"fmt"
"testing"
"github.com/mesg-foundation/core/container"
)
func TestX(t *testing.T) {
c, _ := container.New()
service, _ := FromService(&Service{
Name: "TestServiceDependenciesListensFromSamePort1",
Dependencies: []*Dependency{
{
Key: "1",
Image: "nginx",
Ports: []string{"80"},
},
},
}, ContainerOption(c))
service2, _ := FromService(&Service{
Name: "TestServiceDependenciesListensFromSamePort2",
Dependencies: []*Dependency{
{
Key: "1",
Image: "nginx",
Ports: []string{"80"},
},
},
}, ContainerOption(c))
fmt.Println(service.Start()) // start correctly
fmt.Println(service2.Start()) // return an error
} Error returned:
So the fix is to start the docker service one by one. What do you think @mesg-foundation/core ? |
Maybe we should make an exception for ports that are in use by handling this error in our side so we can return an error on Start(). Note that colliding ports may happen both in the private network of a MESG service and public ports that mapped to host machine. |
Port collision can only happen on the ingress and host network because they share the same IP. |
I like the idea to start service one after another. What we must do as well, is to create an issue in docker repo and wait for the fix, then switch to parallel service deploy |
Similar to #381.
If dependencies from same service listens from the same port, service.Start() will block forever because it waits for status RUNNING for dependency containers. However, N-1 of them will never be in RUNNING state because ports collides.
Also any other misconfiguration on Service or service file (mesg.yml) can cause the same issue.
The text was updated successfully, but these errors were encountered: