| 166 | } |
| 167 | |
| 168 | func NewSlottedTicker(sf SlotInfoFunc, d time.Duration, slotJitter float64) *SlottedTicker { |
| 169 | c := make(chan time.Time, 1) |
| 170 | ctx, cancel := context.WithCancel(context.Background()) |
| 171 | st := &SlottedTicker{ |
| 172 | C: c, |
| 173 | done: cancel, |
| 174 | d: d, |
| 175 | sf: sf, |
| 176 | shouldReset: true, |
| 177 | slotJitter: slotJitter, |
| 178 | } |
| 179 | slitIndex, totalSlots := sf() |
| 180 | st.ticker = time.NewTicker(st.nextInterval()) |
| 181 | go func() { |
| 182 | for ctx.Err() == nil { |
| 183 | select { |
| 184 | case t := <-st.ticker.C: |
| 185 | if i, s := sf(); i != slitIndex || s != totalSlots { |
| 186 | slitIndex, totalSlots = i, s |
| 187 | st.ticker.Reset(st.nextInterval()) |
| 188 | st.shouldReset = true |
| 189 | continue |
| 190 | } |
| 191 | |
| 192 | c <- t |
| 193 | if st.shouldReset { |
| 194 | st.ticker.Reset(st.d) |
| 195 | } |
| 196 | |
| 197 | st.shouldReset = false |
| 198 | case <-ctx.Done(): |
| 199 | return |
| 200 | } |
| 201 | } |
| 202 | close(c) |
| 203 | }() |
| 204 | return st |
| 205 | } |
| 206 | |
| 207 | func (t *SlottedTicker) Stop() { |
| 208 | t.ticker.Stop() |