WiP
Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
parent
8c62b6de8c
commit
bc470c5f78
5 changed files with 58 additions and 0 deletions
|
|
@ -5,6 +5,7 @@ import "time"
|
||||||
// TODO(gabriel-samfira): needs owner attribute.
|
// TODO(gabriel-samfira): needs owner attribute.
|
||||||
type Locker interface {
|
type Locker interface {
|
||||||
TryLock(key string) bool
|
TryLock(key string) bool
|
||||||
|
Lock(key string)
|
||||||
Unlock(key string, remove bool)
|
Unlock(key string, remove bool)
|
||||||
Delete(key string)
|
Delete(key string)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,12 @@ func (k *keyMutex) TryLock(key string) bool {
|
||||||
return keyMux.TryLock()
|
return keyMux.TryLock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *keyMutex) Lock(key string) {
|
||||||
|
mux, _ := k.muxes.LoadOrStore(key, &sync.Mutex{})
|
||||||
|
keyMux := mux.(*sync.Mutex)
|
||||||
|
keyMux.Lock()
|
||||||
|
}
|
||||||
|
|
||||||
func (k *keyMutex) Unlock(key string, remove bool) {
|
func (k *keyMutex) Unlock(key string, remove bool) {
|
||||||
mux, ok := k.muxes.Load(key)
|
mux, ok := k.muxes.Load(key)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,15 @@ func TryLock(key string) (bool, error) {
|
||||||
|
|
||||||
return locker.TryLock(key), nil
|
return locker.TryLock(key), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Lock(key string) {
|
||||||
|
if locker == nil {
|
||||||
|
panic("no locker is registered")
|
||||||
|
}
|
||||||
|
|
||||||
|
locker.Lock(key)
|
||||||
|
}
|
||||||
|
|
||||||
func Unlock(key string, remove bool) error {
|
func Unlock(key string, remove bool) error {
|
||||||
if locker == nil {
|
if locker == nil {
|
||||||
return fmt.Errorf("no locker is registered")
|
return fmt.Errorf("no locker is registered")
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,7 @@ func (w *Worker) Start() (err error) {
|
||||||
slog.DebugContext(w.ctx, "starting scale set worker loops", "scale_set", w.consumerID)
|
slog.DebugContext(w.ctx, "starting scale set worker loops", "scale_set", w.consumerID)
|
||||||
go w.loop()
|
go w.loop()
|
||||||
go w.keepListenerAlive()
|
go w.keepListenerAlive()
|
||||||
|
go w.handleAutoScale()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,3 +308,35 @@ func (w *Worker) keepListenerAlive() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Worker) handleAutoScale() {
|
||||||
|
ticker := time.NewTicker(5 * time.Second)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-w.quit:
|
||||||
|
return
|
||||||
|
case <-w.ctx.Done():
|
||||||
|
return
|
||||||
|
case <-ticker.C:
|
||||||
|
var desiredRunners uint
|
||||||
|
if w.scaleSet.DesiredRunnerCount > 0 {
|
||||||
|
desiredRunners = uint(w.scaleSet.DesiredRunnerCount)
|
||||||
|
}
|
||||||
|
targetRunners := min(w.scaleSet.MinIdleRunners+desiredRunners, w.scaleSet.MaxRunners)
|
||||||
|
|
||||||
|
currentRunners := uint(len(w.runners))
|
||||||
|
if currentRunners == targetRunners {
|
||||||
|
slog.DebugContext(w.ctx, "desired runner count reached", "desired_runners", targetRunners)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if currentRunners < targetRunners {
|
||||||
|
slog.DebugContext(w.ctx, "scaling up", "current_runners", currentRunners, "target_runners", targetRunners)
|
||||||
|
} else {
|
||||||
|
slog.DebugContext(w.ctx, "scaling down", "current_runners", currentRunners, "target_runners", targetRunners)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
commonParams "github.com/cloudbase/garm-provider-common/params"
|
||||||
|
|
||||||
|
"github.com/cloudbase/garm/locking"
|
||||||
"github.com/cloudbase/garm/params"
|
"github.com/cloudbase/garm/params"
|
||||||
"github.com/cloudbase/garm/util/github/scalesets"
|
"github.com/cloudbase/garm/util/github/scalesets"
|
||||||
)
|
)
|
||||||
|
|
@ -45,12 +46,16 @@ func (w *Worker) HandleJobsCompleted(jobs []params.ScaleSetJobMessage) error {
|
||||||
Status: commonParams.InstancePendingDelete,
|
Status: commonParams.InstancePendingDelete,
|
||||||
RunnerStatus: params.RunnerTerminated,
|
RunnerStatus: params.RunnerTerminated,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
locking.Lock(job.RunnerName)
|
||||||
_, err := w.store.UpdateInstance(w.ctx, job.RunnerName, runnerUpdateParams)
|
_, err := w.store.UpdateInstance(w.ctx, job.RunnerName, runnerUpdateParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
if !errors.Is(err, runnerErrors.ErrNotFound) {
|
||||||
|
locking.Unlock(job.RunnerName, false)
|
||||||
return fmt.Errorf("updating runner %s: %w", job.RunnerName, err)
|
return fmt.Errorf("updating runner %s: %w", job.RunnerName, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
locking.Unlock(job.RunnerName, false)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -68,14 +73,18 @@ func (w *Worker) HandleJobsStarted(jobs []params.ScaleSetJobMessage) error {
|
||||||
RunnerStatus: params.RunnerActive,
|
RunnerStatus: params.RunnerActive,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
locking.Lock(job.RunnerName)
|
||||||
_, err := w.store.UpdateInstance(w.ctx, job.RunnerName, updateParams)
|
_, err := w.store.UpdateInstance(w.ctx, job.RunnerName, updateParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, runnerErrors.ErrNotFound) {
|
if errors.Is(err, runnerErrors.ErrNotFound) {
|
||||||
slog.InfoContext(w.ctx, "runner not found; handled by some other controller?", "runner_name", job.RunnerName)
|
slog.InfoContext(w.ctx, "runner not found; handled by some other controller?", "runner_name", job.RunnerName)
|
||||||
|
locking.Unlock(job.RunnerName, true)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
locking.Unlock(job.RunnerName, false)
|
||||||
return fmt.Errorf("updating runner %s: %w", job.RunnerName, err)
|
return fmt.Errorf("updating runner %s: %w", job.RunnerName, err)
|
||||||
}
|
}
|
||||||
|
locking.Unlock(job.RunnerName, false)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue