github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/event/example_scope_test.go (about) 1 // This file is part of the go-sberex library. The go-sberex library is 2 // free software: you can redistribute it and/or modify it under the terms 3 // of the GNU Lesser General Public License as published by the Free 4 // Software Foundation, either version 3 of the License, or (at your option) 5 // any later version. 6 // 7 // The go-sberex library is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 10 // General Public License <http://www.gnu.org/licenses/> for more details. 11 12 package event_test 13 14 import ( 15 "fmt" 16 "sync" 17 18 "github.com/Sberex/go-sberex/event" 19 ) 20 21 // This example demonstrates how SubscriptionScope can be used to control the lifetime of 22 // subscriptions. 23 // 24 // Our example program consists of two servers, each of which performs a calculation when 25 // requested. The servers also allow subscribing to results of all computations. 26 type divServer struct{ results event.Feed } 27 type mulServer struct{ results event.Feed } 28 29 func (s *divServer) do(a, b int) int { 30 r := a / b 31 s.results.Send(r) 32 return r 33 } 34 35 func (s *mulServer) do(a, b int) int { 36 r := a * b 37 s.results.Send(r) 38 return r 39 } 40 41 // The servers are contained in an App. The app controls the servers and exposes them 42 // through its API. 43 type App struct { 44 divServer 45 mulServer 46 scope event.SubscriptionScope 47 } 48 49 func (s *App) Calc(op byte, a, b int) int { 50 switch op { 51 case '/': 52 return s.divServer.do(a, b) 53 case '*': 54 return s.mulServer.do(a, b) 55 default: 56 panic("invalid op") 57 } 58 } 59 60 // The app's SubscribeResults method starts sending calculation results to the given 61 // channel. Subscriptions created through this method are tied to the lifetime of the App 62 // because they are registered in the scope. 63 func (s *App) SubscribeResults(op byte, ch chan<- int) event.Subscription { 64 switch op { 65 case '/': 66 return s.scope.Track(s.divServer.results.Subscribe(ch)) 67 case '*': 68 return s.scope.Track(s.mulServer.results.Subscribe(ch)) 69 default: 70 panic("invalid op") 71 } 72 } 73 74 // Stop stops the App, closing all subscriptions created through SubscribeResults. 75 func (s *App) Stop() { 76 s.scope.Close() 77 } 78 79 func ExampleSubscriptionScope() { 80 // Create the app. 81 var ( 82 app App 83 wg sync.WaitGroup 84 divs = make(chan int) 85 muls = make(chan int) 86 ) 87 88 // Run a subscriber in the background. 89 divsub := app.SubscribeResults('/', divs) 90 mulsub := app.SubscribeResults('*', muls) 91 wg.Add(1) 92 go func() { 93 defer wg.Done() 94 defer fmt.Println("subscriber exited") 95 defer divsub.Unsubscribe() 96 defer mulsub.Unsubscribe() 97 for { 98 select { 99 case result := <-divs: 100 fmt.Println("division happened:", result) 101 case result := <-muls: 102 fmt.Println("multiplication happened:", result) 103 case <-divsub.Err(): 104 return 105 case <-mulsub.Err(): 106 return 107 } 108 } 109 }() 110 111 // Interact with the app. 112 app.Calc('/', 22, 11) 113 app.Calc('*', 3, 4) 114 115 // Stop the app. This shuts down the subscriptions, causing the subscriber to exit. 116 app.Stop() 117 wg.Wait() 118 119 // Output: 120 // division happened: 2 121 // multiplication happened: 12 122 // subscriber exited 123 }