hmdeploy/deployers/commons.go
2025-04-03 21:50:24 +02:00

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
}