From 0fdc1da4c91651606bb4c431ea11f635bfdf401a Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Mon, 12 Nov 2018 16:04:57 -0800 Subject: [PATCH 1/2] Adding base_mutations proto field --- .../Protos/cpp/firestore/local/mutation.pb.cc | 56 +++++++++++++++++-- .../Protos/cpp/firestore/local/mutation.pb.h | 40 +++++++++++++ .../nanopb/firestore/local/mutation.nanopb.cc | 3 +- .../nanopb/firestore/local/mutation.nanopb.h | 9 ++- .../objc/firestore/local/Mutation.pbobjc.h | 17 ++++++ .../objc/firestore/local/Mutation.pbobjc.m | 11 ++++ .../protos/firestore/local/mutation.proto | 12 ++++ 7 files changed, 140 insertions(+), 8 deletions(-) diff --git a/Firestore/Protos/cpp/firestore/local/mutation.pb.cc b/Firestore/Protos/cpp/firestore/local/mutation.pb.cc index e6c88d76d33..e2dfb718591 100644 --- a/Firestore/Protos/cpp/firestore/local/mutation.pb.cc +++ b/Firestore/Protos/cpp/firestore/local/mutation.pb.cc @@ -112,6 +112,7 @@ const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUT GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::firestore::client::WriteBatch, batch_id_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::firestore::client::WriteBatch, writes_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::firestore::client::WriteBatch, local_write_time_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::firestore::client::WriteBatch, base_writes_), }; static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { { 0, -1, sizeof(::firestore::client::MutationQueue)}, @@ -150,14 +151,16 @@ void AddDescriptorsImpl() { "te.proto\032\037google/protobuf/timestamp.prot" "o\"N\n\rMutationQueue\022\"\n\032last_acknowledged_" "batch_id\030\001 \001(\005\022\031\n\021last_stream_token\030\002 \001(" - "\014\"\205\001\n\nWriteBatch\022\020\n\010batch_id\030\001 \001(\005\022/\n\006wr" + "\014\"\273\001\n\nWriteBatch\022\020\n\010batch_id\030\001 \001(\005\022/\n\006wr" "ites\030\002 \003(\0132\037.google.firestore.v1beta1.Wr" "ite\0224\n\020local_write_time\030\003 \001(\0132\032.google.p" - "rotobuf.TimestampB/\n#com.google.firebase" - ".firestore.protoP\001\242\002\005FSTPBb\006proto3" + "rotobuf.Timestamp\0224\n\013base_writes\030\004 \003(\0132\037" + ".google.firestore.v1beta1.WriteB/\n#com.g" + "oogle.firebase.firestore.protoP\001\242\002\005FSTPB" + "b\006proto3" }; ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( - descriptor, 394); + descriptor, 448); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "firestore/local/mutation.proto", &protobuf_RegisterTypes); ::protobuf_google_2ffirestore_2fv1beta1_2fwrite_2eproto::AddDescriptors(); @@ -476,10 +479,14 @@ void WriteBatch::clear_local_write_time() { } local_write_time_ = NULL; } +void WriteBatch::clear_base_writes() { + base_writes_.Clear(); +} #if !defined(_MSC_VER) || _MSC_VER >= 1900 const int WriteBatch::kBatchIdFieldNumber; const int WriteBatch::kWritesFieldNumber; const int WriteBatch::kLocalWriteTimeFieldNumber; +const int WriteBatch::kBaseWritesFieldNumber; #endif // !defined(_MSC_VER) || _MSC_VER >= 1900 WriteBatch::WriteBatch() @@ -494,6 +501,7 @@ WriteBatch::WriteBatch(const WriteBatch& from) : ::google::protobuf::Message(), _internal_metadata_(NULL), writes_(from.writes_), + base_writes_(from.base_writes_), _cached_size_(0) { _internal_metadata_.MergeFrom(from._internal_metadata_); if (from.has_local_write_time()) { @@ -551,6 +559,7 @@ void WriteBatch::Clear() { (void) cached_has_bits; writes_.Clear(); + base_writes_.Clear(); if (GetArenaNoVirtual() == NULL && local_write_time_ != NULL) { delete local_write_time_; } @@ -606,6 +615,17 @@ bool WriteBatch::MergePartialFromCodedStream( break; } + // repeated .google.firestore.v1beta1.Write base_writes = 4; + case 4: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(input, add_base_writes())); + } else { + goto handle_unusual; + } + break; + } + default: { handle_unusual: if (tag == 0) { @@ -650,6 +670,13 @@ void WriteBatch::SerializeWithCachedSizes( 3, *this->local_write_time_, output); } + // repeated .google.firestore.v1beta1.Write base_writes = 4; + for (unsigned int i = 0, + n = static_cast(this->base_writes_size()); i < n; i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 4, this->base_writes(static_cast(i)), output); + } + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); @@ -684,6 +711,14 @@ ::google::protobuf::uint8* WriteBatch::InternalSerializeWithCachedSizesToArray( 3, *this->local_write_time_, deterministic, target); } + // repeated .google.firestore.v1beta1.Write base_writes = 4; + for (unsigned int i = 0, + n = static_cast(this->base_writes_size()); i < n; i++) { + target = ::google::protobuf::internal::WireFormatLite:: + InternalWriteMessageToArray( + 4, this->base_writes(static_cast(i)), deterministic, target); + } + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); @@ -712,6 +747,17 @@ size_t WriteBatch::ByteSizeLong() const { } } + // repeated .google.firestore.v1beta1.Write base_writes = 4; + { + unsigned int count = static_cast(this->base_writes_size()); + total_size += 1UL * count; + for (unsigned int i = 0; i < count; i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSize( + this->base_writes(static_cast(i))); + } + } + // .google.protobuf.Timestamp local_write_time = 3; if (this->has_local_write_time()) { total_size += 1 + @@ -756,6 +802,7 @@ void WriteBatch::MergeFrom(const WriteBatch& from) { (void) cached_has_bits; writes_.MergeFrom(from.writes_); + base_writes_.MergeFrom(from.base_writes_); if (from.has_local_write_time()) { mutable_local_write_time()->::google::protobuf::Timestamp::MergeFrom(from.local_write_time()); } @@ -789,6 +836,7 @@ void WriteBatch::Swap(WriteBatch* other) { void WriteBatch::InternalSwap(WriteBatch* other) { using std::swap; writes_.InternalSwap(&other->writes_); + base_writes_.InternalSwap(&other->base_writes_); swap(local_write_time_, other->local_write_time_); swap(batch_id_, other->batch_id_); _internal_metadata_.Swap(&other->_internal_metadata_); diff --git a/Firestore/Protos/cpp/firestore/local/mutation.pb.h b/Firestore/Protos/cpp/firestore/local/mutation.pb.h index 99067911aeb..7260914e6a6 100644 --- a/Firestore/Protos/cpp/firestore/local/mutation.pb.h +++ b/Firestore/Protos/cpp/firestore/local/mutation.pb.h @@ -292,6 +292,18 @@ class WriteBatch : public ::google::protobuf::Message /* @@protoc_insertion_poin const ::google::protobuf::RepeatedPtrField< ::google::firestore::v1beta1::Write >& writes() const; + // repeated .google.firestore.v1beta1.Write base_writes = 4; + int base_writes_size() const; + void clear_base_writes(); + static const int kBaseWritesFieldNumber = 4; + const ::google::firestore::v1beta1::Write& base_writes(int index) const; + ::google::firestore::v1beta1::Write* mutable_base_writes(int index); + ::google::firestore::v1beta1::Write* add_base_writes(); + ::google::protobuf::RepeatedPtrField< ::google::firestore::v1beta1::Write >* + mutable_base_writes(); + const ::google::protobuf::RepeatedPtrField< ::google::firestore::v1beta1::Write >& + base_writes() const; + // .google.protobuf.Timestamp local_write_time = 3; bool has_local_write_time() const; void clear_local_write_time(); @@ -312,6 +324,7 @@ class WriteBatch : public ::google::protobuf::Message /* @@protoc_insertion_poin ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; ::google::protobuf::RepeatedPtrField< ::google::firestore::v1beta1::Write > writes_; + ::google::protobuf::RepeatedPtrField< ::google::firestore::v1beta1::Write > base_writes_; ::google::protobuf::Timestamp* local_write_time_; ::google::protobuf::int32 batch_id_; mutable int _cached_size_; @@ -486,6 +499,33 @@ inline void WriteBatch::set_allocated_local_write_time(::google::protobuf::Times // @@protoc_insertion_point(field_set_allocated:firestore.client.WriteBatch.local_write_time) } +// repeated .google.firestore.v1beta1.Write base_writes = 4; +inline int WriteBatch::base_writes_size() const { + return base_writes_.size(); +} +inline const ::google::firestore::v1beta1::Write& WriteBatch::base_writes(int index) const { + // @@protoc_insertion_point(field_get:firestore.client.WriteBatch.base_writes) + return base_writes_.Get(index); +} +inline ::google::firestore::v1beta1::Write* WriteBatch::mutable_base_writes(int index) { + // @@protoc_insertion_point(field_mutable:firestore.client.WriteBatch.base_writes) + return base_writes_.Mutable(index); +} +inline ::google::firestore::v1beta1::Write* WriteBatch::add_base_writes() { + // @@protoc_insertion_point(field_add:firestore.client.WriteBatch.base_writes) + return base_writes_.Add(); +} +inline ::google::protobuf::RepeatedPtrField< ::google::firestore::v1beta1::Write >* +WriteBatch::mutable_base_writes() { + // @@protoc_insertion_point(field_mutable_list:firestore.client.WriteBatch.base_writes) + return &base_writes_; +} +inline const ::google::protobuf::RepeatedPtrField< ::google::firestore::v1beta1::Write >& +WriteBatch::base_writes() const { + // @@protoc_insertion_point(field_list:firestore.client.WriteBatch.base_writes) + return base_writes_; +} + #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ diff --git a/Firestore/Protos/nanopb/firestore/local/mutation.nanopb.cc b/Firestore/Protos/nanopb/firestore/local/mutation.nanopb.cc index f1e606a8991..2dae91555cc 100644 --- a/Firestore/Protos/nanopb/firestore/local/mutation.nanopb.cc +++ b/Firestore/Protos/nanopb/firestore/local/mutation.nanopb.cc @@ -35,10 +35,11 @@ const pb_field_t firestore_client_MutationQueue_fields[3] = { PB_LAST_FIELD }; -const pb_field_t firestore_client_WriteBatch_fields[4] = { +const pb_field_t firestore_client_WriteBatch_fields[5] = { PB_FIELD( 1, INT32 , SINGULAR, STATIC , FIRST, firestore_client_WriteBatch, batch_id, batch_id, 0), PB_FIELD( 2, MESSAGE , REPEATED, POINTER , OTHER, firestore_client_WriteBatch, writes, batch_id, &google_firestore_v1beta1_Write_fields), PB_FIELD( 3, MESSAGE , SINGULAR, STATIC , OTHER, firestore_client_WriteBatch, local_write_time, writes, &google_protobuf_Timestamp_fields), + PB_FIELD( 4, MESSAGE , REPEATED, POINTER , OTHER, firestore_client_WriteBatch, base_writes, local_write_time, &google_firestore_v1beta1_Write_fields), PB_LAST_FIELD }; diff --git a/Firestore/Protos/nanopb/firestore/local/mutation.nanopb.h b/Firestore/Protos/nanopb/firestore/local/mutation.nanopb.h index 3403fd095b7..45944119757 100644 --- a/Firestore/Protos/nanopb/firestore/local/mutation.nanopb.h +++ b/Firestore/Protos/nanopb/firestore/local/mutation.nanopb.h @@ -46,6 +46,8 @@ typedef struct _firestore_client_WriteBatch { pb_size_t writes_count; struct _google_firestore_v1beta1_Write *writes; google_protobuf_Timestamp local_write_time; + pb_size_t base_writes_count; + struct _google_firestore_v1beta1_Write *base_writes; /* @@protoc_insertion_point(struct:firestore_client_WriteBatch) */ } firestore_client_WriteBatch; @@ -53,9 +55,9 @@ typedef struct _firestore_client_WriteBatch { /* Initializer values for message structs */ #define firestore_client_MutationQueue_init_default {0, NULL} -#define firestore_client_WriteBatch_init_default {0, 0, NULL, google_protobuf_Timestamp_init_default} +#define firestore_client_WriteBatch_init_default {0, 0, NULL, google_protobuf_Timestamp_init_default, 0, NULL} #define firestore_client_MutationQueue_init_zero {0, NULL} -#define firestore_client_WriteBatch_init_zero {0, 0, NULL, google_protobuf_Timestamp_init_zero} +#define firestore_client_WriteBatch_init_zero {0, 0, NULL, google_protobuf_Timestamp_init_zero, 0, NULL} /* Field tags (for use in manual encoding/decoding) */ #define firestore_client_MutationQueue_last_acknowledged_batch_id_tag 1 @@ -63,10 +65,11 @@ typedef struct _firestore_client_WriteBatch { #define firestore_client_WriteBatch_batch_id_tag 1 #define firestore_client_WriteBatch_writes_tag 2 #define firestore_client_WriteBatch_local_write_time_tag 3 +#define firestore_client_WriteBatch_base_writes_tag 4 /* Struct field encoding specification for nanopb */ extern const pb_field_t firestore_client_MutationQueue_fields[3]; -extern const pb_field_t firestore_client_WriteBatch_fields[4]; +extern const pb_field_t firestore_client_WriteBatch_fields[5]; /* Maximum encoded size of messages (where known) */ /* firestore_client_MutationQueue_size depends on runtime parameters */ diff --git a/Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h b/Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h index 60491e92f0e..5790e330d76 100644 --- a/Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h +++ b/Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h @@ -102,6 +102,7 @@ typedef GPB_ENUM(FSTPBWriteBatch_FieldNumber) { FSTPBWriteBatch_FieldNumber_BatchId = 1, FSTPBWriteBatch_FieldNumber_WritesArray = 2, FSTPBWriteBatch_FieldNumber_LocalWriteTime = 3, + FSTPBWriteBatch_FieldNumber_BaseWritesArray = 4, }; /** @@ -127,6 +128,22 @@ typedef GPB_ENUM(FSTPBWriteBatch_FieldNumber) { /** Test to see if @c localWriteTime has been set. */ @property(nonatomic, readwrite) BOOL hasLocalWriteTime; +/** + * A list of "writes" that represent a partial base state from when this + * write batch was initially created. During local application of the write + * batch, these base_writes are applied prior to the real writes in order to + * override certain document fields from the remote document cache. This is + * necessary in the case of non-idempotent writes (e.g. numericAdd + * transforms) to make sure that the local view of the modified documents + * doesn't flicker if the remote document cache receives the result of the + * non-idempotent write before the write is removed from the queue. + * + * These writes are never sent to the backend. + **/ +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *baseWritesArray; +/** The number of items in @c baseWritesArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger baseWritesArray_Count; + @end NS_ASSUME_NONNULL_END diff --git a/Firestore/Protos/objc/firestore/local/Mutation.pbobjc.m b/Firestore/Protos/objc/firestore/local/Mutation.pbobjc.m index 642922a78be..5c88e90fa11 100644 --- a/Firestore/Protos/objc/firestore/local/Mutation.pbobjc.m +++ b/Firestore/Protos/objc/firestore/local/Mutation.pbobjc.m @@ -126,12 +126,14 @@ @implementation FSTPBWriteBatch @dynamic batchId; @dynamic writesArray, writesArray_Count; @dynamic hasLocalWriteTime, localWriteTime; +@dynamic baseWritesArray, baseWritesArray_Count; typedef struct FSTPBWriteBatch__storage_ { uint32_t _has_storage_[1]; int32_t batchId; NSMutableArray *writesArray; GPBTimestamp *localWriteTime; + NSMutableArray *baseWritesArray; } FSTPBWriteBatch__storage_; // This method is threadsafe because it is initially called @@ -167,6 +169,15 @@ + (GPBDescriptor *)descriptor { .flags = GPBFieldOptional, .dataType = GPBDataTypeMessage, }, + { + .name = "baseWritesArray", + .dataTypeSpecific.className = GPBStringifySymbol(GCFSWrite), + .number = FSTPBWriteBatch_FieldNumber_BaseWritesArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(FSTPBWriteBatch__storage_, baseWritesArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, }; GPBDescriptor *localDescriptor = [GPBDescriptor allocDescriptorForClass:[FSTPBWriteBatch class] diff --git a/Firestore/Protos/protos/firestore/local/mutation.proto b/Firestore/Protos/protos/firestore/local/mutation.proto index ea448c89a64..8f9607d56d5 100644 --- a/Firestore/Protos/protos/firestore/local/mutation.proto +++ b/Firestore/Protos/protos/firestore/local/mutation.proto @@ -55,4 +55,16 @@ message WriteBatch { // The local time at which the write batch was initiated. google.protobuf.Timestamp local_write_time = 3; + + // A list of "writes" that represent a partial base state from when this + // write batch was initially created. During local application of the write + // batch, these base_writes are applied prior to the real writes in order to + // override certain document fields from the remote document cache. This is + // necessary in the case of non-idempotent writes (e.g. numericAdd + // transforms) to make sure that the local view of the modified documents + // doesn't flicker if the remote document cache receives the result of the + // non-idempotent write before the write is removed from the queue. + // + // These writes are never sent to the backend. + repeated google.firestore.v1beta1.Write base_writes = 4; } From 35456b453d03e3ff048407f34fdbae22d80ac674 Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Mon, 12 Nov 2018 16:25:02 -0800 Subject: [PATCH 2/2] Review comments --- Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h | 6 +++--- Firestore/Protos/protos/firestore/local/mutation.proto | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h b/Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h index 5790e330d76..9091ba6dd38 100644 --- a/Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h +++ b/Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h @@ -129,9 +129,9 @@ typedef GPB_ENUM(FSTPBWriteBatch_FieldNumber) { @property(nonatomic, readwrite) BOOL hasLocalWriteTime; /** - * A list of "writes" that represent a partial base state from when this - * write batch was initially created. During local application of the write - * batch, these base_writes are applied prior to the real writes in order to + * A list of pseudo-writes that represent a partial base state from when this + * write batch was initially created. When computing the local view batch, + * these base_writes are applied prior to the real writes in order to * override certain document fields from the remote document cache. This is * necessary in the case of non-idempotent writes (e.g. numericAdd * transforms) to make sure that the local view of the modified documents diff --git a/Firestore/Protos/protos/firestore/local/mutation.proto b/Firestore/Protos/protos/firestore/local/mutation.proto index 8f9607d56d5..9de9a6bdaf5 100644 --- a/Firestore/Protos/protos/firestore/local/mutation.proto +++ b/Firestore/Protos/protos/firestore/local/mutation.proto @@ -56,9 +56,9 @@ message WriteBatch { // The local time at which the write batch was initiated. google.protobuf.Timestamp local_write_time = 3; - // A list of "writes" that represent a partial base state from when this - // write batch was initially created. During local application of the write - // batch, these base_writes are applied prior to the real writes in order to + // A list of pseudo-writes that represent a partial base state from when this + // write batch was initially created. When computing the local view batch, + // these base_writes are applied prior to the real writes in order to // override certain document fields from the remote document cache. This is // necessary in the case of non-idempotent writes (e.g. numericAdd // transforms) to make sure that the local view of the modified documents