mirror of
https://github.com/siderolabs/talos.git
synced 2025-12-06 18:11:33 +01:00
Rework (and simplify) `DNSResolveCacheController` to use `DNSUpstream` "handle-like" resources. Depends on https://github.com/cosi-project/runtime/pull/400 Signed-off-by: Dmitriy Matrenichev <dmitry.matrenichev@siderolabs.com>
75 lines
1.7 KiB
Go
75 lines
1.7 KiB
Go
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
// Package utils provides various utility functions.
|
|
package utils
|
|
|
|
import (
|
|
"errors"
|
|
"sync/atomic"
|
|
)
|
|
|
|
const (
|
|
notRunning = iota
|
|
running
|
|
closing
|
|
closed
|
|
)
|
|
|
|
// Runner is a fn/stop runner.
|
|
type Runner struct {
|
|
fn func() error
|
|
stop func() error
|
|
retryStop func(error) bool
|
|
status atomic.Int64
|
|
done chan struct{}
|
|
}
|
|
|
|
// NewRunner creates a new runner.
|
|
func NewRunner(fn, stop func() error, retryStop func(error) bool) *Runner {
|
|
return &Runner{fn: fn, stop: stop, retryStop: retryStop, done: make(chan struct{})}
|
|
}
|
|
|
|
// Run runs fn.
|
|
func (r *Runner) Run() error {
|
|
defer func() {
|
|
if r.status.Swap(closed) != closed {
|
|
close(r.done)
|
|
}
|
|
}()
|
|
|
|
if !r.status.CompareAndSwap(notRunning, running) {
|
|
return ErrAlreadyRunning
|
|
}
|
|
|
|
return r.fn()
|
|
}
|
|
|
|
var (
|
|
// ErrAlreadyRunning is the error that is returned when runner is already running/closing/closed.
|
|
ErrAlreadyRunning = errors.New("runner is already running/closing/closed")
|
|
// ErrNotRunning is the error that is returned when runner is not running/closing/closed.
|
|
ErrNotRunning = errors.New("runner is not running/closing/closed")
|
|
)
|
|
|
|
// Stop stops runner. It's safe to call even if runner is already stopped or in process of being stopped.
|
|
func (r *Runner) Stop() error {
|
|
if r.status.CompareAndSwap(notRunning, closing) || !r.status.CompareAndSwap(running, closing) {
|
|
return ErrNotRunning
|
|
}
|
|
|
|
for {
|
|
err := r.stop()
|
|
if err != nil {
|
|
if r.retryStop(err) && r.status.Load() == closing {
|
|
continue
|
|
}
|
|
}
|
|
|
|
<-r.done
|
|
|
|
return err
|
|
}
|
|
}
|