github.com/moleculer-go/moleculer@v0.3.3/registry/registry_test.go (about) 1 package registry_test 2 3 import ( 4 "os" 5 "sync" 6 "time" 7 8 "github.com/moleculer-go/cupaloy/v2" 9 bus "github.com/moleculer-go/goemitter" 10 "github.com/moleculer-go/moleculer" 11 "github.com/moleculer-go/moleculer/broker" 12 "github.com/moleculer-go/moleculer/transit/memory" 13 . "github.com/onsi/ginkgo" 14 . "github.com/onsi/gomega" 15 log "github.com/sirupsen/logrus" 16 ) 17 18 var logLevel = "fatal" 19 var snap = cupaloy.New(cupaloy.FailOnUpdate(os.Getenv("UPDATE_SNAPSHOTS") == "true")) 20 21 func createPrinterBroker(mem *memory.SharedMemory) broker.ServiceBroker { 22 broker := broker.New(&moleculer.Config{ 23 DiscoverNodeID: func() string { return "node_printerBroker" }, 24 LogLevel: logLevel, 25 TransporterFactory: func() interface{} { 26 transport := memory.Create(log.WithField("transport", "memory"), mem) 27 return &transport 28 }, 29 }) 30 31 broker.Publish(moleculer.ServiceSchema{ 32 Name: "printer", 33 Actions: []moleculer.Action{ 34 { 35 Name: "print", 36 Handler: func(context moleculer.Context, params moleculer.Payload) interface{} { 37 context.Logger().Info("print action invoked. params: ", params) 38 return params.Value() 39 }, 40 }, 41 }, 42 Events: []moleculer.Event{ 43 { 44 Name: "printed", 45 Handler: func(context moleculer.Context, params moleculer.Payload) { 46 context.Logger().Info("printer.printed --> ", params.Value()) 47 }, 48 }, 49 }, 50 }) 51 52 return (*broker) 53 } 54 55 func createScannerBroker(mem *memory.SharedMemory) broker.ServiceBroker { 56 broker := broker.New(&moleculer.Config{ 57 DiscoverNodeID: func() string { return "node_scannerBroker" }, 58 LogLevel: logLevel, 59 TransporterFactory: func() interface{} { 60 transport := memory.Create(log.WithField("transport", "memory"), mem) 61 return &transport 62 }, 63 }) 64 broker.Publish(moleculer.ServiceSchema{ 65 Name: "scanner", 66 Actions: []moleculer.Action{ 67 { 68 Name: "scan", 69 Handler: func(context moleculer.Context, params moleculer.Payload) interface{} { 70 context.Logger().Info("scan action invoked!") 71 72 return params.Value() 73 }, 74 }, 75 }, 76 Events: []moleculer.Event{ 77 { 78 Name: "scanned", 79 Handler: func(context moleculer.Context, params moleculer.Payload) { 80 context.Logger().Info("scanner.scanned --> ", params.Value()) 81 }, 82 }, 83 }, 84 }) 85 86 return (*broker) 87 } 88 89 func createCpuBroker(mem *memory.SharedMemory) broker.ServiceBroker { 90 broker := broker.New(&moleculer.Config{ 91 DiscoverNodeID: func() string { return "node_cpuBroker" }, 92 LogLevel: logLevel, 93 TransporterFactory: func() interface{} { 94 transport := memory.Create(log.WithField("transport", "memory"), mem) 95 return &transport 96 }, 97 }) 98 broker.Publish(moleculer.ServiceSchema{ 99 Name: "cpu", 100 Actions: []moleculer.Action{ 101 { 102 Name: "compute", 103 Handler: func(context moleculer.Context, params moleculer.Payload) interface{} { 104 context.Logger().Debug("compute action invoked!") 105 106 scanResult := <-context.Call("scanner.scan", params) 107 108 context.Logger().Debug("scanResult: ", scanResult) 109 110 printResult := <-context.Call("printer.print", scanResult) 111 112 return printResult 113 }, 114 }, 115 }, 116 }) 117 broker.Publish(moleculer.ServiceSchema{ 118 Name: "printer", 119 Actions: []moleculer.Action{ 120 { 121 Name: "print", 122 Handler: func(context moleculer.Context, params moleculer.Payload) interface{} { 123 return params.Value() 124 }, 125 }, 126 }, 127 Events: []moleculer.Event{ 128 { 129 Name: "printed", 130 Handler: func(context moleculer.Context, params moleculer.Payload) { 131 context.Logger().Info("printer.printed --> ", params.Value()) 132 }, 133 }, 134 }, 135 }) 136 return (*broker) 137 } 138 139 func hasNode(list []moleculer.Payload, nodeID string) bool { 140 for _, p := range list { 141 if p.Get("nodeID").String() == nodeID { 142 return true 143 } 144 } 145 return false 146 } 147 148 var _ = Describe("Registry", func() { 149 150 Describe("Auto discovery", func() { 151 //failed with timeout 152 It("3 brokers should auto discovery and perform local and remote Calls", func() { 153 mem := &memory.SharedMemory{} 154 printerBroker := createPrinterBroker(mem) 155 var serviceAdded, serviceRemoved []moleculer.Payload 156 events := bus.Construct() 157 addedMutex := &sync.Mutex{} 158 printerBroker.Publish(moleculer.ServiceSchema{ 159 Name: "internal-consumer", 160 Events: []moleculer.Event{ 161 moleculer.Event{ 162 Name: "$registry.service.added", 163 Handler: func(ctx moleculer.Context, params moleculer.Payload) { 164 addedMutex.Lock() 165 defer addedMutex.Unlock() 166 serviceAdded = append(serviceAdded, params) 167 go events.EmitSync("$registry.service.added", serviceAdded) 168 }, 169 }, 170 moleculer.Event{ 171 Name: "$registry.service.removed", 172 Handler: func(ctx moleculer.Context, params moleculer.Payload) { 173 serviceRemoved = append(serviceRemoved, params) 174 go events.EmitSync("$registry.service.removed", serviceRemoved) 175 }, 176 }, 177 }, 178 }) 179 onEvent := func(event string, callback func(list []moleculer.Payload, cancel func())) { 180 events.On(event, func(v ...interface{}) { 181 list := v[0].([]moleculer.Payload) 182 callback(list, func() { 183 events = bus.Construct() 184 }) 185 }) 186 } 187 188 Expect(printerBroker.LocalNode().GetID()).Should(Equal("node_printerBroker")) 189 190 scannerBroker := createScannerBroker(mem) 191 Expect(scannerBroker.LocalNode().GetID()).Should(Equal("node_scannerBroker")) 192 193 cpuBroker := createCpuBroker(mem) 194 Expect(cpuBroker.LocalNode().GetID()).Should(Equal("node_cpuBroker")) 195 196 printerBroker.Start() 197 198 printText := "TEXT TO PRINT" 199 printResult := <-printerBroker.Call("printer.print", printText) 200 Expect(printResult.Error()).Should(BeNil()) 201 Expect(printResult.Value()).Should(Equal(printText)) 202 203 scanText := "TEXT TO SCAN" 204 205 scanResult := <-printerBroker.Call("scanner.scan", printText) 206 Expect(scanResult.IsError()).Should(BeTrue()) 207 208 step := make(chan bool) 209 onEvent("$registry.service.added", func(list []moleculer.Payload, cancel func()) { 210 if hasNode(serviceAdded, "node_scannerBroker") { 211 cancel() 212 step <- true 213 } 214 }) 215 scannerBroker.Start() 216 <-step 217 218 scanResult = <-scannerBroker.Call("scanner.scan", scanText) 219 Expect(scanResult.IsError()).ShouldNot(Equal(true)) 220 Expect(scanResult.Value()).Should(Equal(scanText)) 221 222 scanResult = <-printerBroker.Call("scanner.scan", scanText) 223 Expect(scanResult.IsError()).ShouldNot(Equal(true)) 224 Expect(scanResult.Value()).Should(Equal(scanText)) 225 226 serviceAdded = []moleculer.Payload{} 227 step = make(chan bool) 228 onEvent("$registry.service.added", func(list []moleculer.Payload, cancel func()) { 229 if hasNode(serviceAdded, "node_cpuBroker") { 230 cancel() 231 step <- true 232 } 233 }) 234 cpuBroker.Start() 235 <-step 236 237 cpuBroker.WaitForActions("scanner.scan", "printer.print") 238 time.Sleep(time.Millisecond) 239 240 contentToCompute := "Some long long text ..." 241 computeResult := <-printerBroker.Call("cpu.compute", contentToCompute) 242 Expect(computeResult.Error()).Should(Succeed()) 243 Expect(computeResult.Value()).Should(Equal(contentToCompute)) 244 245 step = make(chan bool) 246 onEvent("$registry.service.removed", func(list []moleculer.Payload, cancel func()) { 247 if hasNode(serviceRemoved, "node_scannerBroker") { 248 cancel() 249 step <- true 250 } 251 }) 252 253 //stopping broker B 254 scannerBroker.Stop() 255 256 //wait services from node node_scannerBroker to be removed 257 <-step 258 259 Expect(func() { 260 <-scannerBroker.Call("scanner.scan", scanText) 261 }).Should(Panic()) //broker B is stopped ... so it should panic 262 263 }) 264 }) 265 266 Describe("Namespace", func() { 267 268 It("Services across namespaces cannos see each other", func() { 269 270 mem := &memory.SharedMemory{} 271 272 devBroker := broker.New(&moleculer.Config{ 273 DiscoverNodeID: func() string { return "node1_devBroker" }, 274 LogLevel: logLevel, 275 Namespace: "dev", 276 TransporterFactory: func() interface{} { 277 transport := memory.Create(log.WithField("transport", "memory"), mem) 278 return &transport 279 }, 280 RequestTimeout: 1 * time.Second, 281 }) 282 283 stageBroker := broker.New(&moleculer.Config{ 284 DiscoverNodeID: func() string { return "node1_stageBroker" }, 285 LogLevel: logLevel, 286 Namespace: "stage", 287 TransporterFactory: func() interface{} { 288 transport := memory.Create(log.WithField("transport", "memory"), mem) 289 return &transport 290 }, 291 RequestTimeout: 1 * time.Second, 292 }) 293 294 stage2Broker := broker.New(&moleculer.Config{ 295 DiscoverNodeID: func() string { return "node1_stage2Broker" }, 296 LogLevel: logLevel, 297 Namespace: "stage", 298 TransporterFactory: func() interface{} { 299 transport := memory.Create(log.WithField("transport", "memory"), mem) 300 return &transport 301 }, 302 RequestTimeout: 1 * time.Second, 303 }) 304 305 //alarm service - prints the alarm and return the namespace :) 306 alarmService := func(namemspace string) moleculer.ServiceSchema { 307 return moleculer.ServiceSchema{ 308 Name: "alarm", 309 Actions: []moleculer.Action{ 310 { 311 Name: "bell", 312 Handler: func(context moleculer.Context, params moleculer.Payload) interface{} { 313 context.Logger().Info("alarm.bell ringing !!! namemspace: ", namemspace) 314 return namemspace 315 }, 316 }, 317 }, 318 } 319 } 320 321 //available in the dev namespace only 322 devOnlyService := moleculer.ServiceSchema{ 323 Name: "devOnly", 324 Actions: []moleculer.Action{ 325 { 326 Name: "code", 327 Handler: func(context moleculer.Context, params moleculer.Payload) interface{} { 328 return "🧠" 329 }, 330 }, 331 }, 332 } 333 334 devBroker.Publish(alarmService("dev")) 335 devBroker.Publish(devOnlyService) 336 devBroker.Start() 337 338 stageBroker.Start() 339 stage2Broker.Publish(moleculer.ServiceSchema{ 340 Name: "stage2", 341 Actions: []moleculer.Action{ 342 { 343 Name: "where", 344 Handler: func(context moleculer.Context, params moleculer.Payload) interface{} { 345 return "🌏" 346 }, 347 }, 348 }, 349 }) 350 stage2Broker.Start() 351 352 devAlarm := <-devBroker.Call("alarm.bell", nil) 353 Expect(devAlarm.IsError()).Should(BeFalse()) 354 Expect(devAlarm.String()).Should(Equal("dev")) 355 356 code := <-devBroker.Call("devOnly.code", nil) 357 Expect(code.IsError()).Should(BeFalse()) 358 Expect(code.String()).Should(Equal("🧠")) 359 360 //alarm.bell should not be accessible to the stage broker 361 stageAlarm := <-stageBroker.Call("alarm.bell", nil) 362 Expect(stageAlarm.IsError()).Should(BeTrue()) 363 Expect(stageAlarm.Error().Error()).Should(Equal("Registry - endpoint not found for actionName: alarm.bell namespace: stage")) 364 365 stageBroker.Publish(alarmService("stage")) 366 stageAlarm = <-stageBroker.Call("alarm.bell", nil) 367 Expect(stageAlarm.IsError()).Should(BeFalse()) 368 Expect(stageAlarm.String()).Should(Equal("stage")) 369 370 code = <-stageBroker.Call("good.code", nil) 371 Expect(code.IsError()).Should(BeTrue()) 372 Expect(code.Error().Error()).Should(Equal("Registry - endpoint not found for actionName: good.code namespace: stage")) 373 374 time.Sleep(time.Second) 375 //make sure 2 brokers on the same namespace can talk to each other 376 msg := <-stageBroker.Call("stage2.where", nil) 377 Expect(msg.String()).Should(Equal("🌏")) 378 379 devBroker.Stop() 380 stageBroker.Stop() 381 stage2Broker.Stop() 382 383 }) 384 }) 385 })