Vindicator is a lightweight Golang library that is designed to hold and check any blocking function, e.g. subprocess, network connection...
go get -u github.com/phith0n/vindicator
You have to write a struct I call it "Worker", that implements vindicator.Worker
:
type Worker interface {
Work(ctx context.Context) error // the worker() must be a blocking function
GetRunning() bool
SetRunning(bool)
}
There are 3 functions in the Worker
interface:
Work (ctx context.Context) error
this function must be a blocking function. the monitor will start a new worker if this function exit unexpected.SetRunning(run bool)
this function should set the running status of the workerGetRunning() bool
this function should return current running status
The Work
function accepts a context object, it must control the lifecycle of your worker.
For example, if you want to start a subprocess and check it regularly if it is still running, here is the struct implement:
type ProcessWorker struct {
isRunning bool
}
// Work must be a blocking function
func (pw *ProcessWorker) Work(ctx context.Context) error {
cmd := exec.CommandContext(ctx, "sleep", "1h")
if err := cmd.Start(); err != nil {
return err
}
if err := cmd.Wait(); err != nil {
return err
}
return nil
}
func (pw *ProcessWorker) SetRunning(run bool) {
pw.isRunning = run
}
func (pw *ProcessWorker) GetRunning() bool {
return pw.isRunning
}
Then, use Vindicator
to start and monitor the ProcessWorker
:
ctx := context.Background()
worker := ProcessWorker{}
v := vindicator.NewVindicator(&worker, 2)
// you can use event listener to execute some callback function
v.On("monitor:start", func(v *vindicator.Vindicator, args ...interface{}) {
fmt.Println("start monitor")
})
v.On("monitor:working", func (v *vindicator.Vindicator, args ...interface{}) {
fmt.Println("process is working normally...")
})
v.On("monitor:interrupt", func (v *vindicator.Vindicator, args ...interface{}) {
fmt.Println("process is stopped unexpected, try to restart it...")
})
v.On("monitor:stop", func (v *vindicator.Vindicator, args ...interface{}) {
fmt.Println("stop monitor")
})
v.On("worker:start", func (v *vindicator.Vindicator, args ...interface{}) {
fmt.Println("start worker")
})
v.On("worker:stop", func (v *vindicator.Vindicator, args ...interface{}) {
fmt.Println("stop worker")
})
// run worker and monitor in background
go v.Start(ctx)
go v.Monitor(ctx)
// to wait sometime...
timer := time.NewTimer(time.Second * 10)
<-timer.C
// demonstrate how to stop the worker and the monitor manual
v.Stop()
This example checks the process running status every 2 seconds, and stop it after 10 seconds.
The output:
start worker
start monitor
process is working normally...
process is working normally...
process is working normally...
process is working normally...
process is working normally...
stop monitor
stop worker
The full example code you can find here.
Create a new Vindicator
:
v := vindicator.NewVindicator(&worker, 2)
The first argument is your custom Worker
implements, the second argument is the monitor cycle time by seconds.
type Worker interface {
Work(ctx context.Context) error // the worker() must be a blocking function
GetRunning() bool
SetRunning(bool)
}
There are several events that you can listen and execute custom callback functions:
monitor:start
trigger when monitor is startedmonitor:stop
trigger when monitor is stopped manualmonitor:interrupt
trigger when monitor is stopped unexpectedmonitor:working
trigger when monitor works at cycle runworker:start
trigger when worker is startedworker:stop
trigger when worker is stoppedworker:error
trigger when an error is raised by worker
Use Vindicator.On
to register a listener:
type VindicatorFn func(v *Vindicator, args ...interface{})
func (v *Vindicator) On(eventName string, callback VindicatorFn) {
// ...
}
When should I use this library?
You can use github.com/phith0n/vindicator when you are going to run a blocking function and maintain its status. For example, the subprocess, the TCP long connection, the Websocket connection, and any other program like these.
Is there a document for this library?
No yet. But there are only 100+ lines code for this project, you can kindly read the code and understand it by yourself.
If you'd like to help out with the project. You can put up a Pull Request.
The Vindicator is open-sourced software licensed under the MIT License.