feat(coredeno): wire Service into framework DI with ServiceRuntime[T]
Service embeds ServiceRuntime[Options] for Core/Opts access. NewServiceFactory returns factory for core.WithService registration. Correct Startable/Stoppable signatures with context.Context. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e8695b72a6
commit
7d047fbdcc
2 changed files with 64 additions and 19 deletions
|
|
@ -1,29 +1,39 @@
|
||||||
package coredeno
|
package coredeno
|
||||||
|
|
||||||
import "context"
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
// Service wraps the CoreDeno sidecar for framework lifecycle integration.
|
core "forge.lthn.ai/core/go/pkg/framework/core"
|
||||||
// Implements Startable (OnStartup) and Stoppable (OnShutdown) interfaces.
|
)
|
||||||
|
|
||||||
|
// Service wraps the CoreDeno sidecar as a framework service.
|
||||||
|
// Implements Startable and Stoppable for lifecycle management.
|
||||||
|
//
|
||||||
|
// Registration:
|
||||||
|
//
|
||||||
|
// core.New(core.WithService(coredeno.NewServiceFactory(opts)))
|
||||||
type Service struct {
|
type Service struct {
|
||||||
|
*core.ServiceRuntime[Options]
|
||||||
sidecar *Sidecar
|
sidecar *Sidecar
|
||||||
opts Options
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewService creates a CoreDeno service ready for framework registration.
|
// NewServiceFactory returns a factory function for framework registration via WithService.
|
||||||
func NewService(opts Options) *Service {
|
func NewServiceFactory(opts Options) func(*core.Core) (any, error) {
|
||||||
|
return func(c *core.Core) (any, error) {
|
||||||
return &Service{
|
return &Service{
|
||||||
|
ServiceRuntime: core.NewServiceRuntime(c, opts),
|
||||||
sidecar: NewSidecar(opts),
|
sidecar: NewSidecar(opts),
|
||||||
opts: opts,
|
}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnStartup starts the Deno sidecar. Called by the framework.
|
// OnStartup starts the Deno sidecar. Called by the framework on app startup.
|
||||||
func (s *Service) OnStartup(ctx context.Context) error {
|
func (s *Service) OnStartup(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnShutdown stops the Deno sidecar. Called by the framework.
|
// OnShutdown stops the Deno sidecar. Called by the framework on app shutdown.
|
||||||
func (s *Service) OnShutdown() error {
|
func (s *Service) OnShutdown(_ context.Context) error {
|
||||||
return s.sidecar.Stop()
|
return s.sidecar.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,65 @@
|
||||||
package coredeno
|
package coredeno
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
core "forge.lthn.ai/core/go/pkg/framework/core"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewService_Good(t *testing.T) {
|
func TestNewServiceFactory_Good(t *testing.T) {
|
||||||
opts := Options{
|
opts := Options{
|
||||||
DenoPath: "echo",
|
DenoPath: "echo",
|
||||||
SocketPath: "/tmp/test-service.sock",
|
SocketPath: "/tmp/test-service.sock",
|
||||||
}
|
}
|
||||||
svc := NewService(opts)
|
c, err := core.New()
|
||||||
require.NotNil(t, svc)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
factory := NewServiceFactory(opts)
|
||||||
|
result, err := factory(c)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
svc, ok := result.(*Service)
|
||||||
|
require.True(t, ok)
|
||||||
assert.NotNil(t, svc.sidecar)
|
assert.NotNil(t, svc.sidecar)
|
||||||
assert.Equal(t, "echo", svc.sidecar.opts.DenoPath)
|
assert.Equal(t, "echo", svc.sidecar.opts.DenoPath)
|
||||||
|
assert.NotNil(t, svc.Core(), "ServiceRuntime should provide Core access")
|
||||||
|
assert.Equal(t, opts, svc.Opts(), "ServiceRuntime should provide Options access")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestService_OnShutdown_Good_NotStarted(t *testing.T) {
|
func TestService_WithService_Good(t *testing.T) {
|
||||||
svc := NewService(Options{DenoPath: "echo"})
|
opts := Options{DenoPath: "echo"}
|
||||||
err := svc.OnShutdown()
|
c, err := core.New(core.WithService(NewServiceFactory(opts)))
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.NotNil(t, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestService_Lifecycle_Good(t *testing.T) {
|
||||||
|
c, err := core.New()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
factory := NewServiceFactory(Options{DenoPath: "echo"})
|
||||||
|
result, _ := factory(c)
|
||||||
|
svc := result.(*Service)
|
||||||
|
|
||||||
|
// Verify Startable
|
||||||
|
err = svc.OnStartup(context.Background())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Verify Stoppable (not started, should be no-op)
|
||||||
|
err = svc.OnShutdown(context.Background())
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestService_Sidecar_Good(t *testing.T) {
|
func TestService_Sidecar_Good(t *testing.T) {
|
||||||
svc := NewService(Options{DenoPath: "echo"})
|
c, err := core.New()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
factory := NewServiceFactory(Options{DenoPath: "echo"})
|
||||||
|
result, _ := factory(c)
|
||||||
|
svc := result.(*Service)
|
||||||
|
|
||||||
assert.NotNil(t, svc.Sidecar())
|
assert.NotNil(t, svc.Sidecar())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue