gevent imply go-event which tries to make event handling easier.
What does gevent want to do
- Async execute jobs safely without too many go routines.
- Support delayed events to execute.
- Support to config executing options
Main usage scenarios:
- Separate side business from main, like system log which should be async.
- Use delayed event to confirm order status or pay status.
- Decouple domain events to avoid cycling call.
- Notify downstream while domain event happening.
Attention
- Instant event may delay a few milliseconds while dispatching.
- Local events are not durable, use redis durable model for distribute systems.
TODO
- Support use rmq etc.
- Benchmark
Any question or suggestion, please let me know.
How to use:
go get github.com/ltwonders/gevent
Example:
package main
import (
"context"
"log"
"time"
"github.com/alicebob/miniredis"
"github.com/gomodule/redigo/redis"
"github.com/ltwonders/gevent"
)
func main() {
ctx := context.Background()
gevent.LocalInit()
s, err0 := miniredis.Run()
if err0 != nil {
panic(err0)
}
defer s.Close()
pool := &redis.Pool{
MaxIdle: 2,
Dial: func() (redis.Conn, error) { return redis.Dial("tcp", s.Addr()) },
}
redisDispatcher := gevent.NewRedisWithContext(ctx, &gevent.ClientSimple{Pool: pool})
//annoy func to handle event
var annoyFunc = func(ctx context.Context, evt gevent.Event) error {
log.Printf("instant event [%+v] start at %+v", evt, time.Now().Second())
time.Sleep(2 * time.Second)
log.Printf("instant event [%+v] finish at %+v", evt, time.Now().Second())
return nil
}
if err1 := gevent.Local().Register(ctx, "instant", annoyFunc); nil != err1 {
log.Printf("fail to register local handler")
}
type instantEvent struct {
ID int
}
// dispatch events
for i := 1; i <= 100; i++ {
inst := &instantEvent{ID: i}
if err := gevent.Dispatch(ctx, "instant", inst, gevent.Local(), redisDispatcher); nil != err {
log.Printf("dispatch failed: %s", err)
}
}
if err2 := redisDispatcher.Register(ctx, "instant", annoyFunc); nil != err2 {
log.Printf("fail to register redis handler")
}
time.Sleep(200 * time.Second)
}
more examples, see example package