github.com/chain5j/chain5j-pkg@v1.0.7/eventbus/client.go (about) 1 package EventBus 2 3 import ( 4 "errors" 5 "fmt" 6 "net" 7 "net/http" 8 "net/rpc" 9 "sync" 10 ) 11 12 const ( 13 // PublishService - Client service method 14 PublishService = "ClientService.PushEvent" 15 ) 16 17 // ClientArg - object containing event for client to publish locally 18 type ClientArg struct { 19 Args []interface{} 20 Topic string 21 } 22 23 // Client - object capable of subscribing to a remote event bus 24 type Client struct { 25 eventBus Bus 26 address string 27 path string 28 service *ClientService 29 } 30 31 // NewClient - create a client object with the address and server path 32 func NewClient(address, path string, eventBus Bus) *Client { 33 client := new(Client) 34 client.eventBus = eventBus 35 client.address = address 36 client.path = path 37 client.service = &ClientService{client, &sync.WaitGroup{}, false} 38 return client 39 } 40 41 // EventBus - returns the underlying event bus 42 func (client *Client) EventBus() Bus { 43 return client.eventBus 44 } 45 46 func (client *Client) doSubscribe(topic string, fn interface{}, serverAddr, serverPath string, subscribeType SubscribeType) { 47 defer func() { 48 if r := recover(); r != nil { 49 fmt.Println("Server not found -", r) 50 } 51 }() 52 53 rpcClient, err := rpc.DialHTTPPath("tcp", serverAddr, serverPath) 54 defer rpcClient.Close() 55 if err != nil { 56 fmt.Errorf("dialing: %v", err) 57 } 58 args := &SubscribeArg{client.address, client.path, PublishService, subscribeType, topic} 59 reply := new(bool) 60 err = rpcClient.Call(RegisterService, args, reply) 61 if err != nil { 62 fmt.Errorf("Register error: %v", err) 63 } 64 if *reply { 65 client.eventBus.Subscribe(topic, fn) 66 } 67 } 68 69 //Subscribe subscribes to a topic in a remote event bus 70 func (client *Client) Subscribe(topic string, fn interface{}, serverAddr, serverPath string) { 71 client.doSubscribe(topic, fn, serverAddr, serverPath, Subscribe) 72 } 73 74 //SubscribeOnce subscribes once to a topic in a remote event bus 75 func (client *Client) SubscribeOnce(topic string, fn interface{}, serverAddr, serverPath string) { 76 client.doSubscribe(topic, fn, serverAddr, serverPath, SubscribeOnce) 77 } 78 79 // Start - starts the client service to listen to remote events 80 func (client *Client) Start() error { 81 var err error 82 service := client.service 83 if !service.started { 84 server := rpc.NewServer() 85 server.Register(service) 86 server.HandleHTTP(client.path, "/debug"+client.path) 87 l, err := net.Listen("tcp", client.address) 88 if err == nil { 89 service.wg.Add(1) 90 service.started = true 91 go http.Serve(l, nil) 92 } 93 } else { 94 err = errors.New("Client service already started") 95 } 96 return err 97 } 98 99 // Stop - signal for the service to stop serving 100 func (client *Client) Stop() { 101 service := client.service 102 if service.started { 103 service.wg.Done() 104 service.started = false 105 } 106 } 107 108 // ClientService - service object listening to events published in a remote event bus 109 type ClientService struct { 110 client *Client 111 wg *sync.WaitGroup 112 started bool 113 } 114 115 // PushEvent - exported service to listening to remote events 116 func (service *ClientService) PushEvent(arg *ClientArg, reply *bool) error { 117 service.client.eventBus.Publish(arg.Topic, arg.Args...) 118 *reply = true 119 return nil 120 }