//RunUpdater: creates and runs a go routine that will periodically (and if requested) update the symbols in the struct
creates and runs a go routine that will periodically (and if requested) update the symbols in the struct
// RunUpdater : creates and runs a go routine that will periodically ( and if requested ) update the symbols in the struct
func (sc *StockCache) Run() error {
	if sc.running {
		return fmt.Errorf("StockCache is already running")
	}
	sc.running = true
	go func(sc *StockCache) {
	getData:
		for {
			select {
			case <-sc.killCtx.Done():
				break getData
			case <-time.After(5 * time.Second):
				if err := sc.updatedSymbolsList(); err != nil {
					logrus.Errorf("StockCache: had an error while getting data from DB: %v", err)
				} else {
					break getData
				}
			}
		}
		logrus.Infof("StockCache: loaded Data from Database")
		updateDBTicker := time.NewTicker(1 * time.Second)
	mainLoop:
		for {
			select {
			case <-sc.killCtx.Done():
				break mainLoop
			case <-updateDBTicker.C:
				startTime := time.Now()
				if !sc.stateChange {
					continue
				}
				sc.stateChange = false
				stocks, err := sc.db.GetAllStockRecords(sc.killCtx)
				if err != nil {
					logrus.Infof("StockCache: unable to retrieve stocks for update")
					continue
				}
				sc.stocksMu.RLock()
				for _, stock := range stocks {
					if _, has := sc.stocks[stock.Symbol]; !has {
						sc.db.StockDelete(sc.killCtx, stock.Symbol)
					}
				}
				for _, stock := range sc.stocks {
					err := sc.db.InsertOrUpdateStock(sc.killCtx, &stock)
					if err != nil {
						logrus.Errorf("StockCache:  %v", err)
					}
				}
				sc.stocksMu.RUnlock()
				logrus.Infof("StockCache: updated Database in %v", time.Since(startTime))
			}
		}
		sc.done()
	}(sc)
	return nil
}
func ( sc * StockCache ) Run ( ) error { if sc . running { return fmt . Errorf ( " " ) } sc . running = true go func ( sc * StockCache ) { getData : for { select { case <- sc . killCtx . Done ( ) : break getData case <- time . After ( 5 * time . Second ) : if err := sc . updatedSymbolsList ( ) ; err != nil { logrus . Errorf ( " " , err ) } else { break getData } } } logrus . Infof ( " " ) updateDBTicker := time . NewTicker ( 1 * time . Second ) mainLoop : for { select { case <- sc . killCtx . Done ( ) : break mainLoop case <- updateDBTicker . C : startTime := time . Now ( ) if ! sc . stateChange { continue } sc . stateChange = false stocks , err := sc . db . GetAllStockRecords ( sc . killCtx ) if err != nil { logrus . Infof ( " " ) continue } sc . stocksMu . RLock ( ) for _ , stock := range stocks { if _ , has := sc . stocks [ stock . Symbol ] ; ! has { sc . db . StockDelete ( sc . killCtx , stock . Symbol ) } } for _ , stock := range sc . stocks { err := sc . db . InsertOrUpdateStock ( sc . killCtx , & stock ) if err != nil { logrus . Errorf ( " " , err ) } } sc . stocksMu . RUnlock ( ) logrus . Infof ( " " , time . Since ( startTime ) ) } } sc . done ( ) } ( sc ) return nil }
creates and runs a go routine that will periodically (and if requested) update the symbols in the struct
creates and runs a go routine that will periodically ( and if requested ) update the symbols in the struct
//we want to prime the update requester becuase we want to update the cache as soon as we start running //on startup the cache is empty so we need to get data from the DB // then update the DB ever so often // now the only thing left to do is update the DB every so often //first we remove anything that's no longer in the cache //finally we take what's in the cache and update the DB