internal/jobs: add ListJobs
Change-Id: I06878f12210a82766d1d471265debd661e7dd342
Reviewed-on: https://go-review.googlesource.com/c/pkgsite-metrics/+/495797
Reviewed-by: Maceo Thompson <maceothompson@google.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/internal/jobs/firestore.go b/internal/jobs/firestore.go
index 4b288d5..859c154 100644
--- a/internal/jobs/firestore.go
+++ b/internal/jobs/firestore.go
@@ -7,9 +7,11 @@
import (
"context"
"errors"
+ "time"
"cloud.google.com/go/firestore"
"golang.org/x/pkgsite-metrics/internal/derrors"
+ "google.golang.org/api/iterator"
)
// A DB is a client for a database that stores Jobs.
@@ -89,6 +91,34 @@
})
}
+// ListJobs calls f on each job in the DB, most recently started first.
+// f is also passed the time that the job was last updated.
+// If f returns a non-nil error, the iteration stops and returns that error.
+func (d *DB) ListJobs(ctx context.Context, f func(_ *Job, lastUpdate time.Time) error) (err error) {
+ defer derrors.Wrap(&err, "job.DB.ListJobs()")
+
+ q := d.nsDoc.Collection(jobCollection).OrderBy("StartedAt", firestore.Desc)
+ iter := q.Documents(ctx)
+ defer iter.Stop()
+ for {
+ docsnap, err := iter.Next()
+ if err == iterator.Done {
+ break
+ }
+ if err != nil {
+ return err
+ }
+ job, err := docsnapToJob(docsnap)
+ if err != nil {
+ return err
+ }
+ if err := f(job, docsnap.UpdateTime); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
// jobRef returns the DocumentRef for a job with the given ID.
func (d *DB) jobRef(id string) *firestore.DocumentRef {
return d.nsDoc.Collection(jobCollection).Doc(id)
diff --git a/internal/jobs/firestore_test.go b/internal/jobs/firestore_test.go
index 88d4cbc..3c9bdb0 100644
--- a/internal/jobs/firestore_test.go
+++ b/internal/jobs/firestore_test.go
@@ -69,4 +69,20 @@
if !cmp.Equal(got, job) {
t.Errorf("got\n%+v\nwant\n%+v", got, job)
}
+
+ // Create another job, then list both.
+ job2 := NewJob("user2", tm.Add(24*time.Hour), "url2")
+ must(db.DeleteJob(ctx, job2.ID()))
+ must(db.CreateJob(ctx, job2))
+
+ var got2 []*Job
+ must(db.ListJobs(ctx, func(j *Job, _ time.Time) error {
+ got2 = append(got2, j)
+ return nil
+ }))
+ // Jobs listed in reverse start-time order.
+ want2 := []*Job{job2, job}
+ if diff := cmp.Diff(want2, got2); diff != "" {
+ t.Errorf("mismatch (-want, +got)\n%s", diff)
+ }
}