117 lines
2.1 KiB
Go
117 lines
2.1 KiB
Go
package deployers
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"gitea.thegux.fr/hmdeploy/models"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
var ErrContextDone = errors.New("unable to execute, context done")
|
|
|
|
type IDeployer interface {
|
|
Type() DeployerType
|
|
Deploy() error
|
|
Build() error
|
|
Clear() error
|
|
Error() error
|
|
Done() <-chan struct{}
|
|
}
|
|
|
|
type DeployerType string
|
|
|
|
const (
|
|
Nginx DeployerType = "nginx"
|
|
Swarm DeployerType = "swarm"
|
|
|
|
GracefulTimeout = 10 * time.Second
|
|
)
|
|
|
|
type deployer struct {
|
|
ctx context.Context
|
|
fnCancel context.CancelFunc
|
|
|
|
type_ DeployerType
|
|
project *models.Project
|
|
|
|
processing atomic.Bool
|
|
chDone chan struct{}
|
|
errFlag error
|
|
}
|
|
|
|
func newDeployer(ctx context.Context, type_ DeployerType, project *models.Project) *deployer {
|
|
d := &deployer{
|
|
ctx: ctx,
|
|
type_: type_,
|
|
project: project,
|
|
processing: atomic.Bool{},
|
|
chDone: make(chan struct{}, 1),
|
|
}
|
|
|
|
d.processing.Store(false)
|
|
return d
|
|
}
|
|
|
|
func (d *deployer) setDone(err error) {
|
|
d.chDone <- struct{}{}
|
|
d.errFlag = err
|
|
if err != nil && d.fnCancel != nil {
|
|
d.fnCancel()
|
|
}
|
|
}
|
|
|
|
func (d *deployer) SetCancellationFunc(fnCancel context.CancelFunc) {
|
|
d.fnCancel = fnCancel
|
|
}
|
|
|
|
func (d *deployer) Type() DeployerType {
|
|
return d.type_
|
|
}
|
|
|
|
func (d *deployer) Error() error {
|
|
return d.errFlag
|
|
}
|
|
|
|
func (d *deployer) Done() <-chan struct{} {
|
|
chDone := make(chan struct{})
|
|
go func() {
|
|
defer func() {
|
|
close(chDone)
|
|
}()
|
|
|
|
for {
|
|
select {
|
|
case <-d.ctx.Done():
|
|
log.Warn().Str("deployer", string(d.type_)).Msg("context done catch")
|
|
|
|
timeout := time.NewTicker(GracefulTimeout)
|
|
tick := time.NewTicker(time.Second)
|
|
for {
|
|
select {
|
|
case <-timeout.C:
|
|
log.Error().
|
|
Str("deployer", string(d.type_)).
|
|
Msg("timeout while waiting for graceful shutdown")
|
|
chDone <- struct{}{}
|
|
return
|
|
case <-tick.C:
|
|
if !d.processing.Load() {
|
|
chDone <- struct{}{}
|
|
return
|
|
}
|
|
tick.Reset(1 * time.Second)
|
|
}
|
|
}
|
|
case <-d.chDone:
|
|
log.Info().Str("deployer", string(d.type_)).Msg("terminated")
|
|
chDone <- struct{}{}
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
return chDone
|
|
}
|