github.com/moleculer-go/moleculer@v0.3.3/transit/nats/nats_test.go (about)

     1  package nats_test
     2  
     3  import (
     4  	"os"
     5  	"time"
     6  
     7  	"github.com/moleculer-go/moleculer/payload"
     8  	"github.com/moleculer-go/moleculer/util"
     9  	. "github.com/onsi/ginkgo"
    10  	. "github.com/onsi/gomega"
    11  
    12  	"github.com/moleculer-go/moleculer"
    13  	"github.com/moleculer-go/moleculer/broker"
    14  	"github.com/moleculer-go/moleculer/context"
    15  	"github.com/moleculer-go/moleculer/serializer"
    16  	"github.com/moleculer-go/moleculer/transit/nats"
    17  )
    18  
    19  func natsTestHost() string {
    20  	env := os.Getenv("NATS_HOST")
    21  	if env == "" {
    22  		return "localhost"
    23  	}
    24  	return env
    25  }
    26  
    27  var NatsTestHost = natsTestHost()
    28  
    29  var _ = Describe("NATS Streaming Transit", func() {
    30  	//log.SetLevel(log.TraceLevel)
    31  	brokerDelegates := BrokerDelegates()
    32  	contextA := context.BrokerContext(brokerDelegates)
    33  	url := "nats://" + NatsTestHost + ":4222"
    34  
    35  	stringSize := 50
    36  	arraySize := 100
    37  	var longList []interface{}
    38  	for i := 0; i < arraySize; i++ {
    39  		randomString := util.RandomString(stringSize)
    40  		longList = append(longList, randomString)
    41  	}
    42  
    43  	Describe("Remote Calls", func() {
    44  		logLevel := "fatal"
    45  		transporter := "nats://" + NatsTestHost + ":4222"
    46  
    47  		var userBroker, profileBroker *broker.ServiceBroker
    48  		BeforeEach(func() {
    49  
    50  			userBroker = broker.New(&moleculer.Config{
    51  				LogLevel:    logLevel,
    52  				Transporter: transporter,
    53  				DiscoverNodeID: func() string {
    54  					return "user_broker"
    55  				},
    56  				RequestTimeout: time.Second,
    57  			})
    58  			userBroker.Publish(userService())
    59  
    60  			profileBroker = broker.New(&moleculer.Config{
    61  				LogLevel:    logLevel,
    62  				Transporter: transporter,
    63  				DiscoverNodeID: func() string {
    64  					return "profile_broker"
    65  				},
    66  				RequestTimeout: time.Second,
    67  			})
    68  			profileBroker.Publish(profileService())
    69  
    70  		})
    71  
    72  		It("should make a remote call from profile broker a to user broker", func() {
    73  			userBroker.Start()
    74  			profileBroker.Start()
    75  			profileBroker.WaitFor("user")
    76  			result := <-profileBroker.Call("user.update", longList)
    77  			Expect(result.Error()).Should(Succeed())
    78  			Expect(len(result.StringArray())).Should(Equal(arraySize + 1))
    79  
    80  			userBroker.Stop()
    81  			profileBroker.Stop()
    82  		})
    83  
    84  		It("should fail after brokers are stopped", func() {
    85  			userBroker.Start()
    86  			profileBroker.Start()
    87  
    88  			profileBroker.WaitFor("user")
    89  			p := (<-profileBroker.Call("user.update", longList))
    90  			Expect(p.Error()).Should(Succeed())
    91  			userBroker.Stop()
    92  
    93  			r := <-profileBroker.Call("user.update", longList)
    94  			Expect(r.IsError()).Should(BeTrue())
    95  
    96  			profileBroker.Stop()
    97  		})
    98  	})
    99  
   100  	Describe("Start / Stop Cycles.", func() {
   101  		logLevel := "error"
   102  		numberOfLoops := 5
   103  		loopNumber := 0
   104  		Measure("Creation of multiple brokers with connect/disconnect cycles running on nats transporter.", func(bench Benchmarker) {
   105  			transporter := "nats://" + NatsTestHost + ":4222"
   106  			var userBroker, contactBroker, profileBroker *broker.ServiceBroker
   107  			bench.Time("brokers creation", func() {
   108  				userBroker = broker.New(&moleculer.Config{
   109  					LogLevel:       logLevel,
   110  					Transporter:    transporter,
   111  					RequestTimeout: time.Second,
   112  				})
   113  				userBroker.Publish(userService())
   114  				userBroker.Start()
   115  
   116  				contactBroker = broker.New(&moleculer.Config{
   117  					LogLevel:       logLevel,
   118  					Transporter:    transporter,
   119  					RequestTimeout: time.Second,
   120  				})
   121  				contactBroker.Publish(contactService())
   122  				contactBroker.Start()
   123  
   124  				profileBroker = broker.New(&moleculer.Config{
   125  					LogLevel:       logLevel,
   126  					Transporter:    transporter,
   127  					RequestTimeout: time.Second,
   128  				})
   129  				profileBroker.Publish(profileService())
   130  				profileBroker.Start()
   131  
   132  				userBroker.WaitFor("contact", "profile")
   133  				contactBroker.WaitFor("user", "profile")
   134  				profileBroker.WaitFor("contact", "user")
   135  			})
   136  
   137  			bench.Time("local calls", func() {
   138  				result := <-userBroker.Call("user.update", longList)
   139  				Expect(len(result.StringArray())).Should(Equal(arraySize + 1))
   140  
   141  				result = <-contactBroker.Call("contact.update", longList)
   142  				Expect(len(result.StringArray())).Should(Equal(arraySize + 1))
   143  			})
   144  
   145  			bench.Time("5 remote calls", func() {
   146  				result := <-userBroker.Call("contact.update", longList)
   147  				Expect(len(result.StringArray())).Should(Equal(arraySize + 1))
   148  
   149  				result = <-contactBroker.Call("user.update", longList)
   150  				Expect(len(result.StringArray())).Should(Equal(arraySize + 1))
   151  
   152  				result = <-profileBroker.Call("profile.update", longList)
   153  				Expect(len(result.StringArray())).Should(Equal(arraySize + 3))
   154  
   155  				result = <-contactBroker.Call("profile.update", longList)
   156  				Expect(len(result.StringArray())).Should(Equal(arraySize + 3))
   157  
   158  				result = <-userBroker.Call("profile.update", longList)
   159  				Expect(len(result.StringArray())).Should(Equal(arraySize + 3))
   160  			})
   161  
   162  			bench.Time("stop and fail on action call", func() {
   163  				stopBrokers(userBroker)
   164  
   165  				Expect((<-contactBroker.Call("user.update", longList)).IsError()).Should(BeTrue())
   166  				Expect((<-profileBroker.Call("user.update", longList)).IsError()).Should(BeTrue())
   167  
   168  				stopBrokers(contactBroker)
   169  				Expect((<-profileBroker.Call("contact.update", longList)).IsError()).Should(BeTrue())
   170  
   171  				stopBrokers(profileBroker)
   172  				Expect(func() {
   173  					<-profileBroker.Call("profile.update", longList)
   174  				}).Should(Panic())
   175  			})
   176  
   177  			loopNumber++
   178  
   179  		}, numberOfLoops)
   180  
   181  	})
   182  
   183  	It("Should fail to connect", func() {
   184  		logger := contextA.Logger()
   185  		var serializer serializer.Serializer = serializer.CreateJSONSerializer(logger)
   186  		options := nats.NATSOptions{
   187  			URL:        "some ivalid URL",
   188  			Name:       "test-cluster",
   189  			Logger:     logger,
   190  			Serializer: serializer,
   191  			ValidateMsg: func(msg moleculer.Payload) bool {
   192  				return true
   193  			},
   194  		}
   195  		transporter := nats.CreateNatsTransporter(options)
   196  		transporter.SetPrefix("MOL")
   197  		Expect(<-transporter.Connect()).ShouldNot(Succeed())
   198  	})
   199  
   200  	It("Should not fail on double disconnect", func() {
   201  		logger := contextA.Logger()
   202  		var serializer serializer.Serializer = serializer.CreateJSONSerializer(logger)
   203  		options := nats.NATSOptions{
   204  			URL:        url,
   205  			Name:       "test-cluster",
   206  			Logger:     logger,
   207  			Serializer: serializer,
   208  			ValidateMsg: func(msg moleculer.Payload) bool {
   209  				return true
   210  			},
   211  		}
   212  		transporter := nats.CreateNatsTransporter(options)
   213  		transporter.SetPrefix("MOL")
   214  		Expect(<-transporter.Connect()).Should(Succeed())
   215  		Expect(<-transporter.Disconnect()).Should(Succeed())
   216  		Expect(<-transporter.Disconnect()).Should(Succeed())
   217  	})
   218  
   219  	It("Should fail Subscribe() and Publish() when is not connected", func() {
   220  		transporter := nats.CreateNatsTransporter(nats.NATSOptions{})
   221  		Expect(func() { transporter.Subscribe("", "", func(moleculer.Payload) {}) }).Should(Panic())
   222  		Expect(func() { transporter.Publish("", "", payload.Empty()) }).Should(Panic())
   223  	})
   224  
   225  	It("Should connect, subscribe, publish and disconnect", func() {
   226  		logger := contextA.Logger()
   227  		var serializer serializer.Serializer = serializer.CreateJSONSerializer(logger)
   228  		options := nats.NATSOptions{
   229  			URL:        url,
   230  			Name:       "test-cluster",
   231  			Logger:     logger,
   232  			Serializer: serializer,
   233  			ValidateMsg: func(msg moleculer.Payload) bool {
   234  				return true
   235  			},
   236  		}
   237  
   238  		params := map[string]string{
   239  			"name":     "John",
   240  			"lastName": "Snow",
   241  		}
   242  
   243  		actionName := "some.service.action"
   244  		actionContext := contextA.ChildActionContext(actionName, payload.New(params))
   245  
   246  		transporter := nats.CreateNatsTransporter(options)
   247  		transporter.SetPrefix("MOL")
   248  		Expect(<-transporter.Connect()).Should(Succeed())
   249  
   250  		received := make(chan bool)
   251  		transporter.Subscribe("topicA", "node1", func(message moleculer.Payload) {
   252  
   253  			contextMap := serializer.PayloadToContextMap(message)
   254  
   255  			newContext := context.ActionContext(brokerDelegates, contextMap)
   256  			Expect(newContext.ActionName()).Should(Equal(actionName))
   257  			contextParams := newContext.Payload()
   258  			Expect(contextParams.Get("name").String()).Should(Equal("John"))
   259  			Expect(contextParams.Get("lastName").String()).Should(Equal("Snow"))
   260  
   261  			received <- true
   262  		})
   263  
   264  		contextMap := actionContext.AsMap()
   265  		contextMap["sender"] = "someone"
   266  
   267  		msg, _ := serializer.MapToPayload(&contextMap)
   268  
   269  		transporter.Publish("topicA", "node1", msg)
   270  
   271  		Expect(<-received).Should(Equal(true))
   272  
   273  		Expect(<-transporter.Disconnect()).Should(Succeed())
   274  
   275  	})
   276  
   277  })