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 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] // StagingContext represents a context for [Backupable] and [Snapshotable]
type StagingContext interface { type StagingContext interface {
// IO returns the input output stream belonging to this backup file // 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 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] // NewStagingContext returns a new [StagingContext]
func NewStagingContext(env environment.Environment, io stream.IOStream, path string, manifest chan<- string) StagingContext { func NewStagingContext(env environment.Environment, io stream.IOStream, path string, manifest chan<- string) StagingContext {
return &stagingContext{ return &stagingContext{

View file

@ -1,20 +1,57 @@
// Package component holds the main abstraction for components. // Package component holds the main abstraction for components.
package component package component
// Component represents a logical subsystem of the distillery. import (
// Every component must embed [ComponentBase] and should be initialized using [Initialize]. "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. // 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. // By convention these are defined within their corresponding subpackage.
// This subpackage also contains all required resources. // This subpackage also contains all required resources.
//
// Components are initialized using a [Pool].
type Component interface { type Component interface {
// Name returns the name of this component // Name returns the name of this component
// Name should be implemented by the [ComponentBase] struct. // Name should be implemented by the [ComponentBase] struct.
Name() string 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 // 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. // Control represents the running control server.
type Control struct { type Control struct {
component.ComponentBase component.Base
Servables []component.Servable Servables []component.Servable
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,31 +6,27 @@ import (
"github.com/FAU-CDI/wisski-distillery/pkg/lazy" "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] pool lazy.Pool[Component, Still]
poolInit sync.Once poolInit sync.Once
} }
func (pool *ComponentPool) init() { func (pool *Pool) init() {
pool.poolInit.Do(func() { pool.poolInit.Do(func() {
pool.pool.Init = func(component Component, core Still) Component { pool.pool.Init = Init
base := component.getComponentBase()
base.Still = core
base.name = nameOf(component)
return component
}
}) })
} }
type ComponentPoolContext = *lazy.PoolContext[Component] type PoolContext = *lazy.PoolContext[Component]
type ComponentAllFunc = func(context ComponentPoolContext) []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() pool.init()
return pool.pool.All(core, 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. // Components are initialized by first calling the init function.
// Then all component-like fields of fields are filled with their appropriate components. // 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. // 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. // 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) 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 be the function of the core that initializes all components.
// All should only make calls to [InitComponent]. // 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() pool.init()
return lazy.ExportComponents[Component, Still, C](&pool.pool, core, All) 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 be the function of the core that initializes all components.
// All should only make calls to [InitComponent]. // 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() pool.init()
return lazy.ExportComponent[Component, Still, C](&pool.pool, core, All) 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" "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 { type Provisionable interface {
Component Component

View file

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

View file

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

View file

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

View file

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

View file

@ -12,7 +12,7 @@ import (
) )
type Static struct { type Static struct {
component.ComponentBase component.Base
} }
func (*Static) Routes() []string { return []string{"/static/"} } 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 { type Triplestore struct {
component.ComponentBase component.Base
BaseURL string // upstream server url BaseURL string // upstream server url

View file

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

View file

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

View file

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

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

@ -0,0 +1 @@
package dis