internal/firestore: various small changes
- Improve documentation
- Represent values as structs.
- Check connection in NewDB.
Change-Id: Ie4f59283393216c0847df1efffd6eda6c3463cd5
Reviewed-on: https://go-review.googlesource.com/c/oscar/+/602295
Reviewed-by: Russ Cox <rsc@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/internal/firestore/db.go b/internal/firestore/db.go
index 447cada..fd2074c 100644
--- a/internal/firestore/db.go
+++ b/internal/firestore/db.go
@@ -16,18 +16,18 @@
"cloud.google.com/go/firestore"
"golang.org/x/oscar/internal/storage"
- "google.golang.org/api/option"
)
-// DB implements [storage.DB].
+// DB is a connection to a Firestore database.
+// It implements [storage.DB].
type DB struct {
*fstore
uid int64 // unique ID, to identify lock owners
}
-// NewDB constructs a [DB].
-func NewDB(ctx context.Context, dbopts *DBOptions, copts ...option.ClientOption) (*DB, error) {
- fs, err := newFstore(ctx, dbopts, copts)
+// NewDB constructs a [DB] with the given [DBOptions].
+func NewDB(ctx context.Context, dbopts *DBOptions) (*DB, error) {
+ fs, err := newFstore(ctx, dbopts)
if err != nil {
return nil, err
}
@@ -48,6 +48,13 @@
)
// Lock implements [storage.DB.Lock].
+// Locks are stored as documents in the "locks" collection of the database.
+// If the document exists its content is the UID of the [DB] that holds it,
+// as set in [NewDB].
+// It is an error for a DB to unlock a lock that it doesn't own.
+// To avoid deadlock due to failed processes, locks time out after a reasonable
+// period of time.
+// There is no way to change the timeout value, and no way to renew a lease on a lock.
func (db *DB) Lock(name string) {
// Wait for the lock in a separate function to avoid defers inside a loop, consuming
// memory on each iteration.
@@ -146,7 +153,7 @@
// Set implements [storage.DB.Set].
func (db *DB) Set(key, val []byte) {
- db.set(nil, valueCollection, encodeKey(key), encodeValue(val))
+ db.set(nil, valueCollection, encodeKey(key), value{val})
}
// Get implements [storage.DB.Get].
@@ -156,7 +163,7 @@
if ds == nil {
return nil, false
}
- return decodeValue(ds.Data()), true
+ return dataTo[value](db.fstore, ds).V, true
}
// Delete implements [storage.DB.Delete].
@@ -173,7 +180,7 @@
func (db *DB) Scan(start, end []byte) iter.Seq2[[]byte, func() []byte] {
return func(yield func(key []byte, valf func() []byte) bool) {
for ds := range db.scan(nil, valueCollection, encodeKey(start), encodeKey(end)) {
- if !yield(decodeKey(ds.Ref.ID), func() []byte { return decodeValue(ds.Data()) }) {
+ if !yield(decodeKey(ds.Ref.ID), func() []byte { return dataTo[value](db.fstore, ds).V }) {
return
}
}
@@ -201,8 +208,8 @@
// Set implements [storage.Batch.Set].
func (b *dbBatch) Set(key, val []byte) {
- // TODO(jba): account for size of encoded map.
- b.b.set(encodeKey(key), encodeValue(slices.Clone(val)), len(val))
+ // TODO(jba): account for size of encoded struct.
+ b.b.set(encodeKey(key), value{slices.Clone(val)}, len(val))
}
// MaybeApply implements [storage.Batch.MaybeApply].
@@ -229,12 +236,8 @@
return b
}
-// encodeValue encodes v in a format acceptable to Firestore.
+// A value is a [DB] value as a Firestore document.
// (Firestore values must be maps or structs.)
-func encodeValue(v []byte) any {
- return map[string][]byte{"v": v}
-}
-
-func decodeValue(m map[string]any) []byte {
- return m["v"].([]byte)
+type value struct {
+ V []byte
}
diff --git a/internal/firestore/db_test.go b/internal/firestore/db_test.go
index dc11d6e..4b1662a 100644
--- a/internal/firestore/db_test.go
+++ b/internal/firestore/db_test.go
@@ -52,7 +52,7 @@
}
}
- db, err := NewDB(ctx, &DBOptions{ProjectID: fsProject, Database: fsDatabase}, rr.ClientOptions()...)
+ db, err := NewDB(ctx, &DBOptions{ProjectID: fsProject, Database: fsDatabase, ClientOptions: rr.ClientOptions()})
if err != nil {
t.Fatal(err)
}
diff --git a/internal/firestore/firestore.go b/internal/firestore/firestore.go
index 25d215b..3427a55 100644
--- a/internal/firestore/firestore.go
+++ b/internal/firestore/firestore.go
@@ -7,10 +7,16 @@
//
// A brief introduction to Firestore: it is a document DB with hierarchical keys.
// A key is a string of the form "coll1/id1/coll2/id2/.../collN/idN",
-// where the colls are called "collections". The values are called "documents".
+// where the colls are called "collections" and the values are called "documents".
// Each document is a set of key-value pairs. In Go, a document is represented
-// by a map[string]any. The Go Firestore client provides convenience functions for
-// converting documents to and from structs.
+// by a map[string]any, or a struct with exported fields:
+// the Go Firestore client provides convenience functions for converting documents to and from structs.
+//
+// The two database implementations in this package use three collections:
+// - The "locks" collection holds documents representing the locks used by [DB.Lock] and [DB.Unlock].
+// - The "values" collection holds the key-value pairs for [DB]. Keys are byte slices but document
+// names are strings. We hex-encode the keys to obtain strings with the same ordering.
+// - The "vectors" collection holds embeddding vectors for [VectorDB].
//
// [Firestore]: https://cloud.google.com/firestore
package firestore
@@ -31,9 +37,10 @@
// DBOptions is the configuration for a [DB] or [VectorDB].
type DBOptions struct {
- ProjectID string
- Database string
- Logger *slog.Logger
+ ProjectID string // if empty, attempt to detect the project
+ Database string // if empty, use the default database
+ Logger *slog.Logger
+ ClientOptions []option.ClientOption // options to the Firestore client
}
// fstore implements operations common to both [storage.DB] and [storage.VectorDB].
@@ -42,7 +49,7 @@
slog *slog.Logger
}
-func newFstore(ctx context.Context, dbopts *DBOptions, copts []option.ClientOption) (*fstore, error) {
+func newFstore(ctx context.Context, dbopts *DBOptions) (*fstore, error) {
if dbopts == nil {
dbopts = &DBOptions{}
}
@@ -55,10 +62,15 @@
if dbopts.Logger == nil {
dbopts.Logger = slog.Default()
}
- client, err := firestore.NewClientWithDatabase(ctx, dbopts.ProjectID, dbopts.Database, copts...)
+ client, err := firestore.NewClientWithDatabase(ctx, dbopts.ProjectID, dbopts.Database, dbopts.ClientOptions...)
if err != nil {
return nil, err
}
+ // The client doesn't actually connect until something is done, so get a document
+ // to see if there's a problem.
+ if _, err := client.Doc("c/d").Get(ctx); err != nil && !isNotFound(err) {
+ return nil, err
+ }
return &fstore{client: client, slog: dbopts.Logger}, nil
}
diff --git a/internal/firestore/testdata/db.grpcrr b/internal/firestore/testdata/db.grpcrr
index 0750b1a..f6be49c 100644
--- a/internal/firestore/testdata/db.grpcrr
+++ b/internal/firestore/testdata/db.grpcrr
@@ -1,5 +1,33 @@
RPCReTxt1
"go-discovery-exp,"
+79
+kind: CREATE_STREAM
+method: "/google.firestore.v1.Firestore/BatchGetDocuments"
+252
+kind: SEND
+message: {
+ [type.googleapis.com/google.firestore.v1.BatchGetDocumentsRequest]: {
+ database: "projects/go-discovery-exp/databases/(default)"
+ documents: "projects/go-discovery-exp/databases/(default)/documents/c/d"
+ }
+}
+ref_index: 1
+261
+kind: RECV
+message: {
+ [type.googleapis.com/google.firestore.v1.BatchGetDocumentsResponse]: {
+ missing: "projects/go-discovery-exp/databases/(default)/documents/c/d"
+ read_time: {
+ seconds: 1722471840
+ nanos: 129116000
+ }
+ }
+}
+ref_index: 1
+39
+kind: RECV
+is_error: true
+ref_index: 1
443
kind: REQUEST
method: "/google.firestore.v1.Firestore/Commit"
@@ -10,7 +38,7 @@
update: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/6b6579"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "value"
}
@@ -25,17 +53,17 @@
[type.googleapis.com/google.firestore.v1.CommitResponse]: {
write_results: {
update_time: {
- seconds: 1721655326
- nanos: 448583000
+ seconds: 1722471840
+ nanos: 437072000
}
}
commit_time: {
- seconds: 1721655326
- nanos: 448583000
+ seconds: 1722471840
+ nanos: 437072000
}
}
}
-ref_index: 1
+ref_index: 5
79
kind: CREATE_STREAM
method: "/google.firestore.v1.Firestore/BatchGetDocuments"
@@ -47,7 +75,7 @@
documents: "projects/go-discovery-exp/databases/(default)/documents/values/6b6579"
}
}
-ref_index: 3
+ref_index: 7
552
kind: RECV
message: {
@@ -55,35 +83,35 @@
found: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/6b6579"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "value"
}
}
create_time: {
- seconds: 1721655326
- nanos: 448583000
+ seconds: 1722471840
+ nanos: 437072000
}
update_time: {
- seconds: 1721655326
- nanos: 448583000
+ seconds: 1722471840
+ nanos: 437072000
}
}
read_time: {
- seconds: 1721655326
- nanos: 448583000
+ seconds: 1722471840
+ nanos: 437072000
}
}
}
-ref_index: 3
+ref_index: 7
39
kind: RECV
is_error: true
-ref_index: 3
+ref_index: 7
79
kind: CREATE_STREAM
method: "/google.firestore.v1.Firestore/BatchGetDocuments"
-270
+271
kind: SEND
message: {
[type.googleapis.com/google.firestore.v1.BatchGetDocumentsRequest]: {
@@ -91,23 +119,23 @@
documents: "projects/go-discovery-exp/databases/(default)/documents/values/6d697373696e67"
}
}
-ref_index: 7
-279
+ref_index: 11
+280
kind: RECV
message: {
[type.googleapis.com/google.firestore.v1.BatchGetDocumentsResponse]: {
missing: "projects/go-discovery-exp/databases/(default)/documents/values/6d697373696e67"
read_time: {
- seconds: 1721655326
- nanos: 756828000
+ seconds: 1722471840
+ nanos: 721386000
}
}
}
-ref_index: 7
-39
+ref_index: 11
+40
kind: RECV
is_error: true
-ref_index: 7
+ref_index: 11
308
kind: REQUEST
method: "/google.firestore.v1.Firestore/Commit"
@@ -125,12 +153,12 @@
[type.googleapis.com/google.firestore.v1.CommitResponse]: {
write_results: {}
commit_time: {
- seconds: 1721655326
- nanos: 859376000
+ seconds: 1722471840
+ nanos: 852230000
}
}
}
-ref_index: 11
+ref_index: 15
79
kind: CREATE_STREAM
method: "/google.firestore.v1.Firestore/BatchGetDocuments"
@@ -142,23 +170,23 @@
documents: "projects/go-discovery-exp/databases/(default)/documents/values/6b6579"
}
}
-ref_index: 13
+ref_index: 17
272
kind: RECV
message: {
[type.googleapis.com/google.firestore.v1.BatchGetDocumentsResponse]: {
missing: "projects/go-discovery-exp/databases/(default)/documents/values/6b6579"
read_time: {
- seconds: 1721655326
- nanos: 944912000
+ seconds: 1722471840
+ nanos: 852230000
}
}
}
-ref_index: 13
+ref_index: 17
40
kind: RECV
is_error: true
-ref_index: 13
+ref_index: 17
222
kind: REQUEST
method: "/google.firestore.v1.Firestore/BeginTransaction"
@@ -167,15 +195,15 @@
database: "projects/go-discovery-exp/databases/(default)"
}
}
-414
+398
kind: RESPONSE
message: {
[type.googleapis.com/google.firestore.v1.BeginTransactionResponse]: {
- transaction: "\x11\xc7b\xd1~RZ5\xd4\"Y\x00\xd4u\xc8\xcdJ\xaf7\xa7\x8b\x0f`\xc7\x12!sG\xae\xacC\xab\x9dh\x92\x94\x87]\xc7\xfe\x15\x07jb\x00l\x8d\x19'2\xfd\x88S\x85\xf9\x13\x84{\x12\xc6\xd5\x18\x80\xc4\"\xa7d\xf8z\xae\xf1\xfe$'V\x15m\xc6ia\x07V\x07 \x8e<\xf3\xba*\xb0*\xeb\x83Yr\x85\xa5Ab\xc9"
+ transaction: "\x11\x8e\xe1\xc8\xebD\x8d\xb6\x87\"Y\x00\xd4u\xc8͊\x0b\xe4A\x0f\xd8сj\xdbY\xac\xa0\xc1LiA]\xf0Pp\xb2\x10\x96\x193$\x9av\xfc\x84\xb92G-b\x87\xf5_\x8b\x11n\xbb\xcf\xff6\xdc Q\x96\xe3W\xb7_u\xd5U\xd8ӽ\x15\x04\x92?66ҷ\xbbz\xf08\xe4\xde\x1d\xdd\xcazO\xc8~\x0fj:"
}
}
-ref_index: 17
-2848
+ref_index: 21
+2832
kind: REQUEST
method: "/google.firestore.v1.Firestore/Commit"
message: {
@@ -185,7 +213,7 @@
update: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3000"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "0"
}
@@ -196,7 +224,7 @@
update: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3001"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "1"
}
@@ -207,7 +235,7 @@
update: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3002"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "2"
}
@@ -218,7 +246,7 @@
update: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3003"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "3"
}
@@ -229,7 +257,7 @@
update: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3004"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "4"
}
@@ -240,7 +268,7 @@
update: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3005"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "5"
}
@@ -251,7 +279,7 @@
update: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3006"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "6"
}
@@ -262,7 +290,7 @@
update: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3007"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "7"
}
@@ -273,7 +301,7 @@
update: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3008"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "8"
}
@@ -284,87 +312,87 @@
update: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3009"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "9"
}
}
}
}
- transaction: "\x11\xc7b\xd1~RZ5\xd4\"Y\x00\xd4u\xc8\xcdJ\xaf7\xa7\x8b\x0f`\xc7\x12!sG\xae\xacC\xab\x9dh\x92\x94\x87]\xc7\xfe\x15\x07jb\x00l\x8d\x19'2\xfd\x88S\x85\xf9\x13\x84{\x12\xc6\xd5\x18\x80\xc4\"\xa7d\xf8z\xae\xf1\xfe$'V\x15m\xc6ia\x07V\x07 \x8e<\xf3\xba*\xb0*\xeb\x83Yr\x85\xa5Ab\xc9"
+ transaction: "\x11\x8e\xe1\xc8\xebD\x8d\xb6\x87\"Y\x00\xd4u\xc8͊\x0b\xe4A\x0f\xd8сj\xdbY\xac\xa0\xc1LiA]\xf0Pp\xb2\x10\x96\x193$\x9av\xfc\x84\xb92G-b\x87\xf5_\x8b\x11n\xbb\xcf\xff6\xdc Q\x96\xe3W\xb7_u\xd5U\xd8ӽ\x15\x04\x92?66ҷ\xbbz\xf08\xe4\xde\x1d\xdd\xcazO\xc8~\x0fj:"
}
}
-1271
+1272
kind: RESPONSE
message: {
[type.googleapis.com/google.firestore.v1.CommitResponse]: {
write_results: {
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
write_results: {
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
write_results: {
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
write_results: {
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
write_results: {
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
write_results: {
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
write_results: {
update_time: {
- seconds: 1721655264
- nanos: 64308000
+ seconds: 1722471841
+ nanos: 255428000
}
}
write_results: {
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
write_results: {
update_time: {
- seconds: 1721171630
- nanos: 112889000
+ seconds: 1722471841
+ nanos: 255428000
}
}
write_results: {
update_time: {
- seconds: 1721171630
- nanos: 112889000
+ seconds: 1722471841
+ nanos: 255428000
}
}
commit_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
}
-ref_index: 19
+ref_index: 23
70
kind: CREATE_STREAM
method: "/google.firestore.v1.Firestore/RunQuery"
@@ -397,7 +425,7 @@
}
}
}
-ref_index: 21
+ref_index: 25
541
kind: RECV
message: {
@@ -405,27 +433,27 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3003"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "3"
}
}
create_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 322624000
+ seconds: 1722471841
+ nanos: 386438000
}
}
}
-ref_index: 21
+ref_index: 25
541
kind: RECV
message: {
@@ -433,27 +461,27 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3004"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "4"
}
}
create_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 322624000
+ seconds: 1722471841
+ nanos: 386438000
}
}
}
-ref_index: 21
+ref_index: 25
541
kind: RECV
message: {
@@ -461,59 +489,59 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3005"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "5"
}
}
create_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 322624000
+ seconds: 1722471841
+ nanos: 386438000
}
}
}
-ref_index: 21
-539
+ref_index: 25
+541
kind: RECV
message: {
[type.googleapis.com/google.firestore.v1.RunQueryResponse]: {
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3006"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "6"
}
}
create_time: {
- seconds: 1721655264
- nanos: 64308000
+ seconds: 1721939400
+ nanos: 535835000
}
update_time: {
- seconds: 1721655264
- nanos: 64308000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 322624000
+ seconds: 1722471841
+ nanos: 386438000
}
}
}
-ref_index: 21
+ref_index: 25
40
kind: RECV
is_error: true
-ref_index: 21
+ref_index: 25
70
kind: CREATE_STREAM
method: "/google.firestore.v1.Firestore/RunQuery"
@@ -546,7 +574,7 @@
}
}
}
-ref_index: 28
+ref_index: 32
541
kind: RECV
message: {
@@ -554,27 +582,27 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3003"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "3"
}
}
create_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 565710000
+ seconds: 1722471841
+ nanos: 519729000
}
}
}
-ref_index: 28
+ref_index: 32
541
kind: RECV
message: {
@@ -582,27 +610,27 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3004"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "4"
}
}
create_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 565710000
+ seconds: 1722471841
+ nanos: 519729000
}
}
}
-ref_index: 28
+ref_index: 32
541
kind: RECV
message: {
@@ -610,27 +638,27 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3005"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "5"
}
}
create_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 565710000
+ seconds: 1722471841
+ nanos: 519729000
}
}
}
-ref_index: 28
+ref_index: 32
70
kind: CREATE_STREAM
method: "/google.firestore.v1.Firestore/RunQuery"
@@ -663,7 +691,7 @@
}
}
}
-ref_index: 33
+ref_index: 37
541
kind: RECV
message: {
@@ -671,27 +699,27 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3004"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "4"
}
}
create_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 657343000
+ seconds: 1722471841
+ nanos: 684584000
}
}
}
-ref_index: 33
+ref_index: 37
541
kind: RECV
message: {
@@ -699,55 +727,55 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3005"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "5"
}
}
create_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 657343000
+ seconds: 1722471841
+ nanos: 684584000
}
}
}
-ref_index: 33
-539
+ref_index: 37
+541
kind: RECV
message: {
[type.googleapis.com/google.firestore.v1.RunQueryResponse]: {
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3006"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "6"
}
}
create_time: {
- seconds: 1721655264
- nanos: 64308000
+ seconds: 1721939400
+ nanos: 535835000
}
update_time: {
- seconds: 1721655264
- nanos: 64308000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 657343000
+ seconds: 1722471841
+ nanos: 684584000
}
}
}
-ref_index: 33
+ref_index: 37
541
kind: RECV
message: {
@@ -755,31 +783,31 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3007"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "7"
}
}
create_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 657343000
+ seconds: 1722471841
+ nanos: 684584000
}
}
}
-ref_index: 33
+ref_index: 37
40
kind: RECV
is_error: true
-ref_index: 33
+ref_index: 37
626
kind: REQUEST
method: "/google.firestore.v1.Firestore/BatchWrite"
@@ -814,7 +842,7 @@
status: {}
}
}
-ref_index: 40
+ref_index: 44
70
kind: CREATE_STREAM
method: "/google.firestore.v1.Firestore/RunQuery"
@@ -847,7 +875,7 @@
}
}
}
-ref_index: 42
+ref_index: 46
541
kind: RECV
message: {
@@ -855,27 +883,27 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3000"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "0"
}
}
create_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 903250000
+ seconds: 1722471841
+ nanos: 944215000
}
}
}
-ref_index: 42
+ref_index: 46
541
kind: RECV
message: {
@@ -883,27 +911,27 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3001"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "1"
}
}
create_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 903250000
+ seconds: 1722471841
+ nanos: 944215000
}
}
}
-ref_index: 42
+ref_index: 46
541
kind: RECV
message: {
@@ -911,27 +939,27 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3002"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "2"
}
}
create_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 903250000
+ seconds: 1722471841
+ nanos: 944215000
}
}
}
-ref_index: 42
+ref_index: 46
541
kind: RECV
message: {
@@ -939,27 +967,27 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3003"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "3"
}
}
create_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 903250000
+ seconds: 1722471841
+ nanos: 944215000
}
}
}
-ref_index: 42
+ref_index: 46
541
kind: RECV
message: {
@@ -967,7 +995,7 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3008"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "8"
}
@@ -977,17 +1005,17 @@
nanos: 112889000
}
update_time: {
- seconds: 1721171630
- nanos: 112889000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 903250000
+ seconds: 1722471841
+ nanos: 944215000
}
}
}
-ref_index: 42
+ref_index: 46
541
kind: RECV
message: {
@@ -995,7 +1023,7 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3009"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "9"
}
@@ -1005,21 +1033,21 @@
nanos: 112889000
}
update_time: {
- seconds: 1721171630
- nanos: 112889000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 903250000
+ seconds: 1722471841
+ nanos: 944215000
}
}
}
-ref_index: 42
+ref_index: 46
40
kind: RECV
is_error: true
-ref_index: 42
+ref_index: 46
222
kind: REQUEST
method: "/google.firestore.v1.Firestore/BeginTransaction"
@@ -1028,18 +1056,18 @@
database: "projects/go-discovery-exp/databases/(default)"
}
}
-410
+412
kind: RESPONSE
message: {
[type.googleapis.com/google.firestore.v1.BeginTransactionResponse]: {
- transaction: "\x11s\xa5\xdd0k\xd2\x04\x0f\"Y\x00\xd4u\xc8\xcd\x1d\xe5\xd31\xeb\xc1i\x01l+~M\xe6\xeb\xc3\xe1\xf22\xa5\xcc\x01G1\xe3i\xc4u\xf0\xa4Lt!\x07\x97\xeb\xaeൃX \xac\x1f\x7f\xf2\x8b\xa9\x7f;\x1e\xd6\xf7\x8f\x11RSi\xfaME\x82\xa1c\x85\xf8^\xf0'\xcfX\xbfN{e\xef\xeb\xa6XRς\x19\x055"
+ transaction: "\x11l\x0f\xa2,u\x95zT\"Y\x00\xd4u\xc8\xcd5\xcf\x1c]c\x8d}Q%\x99\xddG\xe2\x92J]E\x07y\xac\x0b\x1b\xa0\xbb\x9a\x16\xad\xf9$\xcf\x14\"\x19v\xdaK^R\xc3`\x93\xafp\x85쳎\x11P\xdec\x9c\xa5\xec'\xa6\xb2\xb0\xb2\xf1\xa2\"te7p\x08*\x82\x02Z\xaf\x12&\x16\x17\xf5\x1c\xab[\xa6\xae3\xc7"
}
}
-ref_index: 51
+ref_index: 55
70
kind: CREATE_STREAM
method: "/google.firestore.v1.Firestore/RunQuery"
-987
+989
kind: SEND
message: {
[type.googleapis.com/google.firestore.v1.RunQueryRequest]: {
@@ -1066,10 +1094,10 @@
}
}
}
- transaction: "\x11s\xa5\xdd0k\xd2\x04\x0f\"Y\x00\xd4u\xc8\xcd\x1d\xe5\xd31\xeb\xc1i\x01l+~M\xe6\xeb\xc3\xe1\xf22\xa5\xcc\x01G1\xe3i\xc4u\xf0\xa4Lt!\x07\x97\xeb\xaeൃX \xac\x1f\x7f\xf2\x8b\xa9\x7f;\x1e\xd6\xf7\x8f\x11RSi\xfaME\x82\xa1c\x85\xf8^\xf0'\xcfX\xbfN{e\xef\xeb\xa6XRς\x19\x055"
+ transaction: "\x11l\x0f\xa2,u\x95zT\"Y\x00\xd4u\xc8\xcd5\xcf\x1c]c\x8d}Q%\x99\xddG\xe2\x92J]E\x07y\xac\x0b\x1b\xa0\xbb\x9a\x16\xad\xf9$\xcf\x14\"\x19v\xdaK^R\xc3`\x93\xafp\x85쳎\x11P\xdec\x9c\xa5\xec'\xa6\xb2\xb0\xb2\xf1\xa2\"te7p\x08*\x82\x02Z\xaf\x12&\x16\x17\xf5\x1c\xab[\xa6\xae3\xc7"
}
}
-ref_index: 53
+ref_index: 57
541
kind: RECV
message: {
@@ -1077,32 +1105,32 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3000"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "0"
}
}
create_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
update_time: {
- seconds: 1721655327
- nanos: 222942000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655327
- nanos: 907076000
+ seconds: 1722471841
+ nanos: 947802000
}
}
}
-ref_index: 53
+ref_index: 57
40
kind: RECV
is_error: true
-ref_index: 53
-2293
+ref_index: 57
+2295
kind: REQUEST
method: "/google.firestore.v1.Firestore/Commit"
message: {
@@ -1115,7 +1143,7 @@
update: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3000"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "0"
}
@@ -1129,7 +1157,7 @@
update: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3002"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "2"
}
@@ -1143,7 +1171,7 @@
update: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3004"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "4"
}
@@ -1157,7 +1185,7 @@
update: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3006"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "6"
}
@@ -1171,7 +1199,7 @@
update: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3008"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "8"
}
@@ -1181,7 +1209,7 @@
writes: {
delete: "projects/go-discovery-exp/databases/(default)/documents/values/3000"
}
- transaction: "\x11s\xa5\xdd0k\xd2\x04\x0f\"Y\x00\xd4u\xc8\xcd\x1d\xe5\xd31\xeb\xc1i\x01l+~M\xe6\xeb\xc3\xe1\xf22\xa5\xcc\x01G1\xe3i\xc4u\xf0\xa4Lt!\x07\x97\xeb\xaeൃX \xac\x1f\x7f\xf2\x8b\xa9\x7f;\x1e\xd6\xf7\x8f\x11RSi\xfaME\x82\xa1c\x85\xf8^\xf0'\xcfX\xbfN{e\xef\xeb\xa6XRς\x19\x055"
+ transaction: "\x11l\x0f\xa2,u\x95zT\"Y\x00\xd4u\xc8\xcd5\xcf\x1c]c\x8d}Q%\x99\xddG\xe2\x92J]E\x07y\xac\x0b\x1b\xa0\xbb\x9a\x16\xad\xf9$\xcf\x14\"\x19v\xdaK^R\xc3`\x93\xafp\x85쳎\x11P\xdec\x9c\xa5\xec'\xa6\xb2\xb0\xb2\xf1\xa2\"te7p\x08*\x82\x02Z\xaf\x12&\x16\x17\xf5\x1c\xab[\xa6\xae3\xc7"
}
}
598
@@ -1197,25 +1225,25 @@
write_results: {}
write_results: {
update_time: {
- seconds: 1721655328
- nanos: 296191000
+ seconds: 1722471842
+ nanos: 322629000
}
}
write_results: {}
write_results: {
update_time: {
- seconds: 1721171630
- nanos: 112889000
+ seconds: 1722471841
+ nanos: 255428000
}
}
write_results: {}
commit_time: {
- seconds: 1721655328
- nanos: 296191000
+ seconds: 1722471842
+ nanos: 322629000
}
}
}
-ref_index: 57
+ref_index: 61
70
kind: CREATE_STREAM
method: "/google.firestore.v1.Firestore/RunQuery"
@@ -1248,7 +1276,7 @@
}
}
}
-ref_index: 59
+ref_index: 63
541
kind: RECV
message: {
@@ -1256,27 +1284,27 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3006"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "6"
}
}
create_time: {
- seconds: 1721655328
- nanos: 296191000
+ seconds: 1722471842
+ nanos: 322629000
}
update_time: {
- seconds: 1721655328
- nanos: 296191000
+ seconds: 1722471842
+ nanos: 322629000
}
}
read_time: {
- seconds: 1721655328
- nanos: 389515000
+ seconds: 1722471842
+ nanos: 433247000
}
}
}
-ref_index: 59
+ref_index: 63
541
kind: RECV
message: {
@@ -1284,7 +1312,7 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3008"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "8"
}
@@ -1294,17 +1322,17 @@
nanos: 112889000
}
update_time: {
- seconds: 1721171630
- nanos: 112889000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655328
- nanos: 389515000
+ seconds: 1722471842
+ nanos: 433247000
}
}
}
-ref_index: 59
+ref_index: 63
541
kind: RECV
message: {
@@ -1312,7 +1340,7 @@
document: {
name: "projects/go-discovery-exp/databases/(default)/documents/values/3009"
fields: {
- key: "v"
+ key: "V"
value: {
bytes_value: "9"
}
@@ -1322,21 +1350,21 @@
nanos: 112889000
}
update_time: {
- seconds: 1721171630
- nanos: 112889000
+ seconds: 1722471841
+ nanos: 255428000
}
}
read_time: {
- seconds: 1721655328
- nanos: 389515000
+ seconds: 1722471842
+ nanos: 433247000
}
}
}
-ref_index: 59
+ref_index: 63
40
kind: RECV
is_error: true
-ref_index: 59
+ref_index: 63
222
kind: REQUEST
method: "/google.firestore.v1.Firestore/BeginTransaction"
@@ -1345,18 +1373,18 @@
database: "projects/go-discovery-exp/databases/(default)"
}
}
-408
+409
kind: RESPONSE
message: {
[type.googleapis.com/google.firestore.v1.BeginTransactionResponse]: {
- transaction: "\x11\x11 \x8b\x8cX\xe5\x84\xdc\"Y\x00\xd4u\xc8͎\xeb=\xcc\x18ב\x02\x1fu\xed\xaaj\xc0\xf4zZ+\xb8\xb3E\xb9N\xc6\x14\xe2\xbdk\xac\xa8\x1bj\xd7\x0e\x97R<\x7fR\xd3\x0f\x84\xc3\x1d\x14\xb0\xf0\r<G\xf2I\xdf\xee*\xc2x1h.$\xa2X\x12dyY\x10\x95I\xb3w\x99\xdf\xcd\xcefy\xa1V\xe5n4?"
+ transaction: "\x11l\xe2\x0c\xfa\xec\x82;d\"Y\x00\xd4u\xc8\xcd\x010\xae։aS\x95\t`Z1\xdc\xce\xeaO\x8e+\x17\xd87\xa9\xcby\xb0F\x8cn\xb8n\xf9F*\x12\x1d\xc3RZ\xbe\xcex\x9c/$\x1edVV\xa7\x1e0Rz\x11\x8bY\xb5\nz\xbd\x98}\xa1^\xc0\xaeM\xda\xe3\xbe\x17\xb8\xc4\x14\xe2{rQ\xa1\xbd\x9f\xb2\xe2\xd5"
}
}
-ref_index: 65
+ref_index: 69
70
kind: CREATE_STREAM
method: "/google.firestore.v1.Firestore/RunQuery"
-981
+982
kind: SEND
message: {
[type.googleapis.com/google.firestore.v1.RunQueryRequest]: {
@@ -1383,42 +1411,95 @@
}
}
}
- transaction: "\x11\x11 \x8b\x8cX\xe5\x84\xdc\"Y\x00\xd4u\xc8͎\xeb=\xcc\x18ב\x02\x1fu\xed\xaaj\xc0\xf4zZ+\xb8\xb3E\xb9N\xc6\x14\xe2\xbdk\xac\xa8\x1bj\xd7\x0e\x97R<\x7fR\xd3\x0f\x84\xc3\x1d\x14\xb0\xf0\r<G\xf2I\xdf\xee*\xc2x1h.$\xa2X\x12dyY\x10\x95I\xb3w\x99\xdf\xcd\xcefy\xa1V\xe5n4?"
+ transaction: "\x11l\xe2\x0c\xfa\xec\x82;d\"Y\x00\xd4u\xc8\xcd\x010\xae։aS\x95\t`Z1\xdc\xce\xeaO\x8e+\x17\xd87\xa9\xcby\xb0F\x8cn\xb8n\xf9F*\x12\x1d\xc3RZ\xbe\xcex\x9c/$\x1edVV\xa7\x1e0Rz\x11\x8bY\xb5\nz\xbd\x98}\xa1^\xc0\xaeM\xda\xe3\xbe\x17\xb8\xc4\x14\xe2{rQ\xa1\xbd\x9f\xb2\xe2\xd5"
}
}
-ref_index: 67
-178
+ref_index: 71
+538
kind: RECV
message: {
[type.googleapis.com/google.firestore.v1.RunQueryResponse]: {
+ document: {
+ name: "projects/go-discovery-exp/databases/(default)/documents/values/61"
+ fields: {
+ key: "v"
+ value: {
+ bytes_value: ""
+ }
+ }
+ create_time: {
+ seconds: 1721939401
+ nanos: 289035000
+ }
+ update_time: {
+ seconds: 1721939401
+ nanos: 289035000
+ }
+ }
read_time: {
- seconds: 1721655328
- nanos: 585255000
+ seconds: 1722471842
+ nanos: 652207000
}
}
}
-ref_index: 67
+ref_index: 71
+538
+kind: RECV
+message: {
+ [type.googleapis.com/google.firestore.v1.RunQueryResponse]: {
+ document: {
+ name: "projects/go-discovery-exp/databases/(default)/documents/values/62"
+ fields: {
+ key: "v"
+ value: {
+ bytes_value: ""
+ }
+ }
+ create_time: {
+ seconds: 1721939401
+ nanos: 289035000
+ }
+ update_time: {
+ seconds: 1721939401
+ nanos: 289035000
+ }
+ }
+ read_time: {
+ seconds: 1722471842
+ nanos: 652207000
+ }
+ }
+}
+ref_index: 71
40
kind: RECV
is_error: true
-ref_index: 67
-492
+ref_index: 71
+697
kind: REQUEST
method: "/google.firestore.v1.Firestore/Commit"
message: {
[type.googleapis.com/google.firestore.v1.CommitRequest]: {
database: "projects/go-discovery-exp/databases/(default)"
- transaction: "\x11\x11 \x8b\x8cX\xe5\x84\xdc\"Y\x00\xd4u\xc8͎\xeb=\xcc\x18ב\x02\x1fu\xed\xaaj\xc0\xf4zZ+\xb8\xb3E\xb9N\xc6\x14\xe2\xbdk\xac\xa8\x1bj\xd7\x0e\x97R<\x7fR\xd3\x0f\x84\xc3\x1d\x14\xb0\xf0\r<G\xf2I\xdf\xee*\xc2x1h.$\xa2X\x12dyY\x10\x95I\xb3w\x99\xdf\xcd\xcefy\xa1V\xe5n4?"
+ writes: {
+ delete: "projects/go-discovery-exp/databases/(default)/documents/values/61"
+ }
+ writes: {
+ delete: "projects/go-discovery-exp/databases/(default)/documents/values/62"
+ }
+ transaction: "\x11l\xe2\x0c\xfa\xec\x82;d\"Y\x00\xd4u\xc8\xcd\x010\xae։aS\x95\t`Z1\xdc\xce\xeaO\x8e+\x17\xd87\xa9\xcby\xb0F\x8cn\xb8n\xf9F*\x12\x1d\xc3RZ\xbe\xcex\x9c/$\x1edVV\xa7\x1e0Rz\x11\x8bY\xb5\nz\xbd\x98}\xa1^\xc0\xaeM\xda\xe3\xbe\x17\xb8\xc4\x14\xe2{rQ\xa1\xbd\x9f\xb2\xe2\xd5"
}
}
-182
+226
kind: RESPONSE
message: {
[type.googleapis.com/google.firestore.v1.CommitResponse]: {
+ write_results: {}
+ write_results: {}
commit_time: {
- seconds: 1721655328
- nanos: 585255000
+ seconds: 1722471842
+ nanos: 813240000
}
}
}
-ref_index: 71
+ref_index: 76