Skip to content

Conversation

@hiranya911
Copy link
Contributor

Implementing the following new API:

sendAll(messages: Message[], dryRun?: boolean): Promise<BatchResponse>

This implements a part of go/fcm-multicast. I've also implemented the following refactorings in order to keep the size of the messaging.ts module in check:

  • Moved all the type definitions and their util functions to a new messaging-types.ts module.
  • Moved the error handling/parsing logic to a new messaging-errors.ts module.

There's more room for refactoring here, but I would rather do that in separate PRs.

Copy link
Contributor

@bojeil-google bojeil-google left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mostly have nits and some recommendations for providing samples and splitting some code to make it easier to follow. It would make the review easier. I haven't covered the entire PR yet.

constructor(resp: LowLevelResponse) {
this.status = resp.status;
this.headers = resp.headers;
this.multipart = resp.multipart;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should you validate it is an actually multipart response?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class is not exported, and we control the only place where it gets instantiated. So it should be fine.

respStream.on('data', (chunk: Buffer) => {
responseBuffer.push(chunk);
});
const boundary = getMultipartBoundary(res.headers);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sendRequest has become too large, is there a way we can split it to be more manageable? or create smaller functions to handle different parts of the logic?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not easy due to the use of new Promise() but I think we can do some improvements. However, I'd rather do that as a separate PR.

const headerLines: string[] = responseText.substring(0, endOfHeaderPos).split('\r\n');

const statusLine: string = headerLines[0];
const status: string = statusLine.trim().split(/\s/)[1];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validate that the array has >=2 elements and before that headerLines has at least 1 element.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

slice(1) returns an empty array when length is less than 2. So it's safe to iterate over it without a length check. Similarly, headerLines is the result of a split() call, which always returns an array with at least 1 element.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only see that you are using split here and not slice:
statusLine.trim().split(/\s/)[1]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use split and slice for headerLines. For statusLine I added a check to cover the case of a malformed header. Although chances of it happening should be negligibly small.

@hiranya911
Copy link
Contributor Author

Thanks @bojeil-google. I've responded to your comments. PTAL.

const headerLines: string[] = responseText.substring(0, endOfHeaderPos).split('\r\n');

const statusLine: string = headerLines[0];
const status: string = statusLine.trim().split(/\s/)[1];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only see that you are using split here and not slice:
statusLine.trim().split(/\s/)[1]

});

function parseHttpRequest(text: string | Buffer): any {
const httpMessageParser = require('http-message-parser');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: I think we should minimize depending on low usage npm modules. In this case, this has ~2k weekly downloads. We have been bitten by some dependency on an npm module that was abandoned in the past.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only use this in a couple of test cases. I can try to replace it with something else in a future PR.

).should.eventually.be.rejected.and.have.property('code', 'app/invalid-credential');
});

function checkSendResponseSuccess(response: SendResponse, messageId: string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: define helper functions on top of file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Moved to the top of the enclosing block. These helpers are scoped to a specific test case.

@hiranya911
Copy link
Contributor Author

Thanks @bojeil-google. I've addressed most of your comments.

* Implementing sendMulticast() API

* Added integration test

* Fixed a comment

* Readability improvement in the copy operation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants