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  }