Skip to content
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(transport): Return result through Transport send #6626

Merged
merged 6 commits into from Jan 5, 2023

Conversation

timfish
Copy link
Collaborator

@timfish timfish commented Dec 29, 2022

For it to be possible to wrap the transport for offline support (#6403), wrapping transports need to be able to cater for rate limiting and therefore send needs to return TransportMakeRequestResponse rather than void. To move in this direction while minimising breaking changes, this PR changes the return to Promise<void | TransportMakeRequestResponse>.

This PR changes the logic so that send now throws in failure cases. This is not a concern for internal code because the two places it's called errors are caught and logged:

this._transport.send(envelope).then(null, reason => {
__DEBUG_BUILD__ && logger.error('Error while sending event:', reason);
});

try {
return await transport.send(envelope);
} catch {
throw new Error(UNABLE_TO_SEND_REPLAY);
}

The only real risk I see here is if customers are manually calling transport.send and have come to expect that it never throws.

@timfish timfish marked this pull request as draft December 29, 2022 12:20
@timfish timfish marked this pull request as ready for review December 29, 2022 16:23
@timfish timfish self-assigned this Dec 30, 2022
@mydea mydea requested review from a team, mydea, lobsterkatie, lforst and Lms24 and removed request for a team January 4, 2023 12:43
Copy link
Member

@Lms24 Lms24 left a comment

Choose a reason for hiding this comment

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

The only real risk I see here is if customers are manually calling transport.send and have come to expect that it never throws.

So this could be considered behaviorally breaking, for custom transport implementations based on the base transport, right?
Any chance that we can still return the response and not throw? Or do you need it to throw for your transport?

@timfish
Copy link
Collaborator Author

timfish commented Jan 4, 2023

So this could be considered behaviourally breaking, for custom transport implementations based on the base transport, right?

No, this does not change the behaviour, or expected behaviour of any existing transports or custom transports. A custom TransportRequestExecutor passed into createTransport has always been able to throw or not but errors were logged and ignored by createTransport.

Re-throwing the error here will only impact those that call the send function on Transport. So from a public API perspective, this would only result in behavioural changes for anyone calling client.getTransport().send(envelope).

@lforst
Copy link
Member

lforst commented Jan 4, 2023

Do you have a plan on doing something when the error is thrown? Otherwise I would just leave it be for now.

@timfish
Copy link
Collaborator Author

timfish commented Jan 4, 2023

Do you have a plan on doing something when the error is thrown?

Yes, since an exception is the main failure mode for most of the TransportRequestExecutor implementations when the DSN cannot be resolved, (ie. while offline) this would be used to signal that the envelope should be queued and retried later.

We don't actually care about the exception type or any of the details though so I could alternatively include a flag in TransportMakeRequestResponse:

export type TransportMakeRequestResponse = {
  statusCode?: number;
  headers?: {
    [key: string]: string | null;
    'x-sentry-rate-limits': string | null;
    'retry-after': string | null;
  };
  failed?: true
};

So in createTransport, any caught errors would be converted to { failed: true }.

The main issue with this is that it might be confusing to those who are implementing transports. Should your custom transport throw or return { failed: true }? If a TransportRequestExecutor returns { failed: true }, should we treat it like an exception?

@lforst
Copy link
Member

lforst commented Jan 5, 2023

Do you have a plan on doing something when the error is thrown?

Yes, since an exception is the main failure mode for most of the TransportRequestExecutor implementations when the DSN cannot be resolved, (ie. while offline) this would be used to signal that the envelope should be queued and retried later.

We don't actually care about the exception type or any of the details though so I could alternatively include a flag in TransportMakeRequestResponse:

export type TransportMakeRequestResponse = {
  statusCode?: number;
  headers?: {
    [key: string]: string | null;
    'x-sentry-rate-limits': string | null;
    'retry-after': string | null;
  };
  failed?: true
};

So in createTransport, any caught errors would be converted to { failed: true }.

The main issue with this is that it might be confusing to those who are implementing transports. Should your custom transport throw or return { failed: true }? If a TransportRequestExecutor returns { failed: true }, should we treat it like an exception?

Ok thought about this way longer than I probably should. I think throwing is fine and it might have even been an oversight not to throw there in the first place. The only thing I would do is remove the log message on line 89 to only log in the place where we're actually handling the error.

The same sentiment goes towards returning the result. We should probably have made send return PromiseLike<TransportMakeRequestResponse> in the first place.

I say let's go through with it!

@timfish
Copy link
Collaborator Author

timfish commented Jan 5, 2023

I would do is remove the log message on line 89

Oh yes, this will result in logging the error twice!

We should probably have made send return PromiseLike<TransportMakeRequestResponse> in the first place

I'll add a TODO (v8) comment to remove void in the next major.

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.

None yet

3 participants