-
Notifications
You must be signed in to change notification settings - Fork 147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: support byte values in Bundles #1395
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1395 +/- ##
==========================================
- Coverage 98.51% 98.50% -0.01%
==========================================
Files 32 32
Lines 19392 19397 +5
Branches 1273 1362 +89
==========================================
+ Hits 19104 19107 +3
- Misses 284 286 +2
Partials 4 4
Continue to review full report at Codecov.
|
const message = BundleElement.fromObject(bundleElement).toJSON(); | ||
const buffer = Buffer.from(JSON.stringify(message), 'utf-8'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's talk about this offline later, but this is quite an expensive operation. The steps are:
- Manually serialize documents in ProtobufJS format
- Read elements back Protobuf JS and convert to Proto3 JSON
- Parse Proto3 JSON into string
This seems like an okay "quick fix", but not the most elegant solution. We should figure out whether we are ok with this quick fix or whether we should directly produce Proto3 JSON. We could use a similar approach as the Web SDK and use different serialization options in our serializer depending on the target. While this might end up being a fair amount of work, it also helps us with the timestamp conversion.
Furthermore, can you verify whether the current conversion correctly translates numbers greater than 2^53 bits? You would have to turn on useBigInt and then write a large integer value like such: 2147483647n
. I am asking because the JSON roundtrip might convert this type to a lossy floating point representation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a test for BigInt.
dev/src/bundle.ts
Outdated
@@ -41,7 +42,6 @@ export class BundleBuilder { | |||
private latestReadTime = new Timestamp(0, 0); | |||
|
|||
constructor(readonly bundleId: string) {} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should add this back.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
dev/system-test/firestore.ts
Outdated
import BundledDocumentMetadata = firestore.BundledDocumentMetadata; | ||
import IBundleElement = firestore.IBundleElement; | ||
import NamedQuery = firestore.NamedQuery; | ||
import Document = google.firestore.v1.Document; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you move these imports to a different "section" (separated by a blank space below)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
dev/system-test/firestore.ts
Outdated
structuredQuery: query.toProto().structuredQuery, | ||
} | ||
), | ||
}).toJSON() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have to do this round-trip here (and below)? Can we not just compare against the resulting JSON directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The trick here is the expected object we use here will have int64 encoded as number, while the actual object we get from bundles have them encoded as strings, for example.
I have created some utility functions to help with the boilerplate. Unfortunately i cannot figure out how to make them generic, because fromObject
is static, and returns different types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it not possible to manually create the desired Proto output? Would it be possible to write expect(...).to.deep.equal({integerValue:'1337'}))
instead of expect(...).to.deep.equal(fromJson({integerValue:1337}).toJSON()))
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works for the example you give. But the tests deal a lot with timestamps, and expect(...).to.deep.equal(snap.readTime.toProto.timestampValue)
will compare encoded string seconds
to the actual integer value. So you get tests failures like:
- "seconds": "1577836805"
+ "seconds": 1577836805
dev/test/bundle.ts
Outdated
} | ||
expect(meta.id).to.equal(TEST_BUNDLE_ID); | ||
expect(meta.version).to.equal(TEST_BUNDLE_VERSION); | ||
expect(meta.totalDocuments).to.equal(totalDocuments); | ||
expect(meta.createTime).to.deep.equal(createTime); | ||
expect(google.protobuf.Timestamp.fromObject(meta.createTime!)).to.deep.equal( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please update the tests to not use the JSON helpers as it hides bugs in the JSON creation.
@@ -43,12 +43,14 @@ import { | |||
postConverterMerge, | |||
verifyInstance, | |||
} from '../test/util/helpers'; | |||
import IBundleElement = firestore.IBundleElement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for re-ordering. Can you remove the empty line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -37,17 +38,17 @@ export function verifyMetadata( | |||
expectEmptyContent = false | |||
): void { | |||
if (!expectEmptyContent) { | |||
expect(meta.totalBytes).greaterThan(0); | |||
expect(parseInt(meta.totalBytes!.toString())).greaterThan(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can probably emit toString() here (totalBytes should be a string).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's there to silent the type error, it can be number or string.
Co-authored-by: Sebastian Schmidt <mrschmidt@google.com>
Co-authored-by: Sebastian Schmidt <mrschmidt@google.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rubber stamp because I broke CODEOWNERs
No description provided.