vindicator
vindicator copied to clipboard
Vindicator is a lightweight Golang library that is designed to hold and check any blocking function. e.g. subprocess, network connection...
Vindicator
Vindicator is a lightweight Golang library that is designed to hold and check any blocking function, e.g. subprocess, network connection...
Contents
- Installation
- Quick Start
- API Reference
- Vindicator
- Worker Interface
- Event
- FAQ
- Contributing
- License
Installation
go get -u github.com/phith0n/vindicator
Quick Start
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) errorthis 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() boolthis 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.
API Reference
Vindicator Struct
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.
Worker Interface
type Worker interface {
Work(ctx context.Context) error // the worker() must be a blocking function
GetRunning() bool
SetRunning(bool)
}
Event
There are several events that you can listen and execute custom callback functions:
monitor:starttrigger when monitor is startedmonitor:stoptrigger when monitor is stopped manualmonitor:interrupttrigger when monitor is stopped unexpectedmonitor:workingtrigger when monitor works at cycle runworker:starttrigger when worker is startedworker:stoptrigger when worker is stoppedworker:errortrigger 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) {
// ...
}
FAQ
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.
Contributing
If you'd like to help out with the project. You can put up a Pull Request.
License
The Vindicator is open-sourced software licensed under the MIT License.