Environment can now run RunShutdownable actors
This commit is contained in:
parent
dc7c7b5c73
commit
326db33ecc
@ -122,7 +122,9 @@ func (this *environment) Add(ctx context.Context, actors ...Actor) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, actor := range actors {
|
for _, actor := range actors {
|
||||||
if actor, ok := actor.(Runnable); ok {
|
_, isRunnable := actor.(Runnable)
|
||||||
|
_, isRunShutdownable := actor.(RunShutdownable)
|
||||||
|
if isRunnable || isRunShutdownable {
|
||||||
this.start(actor)
|
this.start(actor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,7 +215,7 @@ func (this *environment) info(actor Actor) actorInfo {
|
|||||||
// start increments the wait group by one and starts the given actor in the
|
// start increments the wait group by one and starts the given actor in the
|
||||||
// background, restarting it if it fails. this function will exit immediately.
|
// background, restarting it if it fails. this function will exit immediately.
|
||||||
// see the documentation for run for details.
|
// see the documentation for run for details.
|
||||||
func (this *environment) start(actor Runnable) {
|
func (this *environment) start(actor Actor) {
|
||||||
this.group.Add(1)
|
this.group.Add(1)
|
||||||
go this.run(actor)
|
go this.run(actor)
|
||||||
}
|
}
|
||||||
@ -223,14 +225,12 @@ func (this *environment) start(actor Runnable) {
|
|||||||
// environment once this function exits, and the environment's wait group
|
// environment once this function exits, and the environment's wait group
|
||||||
// counter will be decremented. note that this function will never increment the
|
// counter will be decremented. note that this function will never increment the
|
||||||
// wait group counter, so start should usually be used instead.
|
// wait group counter, so start should usually be used instead.
|
||||||
func (this *environment) run(actor Runnable) {
|
func (this *environment) run(actor Actor) {
|
||||||
// clean up when done
|
// clean up when done
|
||||||
defer this.group.Done()
|
defer this.group.Done()
|
||||||
|
|
||||||
// logging
|
// logging
|
||||||
acto, ok := actor.(Actor)
|
typ := actor.Type()
|
||||||
if !ok { return }
|
|
||||||
typ := acto.Type()
|
|
||||||
if this.Verb() { log.Printf("(i) [%s] running", typ) }
|
if this.Verb() { log.Printf("(i) [%s] running", typ) }
|
||||||
var stopErr error
|
var stopErr error
|
||||||
var exited bool
|
var exited bool
|
||||||
@ -247,10 +247,26 @@ func (this *environment) run(actor Runnable) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// contains context information
|
// contains context information
|
||||||
info := this.info(acto)
|
info := this.info(actor)
|
||||||
ctx := info.ctx
|
ctx := info.ctx
|
||||||
defer close(info.stopped)
|
defer close(info.stopped)
|
||||||
|
|
||||||
|
switch actor := actor.(type) {
|
||||||
|
case Runnable:
|
||||||
|
stopErr, exited = this.runRunnable(ctx, actor)
|
||||||
|
case RunShutdownable:
|
||||||
|
stopErr, exited = this.runRunnable(ctx, &runShutdownableShim {
|
||||||
|
shutdownTimeout: defaul(this.timing.shutdownTimeout.Load(), defaultShutdownTimeout),
|
||||||
|
underlying: actor,
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
panic("actor was neither Runnable or RunShutdownable")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// runRunnable runs an actor implementing [Runnable]. this should only be called
|
||||||
|
// from within [environment.run].
|
||||||
|
func (this *environment) runRunnable(ctx context.Context, actor Runnable) (stopErr error, exited bool) {
|
||||||
// timing
|
// timing
|
||||||
restartThreshold := defaul(this.timing.restartThreshold.Load(), defaultRestartThreshold)
|
restartThreshold := defaul(this.timing.restartThreshold.Load(), defaultRestartThreshold)
|
||||||
restartInitialInterval := defaul(this.timing.restartInitialInterval.Load(), defaultRestartInitialInterval)
|
restartInitialInterval := defaul(this.timing.restartInitialInterval.Load(), defaultRestartInitialInterval)
|
||||||
@ -259,11 +275,14 @@ func (this *environment) run(actor Runnable) {
|
|||||||
resetTimeout := defaul(this.timing.resetTimeout.Load(), defaultResetTimeout)
|
resetTimeout := defaul(this.timing.resetTimeout.Load(), defaultResetTimeout)
|
||||||
restartInterval := restartInitialInterval
|
restartInterval := restartInitialInterval
|
||||||
|
|
||||||
// main loop
|
acto, ok := actor.(Actor)
|
||||||
|
if !ok { return }
|
||||||
|
typ := acto.Type()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// run actor
|
// run actor
|
||||||
lastStart := time.Now()
|
lastStart := time.Now()
|
||||||
err := panicWrap(ctx, actor.Run)
|
err := panicWrapCtx(ctx, actor.Run)
|
||||||
|
|
||||||
// detect context cancellation
|
// detect context cancellation
|
||||||
if ctxErr := ctx.Err(); ctxErr != nil {
|
if ctxErr := ctx.Err(); ctxErr != nil {
|
||||||
@ -387,3 +406,24 @@ func (this *environment) applyConfig() error {
|
|||||||
if err != nil { return err }
|
if err != nil { return err }
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type runShutdownableShim struct {
|
||||||
|
underlying RunShutdownable
|
||||||
|
shutdownTimeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *runShutdownableShim) Type() string {
|
||||||
|
return this.underlying.(Actor).Type()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *runShutdownableShim) Run(ctx context.Context) error {
|
||||||
|
ctx, done := context.WithCancel(ctx)
|
||||||
|
defer done()
|
||||||
|
go func() {
|
||||||
|
<- ctx.Done()
|
||||||
|
shutdownCtx, done := context.WithTimeout(context.Background(), this.shutdownTimeout)
|
||||||
|
defer done()
|
||||||
|
this.underlying.Shutdown(shutdownCtx)
|
||||||
|
}()
|
||||||
|
return this.underlying.Run()
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user