// NewLedgerClosePump starts a background proc that continually watches the // history database provided. The watch is stopped after the provided context // is cancelled. // // Every second, the proc spawned by calling this func will check to see // if a new ledger has been imported (by ruby-horizon as of 2015-04-30, but // should eventually end up being in this project). If a new ledger is seen // the the channel returned by this function emits func NewLedgerClosePump(ctx context.Context, db *sql.DB) <-chan time.Time { result := make(chan time.Time) go func() { var lastSeenLedger int32 for { select { case <-time.After(1 * time.Second): var latestLedger int32 row := db.QueryRow("SELECT MAX(sequence) FROM history_ledgers") err := row.Scan(&latestLedger) if err != nil { log.Warn(ctx, "Failed to check latest ledger", err) break } if latestLedger > lastSeenLedger { log.Debugf(ctx, "saw new ledger: %d, prev: %d", latestLedger, lastSeenLedger) lastSeenLedger = latestLedger result <- time.Now() } case <-ctx.Done(): log.Info(ctx, "canceling ledger pump") return } } }() return result }
// clearSliceIfPossible is a utility function that clears a slice if the // provided interface wraps one. In the event that `dest` is not a pointer to a // slice this func will fail with a warning, this allowing the forthcoming db // select fail more concretely due to an incompatible destination. func (r *Repo) clearSliceIfPossible(dest interface{}) { v := reflect.ValueOf(dest) vt := v.Type() if vt.Kind() != reflect.Ptr { log.Warn("cannot clear slice: dest is not pointer") return } if vt.Elem().Kind() != reflect.Slice { log.Warn("cannot clear slice: dest is a pointer, but not to a slice") return } reflect.Indirect(v).SetLen(0) }
// NewLedgerClosePump starts a background proc that continually watches the // history database provided. The watch is stopped after the provided context // is cancelled. // // Every second, the proc spawned by calling this func will check to see // if a new ledger has been imported (by ruby-horizon as of 2015-04-30, but // should eventually end up being in this project). If a new ledger is seen // the the channel returned by this function emits func NewLedgerClosePump(ctx context.Context, db *sqlx.DB) <-chan struct{} { result := make(chan struct{}) go func() { var lastSeenLedger int32 for { select { case <-time.After(1 * time.Second): var latestLedger int32 row := db.QueryRow(MaxHistoryLedger) err := row.Scan(&latestLedger) if err != nil { log.Warn(ctx, "Failed to check latest ledger", err) break } if latestLedger > lastSeenLedger { log.Debugf(ctx, "saw new ledger: %d, prev: %d", latestLedger, lastSeenLedger) select { case result <- struct{}{}: lastSeenLedger = latestLedger default: log.Debug(ctx, "ledger pump channel is blocked. waiting...") } } else if latestLedger < lastSeenLedger { log.Warn(ctx, "latest ledger went backwards! reseting ledger pump") lastSeenLedger = 0 } case <-ctx.Done(): log.Info(ctx, "canceling ledger pump") close(result) return } } }() return result }
// NewLedgerClosePump starts a background proc that continually watches the // history database provided. The watch is stopped after the provided context // is cancelled. // // Every second, the proc spawned by calling this func will check to see // if a new ledger has been imported (by ruby-horizon as of 2015-04-30, but // should eventually end up being in this project). If a new ledger is seen // the the channel returned by this function emits func NewLedgerClosePump(ctx context.Context, q *history.Q) <-chan struct{} { result := make(chan struct{}) go func() { var lastSeenLedger int32 for { select { case <-time.After(1 * time.Second): var latestLedger int32 err := q.LatestLedger(&latestLedger) if err != nil { log.Warn("Failed to check latest ledger", err) continue } if latestLedger > lastSeenLedger { log.Debugf("saw new ledger: %d, prev: %d", latestLedger, lastSeenLedger) select { case result <- struct{}{}: lastSeenLedger = latestLedger default: log.Debug("ledger pump channel is blocked. waiting...") } } else if latestLedger < lastSeenLedger { log.Warn("latest ledger went backwards! reseting ledger pump") lastSeenLedger = 0 } case <-ctx.Done(): log.Info("canceling ledger pump") close(result) return } } }() return result }