Add a base daemon structure
This commit is contained in:
parent
065e4f936b
commit
318d29bdd6
84
daemon.go
84
daemon.go
|
@ -1,5 +1,14 @@
|
|||
package uberdaemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"log"
|
||||
)
|
||||
|
||||
// Daemon is the interface that contains a set of methods required to be
|
||||
// implemented in order to be treated as a daemon.
|
||||
type Daemon interface {
|
||||
|
@ -32,3 +41,78 @@ type Daemon interface {
|
|||
base() *BaseDaemon
|
||||
}
|
||||
|
||||
// Actor is a function that could be executed by daemon workers.
|
||||
type Actor func()
|
||||
|
||||
// BaseDaemon is the parent structure for all daemons.
|
||||
type BaseDaemon struct {
|
||||
self Daemon
|
||||
name string
|
||||
stats *statistics
|
||||
enqueue func(*task)
|
||||
panicHandler func()
|
||||
shutdown chan struct{}
|
||||
}
|
||||
|
||||
// Process creates a task and then adds it to processing queue.
|
||||
func (b *BaseDaemon) Process(a Actor) {
|
||||
b.enqueue(&task{
|
||||
daemon: b.self,
|
||||
actor: a,
|
||||
createdAt: time.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
// HandlePanics sets up a panic handler function for the daemon.
|
||||
func (b *BaseDaemon) HandlePanics(f func()) {
|
||||
b.panicHandler = f
|
||||
}
|
||||
|
||||
// ShutdownRequested returns a channel that is closed the moment daemon shutdown
|
||||
// is requested.
|
||||
func (b *BaseDaemon) ShutdownRequested() <-chan struct{} {
|
||||
return b.shutdown
|
||||
}
|
||||
|
||||
// ShouldShutdown returns true if daemon should shutdown and false otherwise.
|
||||
func (b *BaseDaemon) ShouldShutdown() bool {
|
||||
return b.shutdown == nil
|
||||
}
|
||||
|
||||
// String returns the name of the Deamon unerlying struct.
|
||||
func (b *BaseDaemon) String() string {
|
||||
if b.name == "" {
|
||||
b.name = strings.Split(fmt.Sprintf("%T", b.self), ".")[1]
|
||||
}
|
||||
|
||||
return b.name
|
||||
}
|
||||
|
||||
// initialize saves a reference to the child daemon which is then used to print
|
||||
// the daemons' name. It also initializes other struct fields.
|
||||
func (b *BaseDaemon) initialize(self Daemon, enqueue func(*task)) {
|
||||
b.self = self
|
||||
b.stats = newStatistics()
|
||||
b.enqueue = enqueue
|
||||
b.shutdown = make(chan struct{})
|
||||
}
|
||||
|
||||
// base is a (hack) function that allows the Daemon interface to reference
|
||||
// underlying BaseDaemon structure.
|
||||
func (b *BaseDaemon) base() *BaseDaemon {
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *BaseDaemon) handlePanic() {
|
||||
if err := recover(); err != nil {
|
||||
b.stats.registerError()
|
||||
|
||||
trace := make([]byte, 1024)
|
||||
runtime.Stack(trace, false)
|
||||
|
||||
if b.panicHandler != nil {
|
||||
b.panicHandler()
|
||||
}
|
||||
log.Printf("Daemon %s recovered from panic. Error: %v\n%s\n", b, err, trace)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue