diff --git a/calculate_deps.go b/calculate_deps.go index 688030b..91a83bf 100644 --- a/calculate_deps.go +++ b/calculate_deps.go @@ -69,6 +69,11 @@ func (e *Endure) addEdges() error { // and we can safely skip the OK parameter here init, _ := reflect.TypeOf(vrtx.Iface).MethodByName(InitMethodName) + if init.Type == nil { + e.logger.Fatal("init method is absent in struct", zap.String("vertexId", vertexID)) + return errNoInitMethodInStructure + } + /* Add the dependencies (if) which this vertex needs to init Information we know at this step is: 1. vertexID @@ -168,7 +173,7 @@ func (e *Endure) addDependersDeps(vertexID string, vertex interface{}) error { } func (e *Endure) addInitDeps(vertexID string, initMethod reflect.Method) error { - // S2 init args + // Init function in arguments initArgs := functionParameters(initMethod) // iterate over all function parameters diff --git a/endure.go b/endure.go index 4ad46e8..def761d 100644 --- a/endure.go +++ b/endure.go @@ -178,11 +178,6 @@ func (e *Endure) Register(vertex interface{}) error { return errors.New("you should pass pointer to the structure instead of value") } - ok := t.Implements(reflect.TypeOf((*Service)(nil)).Elem()) - if !ok { - return errTypeNotImplementError - } - /* Depender the type Information we know at this step is: 1. vertexID diff --git a/errors.go b/errors.go index 78dd1d0..dd1172e 100644 --- a/errors.go +++ b/errors.go @@ -46,3 +46,4 @@ var ErrorDuringServe = Error{ var errTypeNotImplementError = errors.New("type should implement Service interface") var errVertexAlreadyExists = func(name string) error { return fmt.Errorf("vertex `%s` already exists", name) } var errUnknownErrorOccurred = errors.New("unknown error occurred during the function call") +var errNoInitMethodInStructure = errors.New("init method is absent in struct") diff --git a/go.mod b/go.mod index 222fe40..23e5309 100644 --- a/go.mod +++ b/go.mod @@ -7,4 +7,4 @@ require ( github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.6.1 go.uber.org/zap v1.16.0 -) +) \ No newline at end of file diff --git a/internal.go b/internal.go index 0467460..efddd92 100644 --- a/internal.go +++ b/internal.go @@ -426,6 +426,31 @@ func (e *Endure) callConfigureFn(vertex *structures.Vertex, in []reflect.Value) return nil } +func (e *Endure) stop(vID string) error { + vertex := e.graph.GetVertex(vID) + if reflect.TypeOf(vertex.Iface).Implements(reflect.TypeOf((*Service)(nil)).Elem()) { + in := make([]reflect.Value, 0, 1) + // add service itself + in = append(in, reflect.ValueOf(vertex.Iface)) + + err := e.callStopFn(vertex, in) + if err != nil { + e.logger.Error("error occurred during the callStopFn", zap.String("vertex id", vertex.ID)) + return err + } + + if reflect.TypeOf(vertex.Iface).Implements(reflect.TypeOf((*Graceful)(nil)).Elem()) { + err = e.callCloseFn(vertex.ID, in) + if err != nil { + e.logger.Error("error occurred during the callCloseFn", zap.String("vertex id", vertex.ID)) + return err + } + } + } + + return nil +} + func (e *Endure) callStopFn(vertex *structures.Vertex, in []reflect.Value) error { // Call Stop() method, which returns only error (or nil) e.logger.Debug("stopping vertex", zap.String("vertexId", vertex.ID)) @@ -441,30 +466,6 @@ func (e *Endure) callStopFn(vertex *structures.Vertex, in []reflect.Value) error return nil } -func (e *Endure) stop(vID string) error { - vertex := e.graph.GetVertex(vID) - - in := make([]reflect.Value, 0, 1) - // add service itself - in = append(in, reflect.ValueOf(vertex.Iface)) - - err := e.callStopFn(vertex, in) - if err != nil { - e.logger.Error("error occurred during the callStopFn", zap.String("vertex id", vertex.ID)) - return err - } - - if reflect.TypeOf(vertex.Iface).Implements(reflect.TypeOf((*Graceful)(nil)).Elem()) { - err = e.callCloseFn(vertex.ID, in) - if err != nil { - e.logger.Error("error occurred during the callCloseFn", zap.String("vertex id", vertex.ID)) - return err - } - } - - return nil -} - // TODO add stack to the all of the log events func (e *Endure) callCloseFn(vID string, in []reflect.Value) error { v := e.graph.GetVertex(vID) @@ -563,21 +564,24 @@ func (e *Endure) forceExitHandler(ctx context.Context, data chan *structures.Dll // serve run configure (if exist) and callServeFn for each node and put the results in the map func (e *Endure) serve(n *structures.DllNode) error { - // handle all configure - in := make([]reflect.Value, 0, 1) - // add service itself - in = append(in, reflect.ValueOf(n.Vertex.Iface)) + // check if type implements serve, if implements, call serve + if reflect.TypeOf(n.Vertex.Iface).Implements(reflect.TypeOf((*Service)(nil)).Elem()) { + // handle all configure + in := make([]reflect.Value, 0, 1) + // add service itself + in = append(in, reflect.ValueOf(n.Vertex.Iface)) - res := e.callServeFn(n.Vertex, in) - if res != nil { - e.results.Store(res.vertexID, res) - } else { - e.logger.Error("nil result returned from the vertex", zap.String("vertex id", n.Vertex.ID), zap.String("tip:", "serve function should return initialized channel with errors")) - return fmt.Errorf("nil result returned from the vertex, vertex id: %s", n.Vertex.ID) - } + res := e.callServeFn(n.Vertex, in) + if res != nil { + e.results.Store(res.vertexID, res) + } else { + e.logger.Error("nil result returned from the vertex", zap.String("vertex id", n.Vertex.ID), zap.String("tip:", "serve function should return initialized channel with errors")) + return fmt.Errorf("nil result returned from the vertex, vertex id: %s", n.Vertex.ID) + } - // start poll the vertex - e.poll(res) + // start poll the vertex + e.poll(res) + } return nil } diff --git a/tests/backoff/backoff_test.go b/tests/backoff/backoff_test.go index b52f638..9343a5b 100644 --- a/tests/backoff/backoff_test.go +++ b/tests/backoff/backoff_test.go @@ -91,8 +91,8 @@ func TestEndure_MainThread_Backoff(t *testing.T) { wg.Wait() after := time.Now().Second() - // after - now should not be more than 11 as we set in NewContainer - assert.Greater(t, 11, after-now, "time") + // after - now should not be more than 15 as we set in NewContainer + assert.Greater(t, 15, after-now, "time") } func TestEndure_BackoffTimers(t *testing.T) { diff --git a/tests/interfaces/interfaces_test.go b/tests/interfaces/interfaces_test.go index 9a02ca5..1e1ab74 100644 --- a/tests/interfaces/interfaces_test.go +++ b/tests/interfaces/interfaces_test.go @@ -13,6 +13,8 @@ import ( "github.com/spiral/endure/tests/interfaces/plugins/plugin3" "github.com/spiral/endure/tests/interfaces/plugins/plugin4" "github.com/spiral/endure/tests/interfaces/plugins/plugin5" + notImplPlugin1 "github.com/spiral/endure/tests/interfaces/service/not_implemented_service/plugin1" + notImplPlugin2 "github.com/spiral/endure/tests/interfaces/service/not_implemented_service/plugin2" "github.com/stretchr/testify/assert" ) @@ -110,3 +112,18 @@ func TestEndure_NamedProvides_WrongType_Fail(t *testing.T) { assert.NoError(t, c.Stop()) } + +func TestEndure_ServiceInterface_NotImplemented_Ok(t *testing.T) { + c, err := endure.NewContainer(endure.DebugLevel) + assert.NoError(t, err) + + assert.NoError(t, c.Register(¬ImplPlugin1.Foo{})) + assert.NoError(t, c.Register(¬ImplPlugin2.Foo{})) + + assert.NoError(t, c.Init()) + + _, err = c.Serve() + assert.NoError(t, err) + + assert.NoError(t, c.Stop()) +} diff --git a/tests/interfaces/service/not_implemented_service/plugin1/plugin1.go b/tests/interfaces/service/not_implemented_service/plugin1/plugin1.go new file mode 100644 index 0000000..51d9b27 --- /dev/null +++ b/tests/interfaces/service/not_implemented_service/plugin1/plugin1.go @@ -0,0 +1,8 @@ +package plugin1 + +type Foo struct { +} + +func (f *Foo) Init() error { + return nil +} diff --git a/tests/interfaces/service/not_implemented_service/plugin2/plugin2.go b/tests/interfaces/service/not_implemented_service/plugin2/plugin2.go new file mode 100644 index 0000000..c849337 --- /dev/null +++ b/tests/interfaces/service/not_implemented_service/plugin2/plugin2.go @@ -0,0 +1,8 @@ +package plugin2 + +type Foo struct { +} + +func (f *Foo) Init() error { + return nil +}