···134134 l.Warn("failed to ingest record, skipping", "err", err)
135135 }
136136137137- lastTimeUs := e.TimeUS + 1
138138- if saveErr := i.Db.SaveLastTimeUs(lastTimeUs); saveErr != nil {
139139- l.Error("failed to save cursor", "err", saveErr)
140140- }
141141-142137 return nil
143138 }
144139}
+28-23
jetstream/jetstream.go
···77 "os"
88 "os/signal"
99 "sync"
1010+ "sync/atomic"
1011 "syscall"
1112 "time"
1213···3435 db DB
3536 waitForDid bool
3637 mu sync.RWMutex
3838+3939+ lastSeenUs atomic.Int64
37403841 cancel context.CancelFunc
3942 cancelMu sync.Mutex
···7174 // since this closure references j.WantedDids; it should auto-update
7275 // existing instances of the closure when j.WantedDids is mutated
7376 return func(ctx context.Context, evt *models.Event) error {
7474-7577 j.mu.RLock()
7678 // empty filter => all dids allowed
7779 matches := len(j.wantedDids) == 0
···8284 }
8385 j.mu.RUnlock()
84868787+ var err error
8588 if matches {
8686- return processFunc(ctx, evt)
8787- } else {
8888- return nil
8989+ err = processFunc(ctx, evt)
8990 }
9191+9292+ j.lastSeenUs.Store(evt.TimeUS + 1)
9393+ return err
9094 }
9195}
9296···113117}
114118115119// StartJetstream starts the jetstream client and processes events using the provided processFunc.
116116-// The caller is responsible for saving the last time_us to the database (just use your db.UpdateLastTimeUs).
120120+// The client persists the last time_us cursor itself via the DB it was constructed with.
117121func (j *JetstreamClient) StartJetstream(ctx context.Context, processFunc func(context.Context, *models.Event) error) error {
118122 logger := j.l
119123···151155func (j *JetstreamClient) connectAndRead(ctx context.Context) {
152156 l := log.FromContext(ctx)
153157 for {
154154- cursor := j.getLastTimeUs(ctx)
158158+ cursor := j.resumeCursor(ctx)
155159156160 connCtx, cancel := context.WithCancel(ctx)
157161 j.cancelMu.Lock()
···185189 case <-ctx.Done():
186190 return
187191 case <-ticker.C:
188188- j.db.SaveLastTimeUs(time.Now().UnixMicro())
192192+ if seen := j.lastSeenUs.Load(); seen != 0 {
193193+ if err := j.db.SaveLastTimeUs(seen); err != nil {
194194+ log.FromContext(ctx).Error("failed to save cursor", "error", err)
195195+ }
196196+ }
189197 }
190198 }
191199}
192200201201+func (j *JetstreamClient) resumeCursor(ctx context.Context) *int64 {
202202+ if seen := j.lastSeenUs.Load(); seen != 0 {
203203+ return &seen
204204+ }
205205+ return j.getLastTimeUs(ctx)
206206+}
207207+193208func (j *JetstreamClient) getLastTimeUs(ctx context.Context) *int64 {
194209 l := log.FromContext(ctx)
195210 lastTimeUs, err := j.db.GetLastTimeUs()
196211 if err != nil {
197212 l.Warn("couldn't get last time us, starting from now", "error", err)
198213 lastTimeUs = time.Now().UnixMicro()
199199- err = j.db.SaveLastTimeUs(lastTimeUs)
200200- if err != nil {
201201- l.Error("failed to save last time us", "error", err)
202202- }
203203- }
204204-205205- // If last time is older than 2 days, start from now
206206- if time.Now().UnixMicro()-lastTimeUs > 2*24*60*60*1000*1000 {
207207- lastTimeUs = time.Now().UnixMicro()
208208- l.Warn("last time us is older than 2 days; discarding that and starting from now")
209209- err = j.db.SaveLastTimeUs(lastTimeUs)
210210- if err != nil {
214214+ if err = j.db.SaveLastTimeUs(lastTimeUs); err != nil {
211215 l.Error("failed to save last time us", "error", err)
212216 }
213217 }
···234238 sig := <-sigChan
235239 j.l.Info("Received signal, initiating graceful shutdown", "signal", sig)
236240237237- lastTimeUs := time.Now().UnixMicro()
238238- if err := j.db.SaveLastTimeUs(lastTimeUs); err != nil {
239239- j.l.Error("Failed to save last time during shutdown", "error", err)
241241+ if seen := j.lastSeenUs.Load(); seen != 0 {
242242+ if err := j.db.SaveLastTimeUs(seen); err != nil {
243243+ j.l.Error("Failed to save last time during shutdown", "error", err)
244244+ }
245245+ j.l.Info("Saved lastTimeUs before shutdown", "lastTimeUs", seen)
240246 }
241241- j.l.Info("Saved lastTimeUs before shutdown", "lastTimeUs", lastTimeUs)
242247243248 j.cancelMu.Lock()
244249 if j.cancel != nil {