component: Rename and simplification

This commit is contained in:
Tom Wiesing 2022-10-18 09:17:25 +02:00
parent e320bb37bb
commit f7c8a43844
No known key found for this signature in database
26 changed files with 99 additions and 101 deletions

View file

@ -22,6 +22,20 @@ type Backupable interface {
Backup(context StagingContext) error
}
// Snapshotable represents a component with a Snapshot method.
type Snapshotable interface {
Component
// SnapshotNeedsRunning returns if this Snapshotable requires a running instance.
SnapshotNeedsRunning() bool
// SnapshotName returns a new name to be used as an argument for path.
SnapshotName() string
// Snapshot snapshots a part of the instance
Snapshot(wisski models.Instance, context StagingContext) error
}
// StagingContext represents a context for [Backupable] and [Snapshotable]
type StagingContext interface {
// IO returns the input output stream belonging to this backup file
@ -50,20 +64,6 @@ type StagingContext interface {
AddFile(path string, op func(file io.Writer) error) error
}
// Snapshotable represents a component with a Snapshot method.
type Snapshotable interface {
Component
// SnapshotNeedsRunning returns if this Snapshotable requires a running instance.
SnapshotNeedsRunning() bool
// SnapshotName returns a new name to be used as an argument for path.
SnapshotName() string
// Snapshot snapshots a part of the instance
Snapshot(wisski models.Instance, context StagingContext) error
}
// NewStagingContext returns a new [StagingContext]
func NewStagingContext(env environment.Environment, io stream.IOStream, path string, manifest chan<- string) StagingContext {
return &stagingContext{

View file

@ -1,20 +1,57 @@
// Package component holds the main abstraction for components.
package component
// Component represents a logical subsystem of the distillery.
// Every component must embed [ComponentBase] and should be initialized using [Initialize].
import (
"reflect"
"strings"
"github.com/FAU-CDI/wisski-distillery/internal/config"
"github.com/FAU-CDI/wisski-distillery/pkg/environment"
)
// Components represents a logical subsystem of the distillery.
// A Component should be implemented as a pointer to a struct.
// Every component must embed [Base] and should be initialized using [Init] inside a [lazy.Pool].
//
// By convention these are defined within their corresponding subpackage.
// This subpackage also contains all required resources.
//
// Components are initialized using a [Pool].
type Component interface {
// Name returns the name of this component
// Name should be implemented by the [ComponentBase] struct.
Name() string
// getComponentBase returns the underlying ComponentBase object of this Component.
// getBase returns the underlying ComponentBase object of this Component.
// It is used internally during initialization
getComponentBase() *ComponentBase
getBase() *Base
}
// Base is embedded into every Component
type Base struct {
name string // name is the name of this component
Still // the underlying still of the distillery
}
//lint:ignore U1000 used to implement the private methods of [Component]
func (cb *Base) getBase() *Base {
return cb
}
// Init initialzes a new componeont Component with the provided still.
// Init is only initended to be used within a lazy.Pool[Component,Still].
func Init(component Component, core Still) Component {
base := component.getBase() // pointer to a struct
base.Still = core
base.name = strings.ToLower(reflect.TypeOf(component).Elem().Name())
return component
}
func (cb Base) Name() string {
return cb.name
}
// Still represents the central part of a distillery.
// It is used inside the main distillery struct, as well as every component via [ComponentBase].
type Still struct {
Environment environment.Environment // environment to use for reading / writing to and from the distillery
Config *config.Config // the configuration of the distillery
}

View file

@ -11,7 +11,7 @@ import (
// Control represents the running control server.
type Control struct {
component.ComponentBase
component.Base
Servables []component.Servable
}

View file

@ -17,7 +17,7 @@ import (
// Exporter manages snapshots and backups
type Exporter struct {
component.ComponentBase
component.Base
SQL *sql.SQL
Instances *instances.Instances

View file

@ -9,7 +9,7 @@ import (
)
type Bookkeeping struct {
component.ComponentBase
component.Base
}
// SnapshotNeedsRunning returns if this Snapshotable requires a running instance.

View file

@ -8,7 +8,7 @@ import (
// Config implements backing up configuration
type Config struct {
component.ComponentBase
component.Base
}
func (*Config) BackupName() string {

View file

@ -7,7 +7,7 @@ import (
// Filesystem implements snapshotting an instnace filesystem
type Filesystem struct {
component.ComponentBase
component.Base
}
// SnapshotNeedsRunning returns if this Snapshotable requires a running instance.

View file

@ -9,7 +9,7 @@ import (
)
type Pathbuilders struct {
component.ComponentBase
component.Base
Instances *instances.Instances
}

View file

@ -10,7 +10,7 @@ import (
// Logger is responsible for logging backups and snapshots
type Logger struct {
component.ComponentBase
component.Base
SQL *sql.SQL
}

View file

@ -13,7 +13,7 @@ import (
)
type Home struct {
component.ComponentBase
component.Base
Instances *instances.Instances

View file

@ -14,7 +14,7 @@ import (
)
type Info struct {
component.ComponentBase
component.Base
Exporter *exporter.Exporter
Instances *instances.Instances

View file

@ -19,7 +19,7 @@ import (
// Instances manages multiple WissKI Instances.
type Instances struct {
component.ComponentBase
component.Base
TS *triplestore.Triplestore
SQL *sql.SQL

View file

@ -9,7 +9,7 @@ import (
// Component meta is responsible for managing metadata per WissKI Instance
type Meta struct {
component.ComponentBase
component.Base
SQL *sql.SQL

View file

@ -6,31 +6,27 @@ import (
"github.com/FAU-CDI/wisski-distillery/pkg/lazy"
)
type ComponentPool struct {
// Pool holds a pool of components.
type Pool struct {
pool lazy.Pool[Component, Still]
poolInit sync.Once
}
func (pool *ComponentPool) init() {
func (pool *Pool) init() {
pool.poolInit.Do(func() {
pool.pool.Init = func(component Component, core Still) Component {
base := component.getComponentBase()
base.Still = core
base.name = nameOf(component)
return component
}
pool.pool.Init = Init
})
}
type ComponentPoolContext = *lazy.PoolContext[Component]
type ComponentAllFunc = func(context ComponentPoolContext) []Component
type PoolContext = *lazy.PoolContext[Component]
type AllFunc = func(context PoolContext) []Component
func (pool *ComponentPool) All(core Still, init func(context ComponentPoolContext) []Component) []Component {
func (pool *Pool) All(core Still, init func(context PoolContext) []Component) []Component {
pool.init()
return pool.pool.All(core, init)
}
// MakeComponent creates or returns a cached component of the given Context.
// Make creates or returns a cached component of the given Context.
//
// Components are initialized by first calling the init function.
// Then all component-like fields of fields are filled with their appropriate components.
@ -45,24 +41,24 @@ func (pool *ComponentPool) All(core Still, init func(context ComponentPoolContex
// Furthermore, the init function may not cause other components to be initialized.
//
// The init function may be nil, indicating that no additional initialization is required.
func MakeComponent[C Component](context ComponentPoolContext, core Still, init func(component C)) C {
func Make[C Component](context PoolContext, core Still, init func(component C)) C {
return lazy.Make(context, init)
}
// ExportComponents exports all components that are a C from the pool.
// ExportAll exports all components that are a C from the pool.
//
// All should be the function of the core that initializes all components.
// All should only make calls to [InitComponent].
func ExportComponents[C Component](pool *ComponentPool, core Still, All ComponentAllFunc) []C {
func ExportAll[C Component](pool *Pool, core Still, All AllFunc) []C {
pool.init()
return lazy.ExportComponents[Component, Still, C](&pool.pool, core, All)
}
// ExportComponent exports the first component that is a C from the pool.
// Export exports the first component that is a C from the pool.
//
// All should be the function of the core that initializes all components.
// All should only make calls to [InitComponent].
func ExportComponent[C Component](pool *ComponentPool, core Still, All ComponentAllFunc) C {
func Export[C Component](pool *Pool, core Still, All AllFunc) C {
pool.init()
return lazy.ExportComponent[Component, Still, C](&pool.pool, core, All)
}

View file

@ -4,7 +4,7 @@ import (
"github.com/FAU-CDI/wisski-distillery/internal/models"
)
// Provisionable represents a component with a Provision and a Purge method.
// Provisionable is a component that can be provisioned
type Provisionable interface {
Component

View file

@ -16,7 +16,7 @@ import (
)
type Resolver struct {
component.ComponentBase
component.Base
Instances *instances.Instances

View file

@ -7,7 +7,7 @@ import (
"github.com/tkw1536/goprogram/stream"
)
// Servable implements a component with a Serve method
// Servable is a component that is servable
type Servable interface {
Component

View file

@ -12,7 +12,7 @@ import (
)
type SQL struct {
component.ComponentBase
component.Base
ServerURL string // upstream server url

View file

@ -9,7 +9,7 @@ import (
)
type SSH struct {
component.ComponentBase
component.Base
}
func (ssh *SSH) Path() string {

View file

@ -12,7 +12,7 @@ import (
)
type Static struct {
component.ComponentBase
component.Base
}
func (*Static) Routes() []string { return []string{"/static/"} }

View file

@ -1,36 +0,0 @@
package component
import (
"reflect"
"strings"
"github.com/FAU-CDI/wisski-distillery/internal/config"
"github.com/FAU-CDI/wisski-distillery/pkg/environment"
)
// ComponentBase is embedded into every Component
type ComponentBase struct {
name string // name is the name of this component
Still // the underlying still of the distillery
}
//lint:ignore U1000 used to implement the private methods of [Component]
func (cb *ComponentBase) getComponentBase() *ComponentBase {
return cb
}
func (cb ComponentBase) Name() string {
return cb.name
}
// nameOf returns the name of the given component
func nameOf(component Component) string {
return strings.ToLower(reflect.TypeOf(component).Elem().Name())
}
// Still represents the central part of a distillery.
// It is used inside the main distillery struct, as well as every component via [ComponentBase].
type Still struct {
Environment environment.Environment // environment to use for reading / writing to and from the distillery
Config *config.Config // the configuration of the distillery
}

View file

@ -11,7 +11,7 @@ import (
)
type Triplestore struct {
component.ComponentBase
component.Base
BaseURL string // upstream server url

View file

@ -12,7 +12,7 @@ import (
//
// It consists of an nginx docker container and an optional letsencrypt container.
type Web struct {
component.ComponentBase
component.Base
}
func (web *Web) Path() string {

View file

@ -22,7 +22,7 @@ import (
)
// register returns all components of the distillery
func (dis *Distillery) register(context component.ComponentPoolContext) []component.Component {
func (dis *Distillery) register(context component.PoolContext) []component.Component {
return collection.MapSlice([]initFunc{
auto[*web.Web],
@ -65,16 +65,16 @@ func (dis *Distillery) register(context component.ComponentPoolContext) []compon
})
}
type initFunc = func(dis *Distillery, context component.ComponentPoolContext) component.Component
type initFunc = func(dis *Distillery, context component.PoolContext) component.Component
// manual initializes a component from the provided distillery.
func manual[C component.Component](init func(component C)) initFunc {
return func(dis *Distillery, context component.ComponentPoolContext) component.Component {
return component.MakeComponent(context, dis.Still, init)
return func(dis *Distillery, context component.PoolContext) component.Component {
return component.Make(context, dis.Still, init)
}
}
// use is like r, but does not provided additional initialization
func auto[C component.Component](dis *Distillery, context component.ComponentPoolContext) component.Component {
return component.MakeComponent[C](context, dis.Still, nil)
func auto[C component.Component](dis *Distillery, context component.PoolContext) component.Component {
return component.Make[C](context, dis.Still, nil)
}

View file

@ -32,7 +32,7 @@ type Distillery struct {
Upstream Upstream
// Pool holds all the components in this pool
pool component.ComponentPool
pool component.Pool
}
// Upstream contains the configuration for accessing remote configuration.
@ -52,7 +52,7 @@ func (dis *Distillery) Context() context.Context {
// e is a convenience function to export a single component
func e[C component.Component](dis *Distillery) C {
return component.ExportComponent[C](
return component.Export[C](
&dis.pool,
dis.Still,
dis.register,
@ -60,7 +60,7 @@ func e[C component.Component](dis *Distillery) C {
}
func ea[C component.Component](dis *Distillery) []C {
return component.ExportComponents[C](
return component.ExportAll[C](
&dis.pool,
dis.Still,
dis.register,

1
internal/dis/pool.go Normal file
View file

@ -0,0 +1 @@
package dis