github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/prepare/23_proto_actor/backpressure/main.go (about) 1 package main 2 3 import ( 4 "log" 5 "sync/atomic" 6 "time" 7 8 "github.com/AsynkronIT/goconsole" 9 "github.com/AsynkronIT/protoactor-go/actor" 10 "github.com/AsynkronIT/protoactor-go/mailbox" 11 ) 12 13 // sent to producer to request more work 14 type requestMoreWork struct { 15 items int 16 } 17 type requestWorkBehavior struct { 18 tokens int64 19 producer *actor.PID 20 } 21 22 func (m *requestWorkBehavior) MailboxStarted() { 23 m.requestMore() 24 } 25 func (m *requestWorkBehavior) MessagePosted(msg interface{}) { 26 27 } 28 func (m *requestWorkBehavior) MessageReceived(msg interface{}) { 29 atomic.AddInt64(&m.tokens, -1) 30 if m.tokens == 0 { 31 m.requestMore() 32 } 33 } 34 func (m *requestWorkBehavior) MailboxEmpty() { 35 } 36 37 func (m *requestWorkBehavior) requestMore() { 38 log.Println("Requesting more tokens") 39 m.tokens = 50 40 context.Send(m.producer, &requestMoreWork{items: 50}) 41 } 42 43 type producer struct { 44 requestedWork int 45 worker *actor.PID 46 } 47 48 func (p *producer) Receive(ctx actor.Context) { 49 switch msg := ctx.Message().(type) { 50 case *actor.Started: 51 // spawn our worker 52 workerProps := actor.PropsFromProducer(func() actor.Actor { return &worker{} }). 53 WithMailbox(mailbox.Bounded(30, &requestWorkBehavior{ 54 producer: ctx.Self(), 55 })) 56 p.worker = ctx.Spawn(workerProps) 57 case *requestMoreWork: 58 p.requestedWork += msg.items 59 log.Println("Producer got a new work request") 60 ctx.Send(ctx.Self(), &produce{}) 61 case *produce: 62 // produce more work 63 log.Println("Producer is producing work") 64 ctx.Send(p.worker, &work{}) 65 66 // decrease our workload and tell ourselves to produce more work 67 if p.requestedWork > 0 { 68 p.requestedWork-- 69 ctx.Send(ctx.Self(), &produce{}) 70 } 71 } 72 } 73 74 type produce struct{} 75 76 type worker struct { 77 } 78 79 func (w *worker) Receive(ctx actor.Context) { 80 switch msg := ctx.Message().(type) { 81 case *work: 82 log.Printf("Worker is working %v", msg) 83 time.Sleep(100 * time.Millisecond) 84 } 85 } 86 87 type work struct { 88 } 89 90 var context *actor.RootContext 91 92 func main() { 93 context = actor.EmptyRootContext 94 producerProps := actor.PropsFromProducer(func() actor.Actor { return &producer{} }) 95 context.Spawn(producerProps) 96 97 console.ReadLine() 98 }