github.com/vmware/transport-go@v1.3.4/plank/services/simple-stream-service.go (about) 1 // Copyright 2019-2021 VMware, Inc. 2 // SPDX-License-Identifier: BSD-2-Clause 3 4 package services 5 6 import ( 7 "github.com/google/uuid" 8 "github.com/robfig/cron/v3" 9 "github.com/vmware/transport-go/model" 10 "github.com/vmware/transport-go/plank/utils" 11 "github.com/vmware/transport-go/service" 12 "math/rand" 13 "reflect" 14 ) 15 16 const ( 17 SimpleStreamServiceChannel = "simple-stream" 18 ) 19 20 // SimpleStreamService broadcasts a simple random word as a string every 1s on channel simple-stream 21 // It does not accept any commands and is not listening for them, so there is no point in trying to talk to it. 22 // It will only broadcast, you can't stop it and it won't be stopped :) 23 type SimpleStreamService struct { 24 words []string // this is a list of random words. 25 fabricCore service.FabricServiceCore // reference to the fabric core infrastructure we will need later on. 26 readyChan chan bool // once we're ready, let plank know about it. 27 cronJob *cron.Cron // cronjob that runs every 1s. 28 } 29 30 // NewSimpleStreamService will return a new instance of the SimpleStreamService. 31 func NewSimpleStreamService() *SimpleStreamService { 32 return &SimpleStreamService{} 33 } 34 35 // Init will fire when the service is being registered by the fabric, it passes a reference of the same core 36 // Passed through when implementing HandleServiceRequest 37 func (sss *SimpleStreamService) Init(core service.FabricServiceCore) error { 38 39 // capture a reference to our fabric core infrastructure. 40 sss.fabricCore = core 41 return nil 42 } 43 44 func (sss *SimpleStreamService) HandleServiceRequest(request *model.Request, core service.FabricServiceCore) { 45 // do nothing in here, we're not listening for any requests. 46 } 47 48 // OnServiceReady will fetch a list of random words, then set up a timer to broadcast every 500ms, forever. 49 func (sss *SimpleStreamService) OnServiceReady() chan bool { 50 sss.readyChan = make(chan bool, 1) 51 sss.fetchRandomWords() 52 return sss.readyChan 53 } 54 55 // fetchRandomWords will call a public endpoint that very kindly returns random words. 56 func (sss *SimpleStreamService) fetchRandomWords() { 57 58 restRequest := &service.RestServiceRequest{ 59 Uri: "https://random-word-api.herokuapp.com/word?number=500", 60 Method: "GET", 61 ResponseType: reflect.TypeOf(sss.words), 62 } 63 64 // use the in-build REST Service to make this easy. 65 sss.fabricCore.RestServiceRequest(restRequest, sss.handleWordFetchSuccess, sss.handleWordFetchFailure) 66 } 67 68 // handleWordFetchSuccess will parse a successful incoming word response from our API. 69 func (sss *SimpleStreamService) handleWordFetchSuccess(response *model.Response) { 70 sss.words = response.Payload.([]string) 71 sss.fireRandomWords() 72 sss.readyChan <- true 73 } 74 75 // handleWordFetchFailure will parse a failed random word API request. 76 func (sss *SimpleStreamService) handleWordFetchFailure(response *model.Response) { 77 utils.Log.Info(response.Payload) 78 // we have no data, so make something up 79 sss.words = []string{"cake", "pizza", "tree", "bunny", "api-failed", "sorry", "rocket", "soda", "burger", "kitty", "fox"} 80 sss.fireRandomWords() 81 sss.readyChan <- true 82 } 83 84 // fireRandomWords will send out a random word to the stream every second. 85 func (sss *SimpleStreamService) fireRandomWords() { 86 var fireMessage = func() { 87 id := uuid.New() 88 sss.fabricCore.SendResponse(&model.Request{Id: &id}, sss.getRandomWord()) 89 } 90 sss.cronJob = cron.New() 91 sss.cronJob.AddFunc("@every 1s", fireMessage) 92 sss.cronJob.Start() 93 } 94 95 // OnServerShutdown will stop the cronjob firing. 96 func (sss *SimpleStreamService) OnServerShutdown() { 97 sss.cronJob.Stop() 98 } 99 100 // getRandomWord will return a random word from the list we retrieved. 101 func (sss *SimpleStreamService) getRandomWord() string { 102 return sss.words[rand.Intn(len(sss.words)-1)] 103 } 104 105 // these lifecycle hooks are not used in this service, bowever we need them to fulfill our contract to enable the 106 // OnServiceReady lifecycle method 107 func (sss *SimpleStreamService) GetRESTBridgeConfig() []*service.RESTBridgeConfig { 108 return nil 109 }