package syncbeacon import ( "sync" "time" "github.com/iotaledger/goshimmer/packages/shutdown" "github.com/iotaledger/goshimmer/plugins/config" "github.com/iotaledger/goshimmer/plugins/issuer" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/iotaledger/goshimmer/plugins/syncbeacon/payload" "github.com/iotaledger/goshimmer/plugins/syncbeaconfollower" "github.com/iotaledger/hive.go/daemon" "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/hive.go/node" flag "github.com/spf13/pflag" ) const ( // PluginName is the plugin name of the sync beacon plugin. PluginName = "SyncBeacon" // CfgSyncBeaconBroadcastIntervalSec is the interval in seconds at which the node broadcasts its sync status. CfgSyncBeaconBroadcastIntervalSec = "syncbeacon.broadcastInterval" // CfgSyncBeaconStartSynced defines whether to start the sync beacon in synced mode so it can issue an initial sync beacon message. CfgSyncBeaconStartSynced = "syncbeacon.startSynced" ) func init() { flag.Int(CfgSyncBeaconBroadcastIntervalSec, 30, "the interval at which the node will broadcast its sync status") flag.Bool(CfgSyncBeaconStartSynced, false, "set node to start as synced so it can issue an initial sync beacon message") } var ( // plugin is the plugin instance of the sync beacon plugin. plugin *node.Plugin once sync.Once log *logger.Logger ) // Plugin gets the plugin instance. func Plugin() *node.Plugin { once.Do(func() { plugin = node.NewPlugin(PluginName, node.Disabled, configure, run) }) return plugin } // configure events func configure(_ *node.Plugin) { log = logger.NewLogger(PluginName) log.Infof("starting node as sync beacon") if config.Node().GetBool(CfgSyncBeaconStartSynced) { log.Infof("Retrieving all the tips") messagelayer.TipSelector().Set(messagelayer.Tangle().RetrieveAllTips()...) syncbeaconfollower.OverwriteSyncedState(true) log.Infof("overwriting synced state to 'true'") } } // broadcastSyncBeaconPayload broadcasts a sync beacon via communication layer. func broadcastSyncBeaconPayload() { syncBeaconPayload := payload.NewSyncBeaconPayload(time.Now().UnixNano()) msg, err := issuer.IssuePayload(syncBeaconPayload) if err != nil { log.Warnf("error issuing sync beacon: %w", err) return } log.Debugf("issued sync beacon %s", msg.Id()) } func run(_ *node.Plugin) { if err := daemon.BackgroundWorker("Sync-Beacon", func(shutdownSignal <-chan struct{}) { // wait CfgSyncBeaconBroadcastIntervalSec to possibly retrieve new beacons if config.Node().GetBool(CfgSyncBeaconStartSynced) { time.Sleep(config.Node().GetDuration(CfgSyncBeaconBroadcastIntervalSec) * time.Second) } ticker := time.NewTicker(config.Node().GetDuration(CfgSyncBeaconBroadcastIntervalSec) * time.Second) defer ticker.Stop() for { select { case <-ticker.C: broadcastSyncBeaconPayload() case <-shutdownSignal: return } } }, shutdown.PrioritySynchronization); err != nil { log.Panicf("Failed to start as daemon: %s", err) } }