example_router_test.go
1 package actor_test 2 3 import ( 4 "context" 5 "fmt" 6 "time" 7 8 "github.com/lightningnetwork/lnd/actor" 9 "github.com/lightningnetwork/lnd/fn/v2" 10 ) 11 12 // RouterGreetingMsg is a message type for the router example. 13 type RouterGreetingMsg struct { 14 actor.BaseMessage 15 Name string 16 } 17 18 // MessageType implements actor.Message. 19 func (m RouterGreetingMsg) MessageType() string { return "RouterGreetingMsg" } 20 21 // RouterGreetingResponse is a response type for the router example. 22 type RouterGreetingResponse struct { 23 Greeting string 24 HandlerID string 25 } 26 27 // ExampleRouter demonstrates creating multiple actors under the same service 28 // key and using a router to dispatch messages to them. 29 func ExampleRouter() { 30 system := actor.NewActorSystem() 31 defer system.Shutdown() 32 33 //nolint:ll 34 routerGreeterKey := actor.NewServiceKey[RouterGreetingMsg, RouterGreetingResponse]( 35 "router-greeter-service", 36 ) 37 38 // Behavior for the first greeter actor. 39 actorID1 := "router-greeter-1" 40 greeterBehavior1 := actor.NewFunctionBehavior( 41 func(ctx context.Context, 42 msg RouterGreetingMsg) fn.Result[RouterGreetingResponse] { 43 44 return fn.Ok(RouterGreetingResponse{ 45 Greeting: "Greetings, " + msg.Name + "!", 46 HandlerID: actorID1, 47 }) 48 }, 49 ) 50 _, err := routerGreeterKey.Spawn(system, actorID1, greeterBehavior1) 51 if err != nil { 52 fmt.Printf("Failed to spawn actor: %v\n", err) 53 return 54 } 55 fmt.Printf("Actor %s spawned.\n", actorID1) 56 57 // Behavior for the second greeter actor. 58 actorID2 := "router-greeter-2" 59 greeterBehavior2 := actor.NewFunctionBehavior( 60 func(ctx context.Context, 61 msg RouterGreetingMsg) fn.Result[RouterGreetingResponse] { 62 63 return fn.Ok(RouterGreetingResponse{ 64 Greeting: "Salutations, " + msg.Name + "!", 65 HandlerID: actorID2, 66 }) 67 }, 68 ) 69 _, err = routerGreeterKey.Spawn(system, actorID2, greeterBehavior2) 70 if err != nil { 71 fmt.Printf("Failed to spawn actor: %v\n", err) 72 return 73 } 74 fmt.Printf("Actor %s spawned.\n", actorID2) 75 76 // Create a router for the "router-greeter-service". 77 greeterRouter := actor.NewRouter( 78 system.Receptionist(), routerGreeterKey, 79 actor.NewRoundRobinStrategy[RouterGreetingMsg, 80 RouterGreetingResponse](), 81 system.DeadLetters(), 82 ) 83 fmt.Printf("Router %s created for service key '%s'.\n", 84 greeterRouter.ID(), "router-greeter-service") 85 86 // Send messages through the router. 87 names := []string{"Alice", "Bob", "Charlie", "David"} 88 for _, name := range names { 89 askCtx, askCancel := context.WithTimeout( 90 context.Background(), 1*time.Second, 91 ) 92 futureResponse := greeterRouter.Ask( 93 askCtx, RouterGreetingMsg{Name: name}, 94 ) 95 96 awaitCtx, awaitCancel := context.WithTimeout( 97 context.Background(), 1*time.Second, 98 ) 99 result := futureResponse.Await(awaitCtx) 100 101 result.WhenErr(func(err error) { 102 fmt.Printf("For %s: Error - %v\n", name, err) 103 }) 104 result.WhenOk(func(response RouterGreetingResponse) { 105 fmt.Printf("For %s: Received '%s' from %s\n", 106 name, response.Greeting, response.HandlerID) 107 }) 108 awaitCancel() 109 askCancel() 110 } 111 112 // Output: 113 // Actor router-greeter-1 spawned. 114 // Actor router-greeter-2 spawned. 115 // Router router(router-greeter-service) created for service key 'router-greeter-service'. 116 // For Alice: Received 'Greetings, Alice!' from router-greeter-1 117 // For Bob: Received 'Salutations, Bob!' from router-greeter-2 118 // For Charlie: Received 'Greetings, Charlie!' from router-greeter-1 119 // For David: Received 'Salutations, David!' from router-greeter-2 120 }