55 "crypto/ed25519"
66 "encoding/hex"
77 "fmt"
8+ "slices"
9+ "time"
810
911 "github.com/cenkalti/backoff/v3"
1012 "github.com/rs/zerolog/log"
@@ -62,7 +64,9 @@ func action(cli *cli.Context) error {
6264 if err != nil {
6365 return err
6466 }
65-
67+ env := environment .MustGet ()
68+ subURLs := env .SubstrateURL
69+ relayURLs := env .RelaysURLs
6670 manager , err := environment .GetSubstrate ()
6771 if err != nil {
6872 return fmt .Errorf ("failed to create substrate manager: %w" , err )
@@ -105,17 +109,23 @@ func action(cli *cli.Context) error {
105109
106110 bo := backoff .NewExponentialBackOff ()
107111 bo .MaxElapsedTime = 0
112+
113+ // this ctx is used to allow the node to restart the peer without leaving any unwanted open connections
114+ currentPeerCtx , cancel := context .WithCancel (ctx )
108115 backoff .Retry (func () error {
109116 _ , err = peer .NewPeer (
110- ctx ,
117+ currentPeerCtx ,
111118 hex .EncodeToString (pair .Seed ()),
112119 manager ,
113120 router .Serve ,
114121 peer .WithKeyType (peer .KeyTypeEd25519 ),
115- peer .WithRelay (environment . GetRelaysURLs () ... ),
122+ peer .WithRelay (relayURLs ... ),
116123 peer .WithInMemoryExpiration (6 * 60 * 60 ), // 6 hours
117124 )
118125 if err != nil {
126+ if cancel != nil {
127+ cancel ()
128+ }
119129 return fmt .Errorf ("failed to start a new rmb peer: %w" , err )
120130 }
121131
@@ -128,6 +138,75 @@ func action(cli *cli.Context) error {
128138 Msg ("starting api-gateway module" )
129139
130140 // block forever
131- <- ctx .Done ()
132- return nil
141+ for {
142+ select {
143+ case <- ctx .Done ():
144+ return nil
145+ // check if we need to run an update on the peer and only do the update if all the changes are done successfully
146+ case <- time .After (10 * time .Minute ):
147+ env , err := environment .Get ()
148+ if err != nil {
149+ // skip update if we can't get env
150+ log .Debug ().Err (err ).Msg ("failed to load node environment" )
151+ continue
152+ }
153+
154+ updatedSubURLs := env .SubstrateURL
155+ updatedRelayURLs := env .RelaysURLs
156+
157+ // make sure urls are sorted for comparison
158+ slices .Sort (subURLs )
159+ slices .Sort (relayURLs )
160+ slices .Sort (updatedSubURLs )
161+ slices .Sort (updatedRelayURLs )
162+
163+ // skip update if substrate and relay urls did not change
164+ if slices .Equal (subURLs , updatedSubURLs ) && slices .Equal (relayURLs , updatedRelayURLs ) {
165+ log .Debug ().Msg ("zos-config doesn't have updated config to update the node with" )
166+ continue
167+ }
168+
169+ log .Debug ().Strs ("relays_urls" , updatedRelayURLs ).Strs ("substrate_urls" , updatedSubURLs ).Msg ("detected new update in configuration" )
170+
171+ manager , err = environment .GetSubstrate ()
172+ if err != nil {
173+ // skip update if can't get sub manager
174+ log .Debug ().Err (err ).Msg ("failed to get substrate manager" )
175+ continue
176+ }
177+ // cancel the current peer to create new one with updated urls
178+ if cancel != nil {
179+ log .Debug ().Msg ("cancelling current peer context to create a new one with updated urls" )
180+ cancel ()
181+ }
182+
183+ currentPeerCtx , cancel = context .WithCancel (ctx )
184+ backoff .Retry (func () error {
185+ _ , err = peer .NewPeer (
186+ currentPeerCtx ,
187+ hex .EncodeToString (pair .Seed ()),
188+ manager ,
189+ router .Serve ,
190+ peer .WithKeyType (peer .KeyTypeEd25519 ),
191+ peer .WithRelay (updatedRelayURLs ... ),
192+ peer .WithInMemoryExpiration (6 * 60 * 60 ), // 6 hours
193+ )
194+ if err != nil {
195+ if cancel != nil {
196+
197+ // cancel the context to avoid any unwanted open connections
198+ cancel ()
199+ }
200+ return fmt .Errorf ("failed to start a new rmb peer: %w" , err )
201+
202+ }
203+ return nil
204+ }, bo )
205+
206+ relayURLs = updatedRelayURLs
207+ subURLs = updatedSubURLs
208+
209+ log .Debug ().Strs ("relays_urls" , relayURLs ).Strs ("substrate_urls" , subURLs ).Msg ("updated substrate and relay urls" )
210+ }
211+ }
133212}
0 commit comments