-
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
feat: add starting/max rates to BulkWriterOptions #1305
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1305 +/- ##
==========================================
+ Coverage 98.46% 98.51% +0.04%
==========================================
Files 30 30
Lines 18648 18754 +106
Branches 1435 1450 +15
==========================================
+ Hits 18362 18475 +113
+ Misses 283 276 -7
Partials 3 3
Continue to review full report at Codecov.
|
14c5e88
to
a34c278
Compare
} | ||
} | ||
|
||
if ( |
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.
We can use validateInteger
with a NumericRangeOptions
to make sure that the provided numbers are >= 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.
Much better, done.
dev/src/bulk-writer.ts
Outdated
if (typeof options.disableThrottling !== 'boolean') { | ||
throw new Error( | ||
`${invalidArgumentMessage( | ||
arg, | ||
'bulkWriter() options argument' | ||
)} "disableThrottling" is not a boolean.` | ||
); | ||
} |
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.
We don't need to validate invalid TypeScript usage. You should only validate API input that is valid to the transpiler, but not to the SDK (such as disableThrottling
and initialOpsPerSecond
set together)
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.
describe('options', () => { | ||
it('requires object', async () => { | ||
const firestore = await createInstance(); | ||
expect(() => firestore.bulkWriter(42 as InvalidApiUsage)).to.throw( |
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.
You should be able to use //@ ts-expect-error
now: https://dev.to/oliverjumpertz/making-good-use-of-ts-expect-error-in-typescript-1f41
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'll try to keep this in mind for next time! I'll probably end up cutting out the validation code at some point, which means we won't have any InvalidApiUsage
instances that would otherwise require the expect-error comment.
types/firestore.d.ts
Outdated
readonly disableThrottling?: boolean; | ||
|
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.
A lot of the APIs I have been dealing with lately do the following:
export interface BulkWriterOptions {
readonly throttling?: boolean | {initialOpsPerSecond?: number; maxOpsPerSecond?: number; };
}
This would match terser and eslint, but we might want to gather more feedback (maybe from @Feiyang1).
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.
attempted
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.
Used the union types for BulkWriterOptions. I think my constructor logic could be cleaner -- please advise :)
I'll assign to Fei after you think it's in a good place.
} | ||
} | ||
|
||
if ( |
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.
Much better, done.
describe('options', () => { | ||
it('requires object', async () => { | ||
const firestore = await createInstance(); | ||
expect(() => firestore.bulkWriter(42 as InvalidApiUsage)).to.throw( |
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'll try to keep this in mind for next time! I'll probably end up cutting out the validation code at some point, which means we won't have any InvalidApiUsage
instances that would otherwise require the expect-error comment.
dev/src/bulk-writer.ts
Outdated
const startingRate = | ||
typeof options?.throttling !== 'boolean' && | ||
options?.throttling?.initialOpsPerSecond !== undefined | ||
? options.throttling.initialOpsPerSecond | ||
: STARTING_MAXIMUM_OPS_PER_SECOND; |
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 this is:
const startingRate = | |
typeof options?.throttling !== 'boolean' && | |
options?.throttling?.initialOpsPerSecond !== undefined | |
? options.throttling.initialOpsPerSecond | |
: STARTING_MAXIMUM_OPS_PER_SECOND; | |
const startingRate = options?.throttling?.initialOpsPerSecond ?? | |
STARTING_MAXIMUM_OPS_PER_SECOND; |
I tested it with this code:
const STARTING_MAXIMUM_OPS_PER_SECOND = 1337;
const options1 : any = {throttling:false};
const options2 : any = {throttling:true};
const options3 : any = {throttling:{initialOpsPerSecond:10}};
function printThrottler(options?:any) {
console.log(options?.throttling?.initialOpsPerSecond ??STARTING_MAXIMUM_OPS_PER_SECOND)
}
printThrottler(options1);
printThrottler(options2);
printThrottler(options3);
This prints 1337, 1337, 10.
Same 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.
Since it's a union type, initialOpsPerSecond
is not a number unless I explicity check it's not a boolean first.
With the additional change to lower the initial rate to match the max rate if it's below the default, I refactored it to use if statements, which is hopefully more readable.
dev/src/bulk-writer.ts
Outdated
* Validates the use of 'value' as BulkWriterOptions. | ||
* | ||
* @private | ||
* @param arg The argument name or argument index (for varargs methods). |
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.
You can probably be more specific since this is only used for BulkWriterOptions.
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.
removed used of arg
as a parameter.
dev/src/bulk-writer.ts
Outdated
* @param value The object to validate. | ||
* @throws if the input is not a valid BulkWriterOptions object. | ||
*/ | ||
function validateBulkWriterOptions(arg: string | number, value: unknown): void { |
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 can just 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.
done.
dev/src/bulk-writer.ts
Outdated
'initialOpsPerSecond', | ||
options.throttling.initialOpsPerSecond, | ||
{ | ||
minValue: 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.
This needs to be 1, doesn't it?
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/src/bulk-writer.ts
Outdated
|
||
if ('maxOpsPerSecond' in options.throttling) { | ||
validateInteger('maxOpsPerSecond', options.throttling.maxOpsPerSecond, { | ||
minValue: 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.
0 also doesn't quite work here.
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/src/bulk-writer.ts
Outdated
); | ||
} | ||
|
||
if ('maxOpsPerSecond' in options.throttling) { |
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.
If you change this to options.throttling.maxOpsPerSecond !== undefined
, you can get rid of the bang 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/src/bulk-writer.ts
Outdated
}); | ||
|
||
if ( | ||
'initialOpsPerSecond' in options.throttling && |
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.
Same: options.throttling. initialOpsPerSecond !== undefined
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/src/bulk-writer.ts
Outdated
!('initialOpsPerSecond' in options.throttling) && | ||
STARTING_MAXIMUM_OPS_PER_SECOND > options.throttling.maxOpsPerSecond! | ||
) { | ||
throw new Error( |
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 is pretty unexpected, especially since the default value is not known. We should instead adjust the starting value.
BTW, I think we should somehow squeeze DEFAULT
into the name of STARTING_MAXIMUM_OPS_PER_SECOND, since the constant is no longer required to be the maximum.
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.
*/ | ||
readonly throttling?: | ||
| boolean | ||
| {initialOpsPerSecond?: number; maxOpsPerSecond?: number}; |
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 the update. Did you check with @Feiyang1 if he thinks this is a useable API?
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 looks fine to me. Autocomplete will help people figure it out. Currently we are only describing the config params in the comment. I would make it clear in the comment that it can be either a boolean or a config object (boolean to enable/disable, config to enable and set config values).
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.
Was going to ask him after, but he jumped in :)
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 you also want to update the comment per Fei's suggestion?
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 thought I had already added some more to the comments, but this time around I also explicitly stated that setting it to false disables throttling.
dev/src/bulk-writer.ts
Outdated
@@ -351,22 +356,46 @@ export class BulkWriter { | |||
|
|||
constructor( | |||
private readonly firestore: Firestore, | |||
enableThrottling: boolean | |||
private readonly options?: firestore.BulkWriterOptions |
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.
private readonly options?: firestore.BulkWriterOptions | |
options?: firestore.BulkWriterOptions |
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.
*/ | ||
readonly throttling?: | ||
| boolean | ||
| {initialOpsPerSecond?: number; maxOpsPerSecond?: number}; |
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 you also want to update the comment per Fei's suggestion?
Following up from the 555 discussion by adding option to set the initial and maximum rate of the throttler in BulkWriter.