github.com/Axway/agent-sdk@v1.1.101/pkg/agent/eventsync.go (about) 1 package agent 2 3 import ( 4 "fmt" 5 "strconv" 6 "time" 7 8 "github.com/Axway/agent-sdk/pkg/agent/events" 9 "github.com/Axway/agent-sdk/pkg/agent/poller" 10 "github.com/Axway/agent-sdk/pkg/agent/stream" 11 management "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/management/v1alpha1" 12 "github.com/Axway/agent-sdk/pkg/config" 13 "github.com/Axway/agent-sdk/pkg/harvester" 14 "github.com/Axway/agent-sdk/pkg/jobs" 15 "github.com/Axway/agent-sdk/pkg/migrate" 16 "github.com/Axway/agent-sdk/pkg/util" 17 ) 18 19 // EventSync struct for syncing events from central 20 type EventSync struct { 21 watchTopic *management.WatchTopic 22 sequence events.SequenceProvider 23 harvester harvester.Harvest 24 discoveryCache *discoveryCache 25 } 26 27 // NewEventSync creates an EventSync 28 func NewEventSync() (*EventSync, error) { 29 migrations := []migrate.Migrator{} 30 31 // Make sure only DA and Governance agents run migration processes 32 runMigrations := agent.cfg.GetAgentType() != config.TraceabilityAgent 33 34 if runMigrations { 35 // add attribute migration to migrations 36 attributeMigration := migrate.NewAttributeMigration(agent.apicClient, agent.cfg) 37 ardMigration := migrate.NewArdMigration(agent.apicClient, agent.cfg) 38 apisiMigration := migrate.NewAPISIMigration(agent.apicClient, agent.cfg) 39 instanceMigration := migrate.NewInstanceMigration(agent.apicClient, agent.cfg) 40 migrations = append(migrations, attributeMigration, ardMigration, apisiMigration, instanceMigration) 41 42 } 43 44 mig := migrate.NewMigrateAll(migrations...) 45 46 opts := []discoveryOpt{ 47 withMigration(mig), 48 } 49 50 if agent.agentResourceManager != nil { 51 opts = append(opts, withAdditionalDiscoverFuncs(agent.agentResourceManager.FetchAgentResource)) 52 } 53 54 wt, err := events.GetWatchTopic(agent.cfg, GetCentralClient()) 55 if err != nil { 56 return nil, err 57 } 58 59 sequence := events.NewSequenceProvider(agent.cacheManager, wt.Name) 60 hCfg := harvester.NewConfig(agent.cfg, agent.tokenRequester, sequence) 61 hClient := harvester.NewClient(hCfg) 62 63 discoveryCache := newDiscoveryCache( 64 agent.cfg, 65 GetCentralClient(), 66 newHandlers(), 67 wt, 68 opts..., 69 ) 70 71 return &EventSync{ 72 watchTopic: wt, 73 sequence: sequence, 74 harvester: hClient, 75 discoveryCache: discoveryCache, 76 }, nil 77 } 78 79 // SyncCache initializes agent cache and starts the agent in stream or poll mode 80 func (es *EventSync) SyncCache() error { 81 if !agent.cacheManager.HasLoadedPersistedCache() { 82 if err := es.initCache(); err != nil { 83 return err 84 } 85 } 86 87 err := registerExternalIDPs() 88 if err != nil { 89 logger.WithError(err).Warn("failed to register CRDs for external IdP config") 90 } 91 92 err = es.startCentralEventProcessor() 93 if err != nil { 94 return err 95 } 96 97 return es.registerInstanceValidator() 98 } 99 100 func (es *EventSync) registerInstanceValidator() error { 101 if agent.apiValidatorJobID == "" && agent.cfg.GetAgentType() == config.DiscoveryAgent { 102 jobID, err := jobs.RegisterScheduledJobWithName(newInstanceValidator(), agent.cfg.GetAPIValidationCronSchedule(), "API service instance validator") 103 agent.apiValidatorJobID = jobID 104 return err 105 } 106 return nil 107 } 108 109 func (es *EventSync) initCache() error { 110 seqID, err := es.harvester.ReceiveSyncEvents(es.watchTopic.GetSelfLink(), 0, nil) 111 if err != nil { 112 return err 113 } 114 // event channel is not ready yet, so subtract one from the latest sequence id to process the event 115 // when the poll/stream client is ready 116 // when no events returned by harvester the seqID will be 0, so not updated in sequence manager 117 agent.cacheManager.Flush() 118 if seqID > 0 { 119 es.sequence.SetSequence(seqID - 1) 120 } 121 err = es.discoveryCache.execute() 122 if err != nil { 123 // flush cache again to clear out anything that may have been saved before the error to ensure a clean state for the next time through 124 agent.cacheManager.Flush() 125 return err 126 } 127 agent.cacheManager.SaveCache() 128 129 agentInstance := agent.agentResourceManager.GetAgentResource() 130 131 // add 7 days to the current date for the next rebuild cache 132 nextCacheUpdateTime := time.Now().Add(7 * 24 * time.Hour) 133 134 // persist cacheUpdateTime 135 util.SetAgentDetailsKey(agentInstance, "cacheUpdateTime", strconv.FormatInt(nextCacheUpdateTime.UnixNano(), 10)) 136 agent.apicClient.CreateSubResource(agentInstance.ResourceMeta, util.GetSubResourceDetails(agentInstance)) 137 logger.Tracef("setting next cache update time to - %s", time.Unix(0, nextCacheUpdateTime.UnixNano()).Format("2006-01-02 15:04:05.000000")) 138 return nil 139 } 140 141 func (es *EventSync) RebuildCache() { 142 // SDB - NOTE : Do we need to pause jobs. 143 logger.Info("rebuild cache") 144 145 // close window so discovery doesn't happen during this cache rebuild 146 PublishingLock() 147 defer PublishingUnlock() 148 149 if err := es.initCache(); err != nil { 150 logger.WithError(err).Error("failed to rebuild cache") 151 } 152 } 153 154 func (es *EventSync) startCentralEventProcessor() error { 155 if agent.cfg.IsUsingGRPC() { 156 return es.startStreamMode() 157 } 158 return es.startPollMode() 159 } 160 161 func (es *EventSync) startPollMode() error { 162 handlers := newHandlers() 163 164 pc, err := poller.NewPollClient( 165 agent.apicClient, 166 agent.cfg, 167 handlers, 168 poller.WithHarvester(es.harvester, es.sequence, es.watchTopic.GetSelfLink()), 169 poller.WithOnClientStop(es.RebuildCache), 170 poller.WithOnConnect(), 171 ) 172 173 if err != nil { 174 return fmt.Errorf("could not start the harvester poll client: %s", err) 175 } 176 177 if util.IsNotTest() { 178 newEventProcessorJob(pc, "Poll Client") 179 } 180 181 return err 182 } 183 184 func (es *EventSync) startStreamMode() error { 185 handlers := newHandlers() 186 187 sc, err := stream.NewStreamerClient( 188 agent.apicClient, 189 agent.cfg, 190 agent.tokenRequester, 191 handlers, 192 stream.WithOnStreamConnection(), 193 stream.WithEventSyncError(es.RebuildCache), 194 stream.WithWatchTopic(es.watchTopic), 195 stream.WithHarvester(es.harvester, es.sequence), 196 stream.WithCacheManager(agent.cacheManager), 197 stream.WithUserAgent(GetUserAgent()), 198 ) 199 200 if err != nil { 201 return fmt.Errorf("could not start the watch manager: %s", err) 202 } 203 204 agent.streamer = sc 205 206 if util.IsNotTest() { 207 newEventProcessorJob(sc, "Stream Client") 208 } 209 210 return err 211 }