-
Notifications
You must be signed in to change notification settings - Fork 11
feat: queryOffset to return RMQ response code in the domain exception (resolves #283) #285
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
base: main
Are you sure you want to change the base?
feat: queryOffset to return RMQ response code in the domain exception (resolves #283) #285
Conversation
|
Hello @WhereJuly, please keep the PR focused on a single topic. |
|
Hey @l4mby. Thanks for the comment. The JSDoc blocks naturally followed the new functionality implementation. They are, kind of, immanent part of the PR, induced by the changes. Probably, formal separation is not appropriate here. What do you think? |
l4mby
left a comment
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 reviewed your code and found some inconsistencies with our style. Please fix it so we can proceed with the integration. Thank you.
PS: Did you use any AI tool? If yes can you please tell us which tool/model you have used?
|
|
||
| import { ResponseCode } from "../util" | ||
|
|
||
| export type TResponseCode = (typeof ResponseCode)[keyof typeof ResponseCode] |
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 don't think this type is necessary, we can just use a type number for the code
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.
@l4mby I see.
export default class RMQProtocolResponseError extends Error {
readonly #code: TResponseCode
constructor(message: string, rmqStreamResponseCode: TResponseCode) {
super(message)The retionale to narrow type of rmqStreamResponseCode is to not allow to provide any number whereas we actually expect only ResponseCode.
The type alias TResponseCode is for better clarity and readability - semantically and to not use that long typecast. So I believe we should keep it. Let me know your thought on this.
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.
Hi @WhereJuly the problem with this type TResponseCode is that force you to use the as like in the code below
const code = res.code as TResponseCodeAnd if you receive a number that is not present in ResponseCode you are forcing it. This is the reason about using a number and left the user to verify if it's a known code present in ResponseCode.
About the name, it could be useful to have an error we use instead of "generic error" but it not be too generic because not always can be used so I suggest: class StreamResponseError.
So this code could became:
export class StreamResponseError extends Error {
constructor(message: string, readonly errorCode: number) {
super(message)
}
}If you want to use the #errorCode instead the typescript version, it's fine I suggest to name the property errorCode or responseCode.
As side note we prefer don't use default export.
| * | ||
| */ | ||
| export default class Code51Exception extends Error { | ||
| readonly #code?: TResponseCode |
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 should use a more appropriate name for the error, specific to the queryoffset, for example QueryOffsetError could be ok. Also can you rename the property in code and make it mandatory?
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.
@l4mby Thank you. Understood. Wanted to discuss the following points.
code: make it mandatory
Will do.
more appropriate name for the error, specific to the queryoffset, for example
QueryOffsetError
I planned this error to be a generic error for the entire package. Now I see this seems too wide. On the other hand maybe QueryOffsetError is too specific?
Could it be better RMQProtocolResponseError or something like that to cater for all potential use cases with the protocol response code? To not end up with a number of several too specific error classes?
Also can you rename the property in code
I could but this is not name convention, # is the JS property visiblity level. It actually makes the JS (not TS) property private at runtime.
The reason to have it is to actually make it read-only at run time, accessibe only via a getter. Making it code we expose it at runtime. Do you still think we should not use JS private properties?
| throw new Error(`Query offset command returned error with code ${res.code}`) | ||
| const code = res.code as TResponseCode | ||
|
|
||
| throw new Code51Exception(`Query offset command returned error with code ${res.code}`, code) |
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.
Here since we will use the code as a number we can remove the as and throw directly the code in the constructor of QueryOffsetError
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.
@l4mby For this case I made an explanation here #285 (comment).
Shortly, my logic here is we better use the narrower type ResponseCode than wider number as the error class is going to accept only ResponseCode, so no reason to relax the expected type.
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.
Hi @WhereJuly as written above we try to avoid as because it's very dangerous.
|
Hello @l4mby. Thanks for the comments. Will return with the updated PR in the coming days. As I mentioned, are you OK with keeping the JSDocs related to exactly this PR in it?
For code I rarely use AI meaning there is no lines of code produced by AI and copy/pasted in my code. I do use Cline for VS Code code base explorations, sometimes debugging (with free Gemini flash 2.5 I believe). Outside VS Code I use ChatGPT Pro (earlier v3.5, v4o, v5 now) for many things code-wise except writing code. And if used as input, I always edit it heavily before putting into a codebase. Hope that answers the question :) Talk to you soon. |
|
Hi @WhereJuly thank you for the infos. Yes we talked about it internally and decided it's ok to keep the JSDoc in the PR. |
|
@l4mby Welcome and thank you :) I meant to make a separate PRs for the JSDocs when there is no accompanied code comes with that. Will do that in the future. |
- tdd the exception; - update src/utils.ts ResponseCode to add NoOffset member and add jsdoc;
d50d242 to
8dadbb9
Compare
|
@l4mby Messed with git history. Will make updates and open the new PR. |
|
Hey @l4mby. I made code updates corresponding to the And besdes the main subject, I am interested why you asked about my usage of AI? And what is your own stance on using it? Thank you. |
|
Hey @l4mby, just checking in, wanted to make sure my comments still reached you after the PR was closed. Reopened it just for the case. |
|
|
||
| import { ResponseCode } from "../util" | ||
|
|
||
| export type TResponseCode = (typeof ResponseCode)[keyof typeof ResponseCode] |
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.
Hi @WhereJuly the problem with this type TResponseCode is that force you to use the as like in the code below
const code = res.code as TResponseCodeAnd if you receive a number that is not present in ResponseCode you are forcing it. This is the reason about using a number and left the user to verify if it's a known code present in ResponseCode.
About the name, it could be useful to have an error we use instead of "generic error" but it not be too generic because not always can be used so I suggest: class StreamResponseError.
So this code could became:
export class StreamResponseError extends Error {
constructor(message: string, readonly errorCode: number) {
super(message)
}
}If you want to use the #errorCode instead the typescript version, it's fine I suggest to name the property errorCode or responseCode.
As side note we prefer don't use default export.
| throw new Error(`Query offset command returned error with code ${res.code}`) | ||
| const code = res.code as TResponseCode | ||
|
|
||
| throw new Code51Exception(`Query offset command returned error with code ${res.code}`, code) |
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.
Hi @WhereJuly as written above we try to avoid as because it's very dangerous.
| StreamDoesNotExist: 2, | ||
| SubscriptionIdDoesNotExist: 4, | ||
|
|
||
| // Used in src/connection.ts/Connection.queryOffset method |
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 comment could became stale easely please remove it.
| /** | ||
| * Provides distinct domain exception for the package. Contains the optional | ||
| * RabbitMQ Stream protocol response code for more convenient processing. | ||
| * | ||
| * @param message A custom error message. | ||
| * @param rmqStreamResponseCode The above mentioned response code. | ||
| * | ||
| * @see https://github.com/rabbitmq/rabbitmq-server/blob/main/deps/rabbitmq_stream/docs/PROTOCOL.adoc#response-codes | ||
| * | ||
| * @example Selectively manage the exception type and react differently. | ||
| * | ||
| * ```typescript | ||
| * let result: any; | ||
| * | ||
| * const isRethrowable = (error_: Error) => { | ||
| * const isGenericError = error_ instanceof Code51Exception; | ||
| * const isNonManagedResponseCode = (error_ as Code51Exception).code !== ResponseCode.NoOffset; | ||
| * | ||
| * return isGenericError && isNonManagedResponseCode; | ||
| * }; | ||
| * | ||
| * try { | ||
| * result = consumer.queryOffset(); | ||
| * // ... process result | ||
| * } catch (error_) { | ||
| * if (isRethrowable(error_)) { throw error_; } | ||
| * | ||
| * const error = error_ as Code51Exception; | ||
| * if (error.code === ResponseCode.NoOffset) { return null; } | ||
| * | ||
| * return result; | ||
| * } | ||
| * ``` | ||
| * |
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 suggest to keep the description related to the field of class.
We could provide a guard function in this file to verify if the error is StreamResponseError something like:
function isStreamResponseError(error: unknown): error is StreamResponseError {
return ... // shoudl return a boolean value
}|
Hey @gpad, thanks for the response :) I just had a quick glance, it all looked fine. I will return to the PR in the coming days. Hope to complete it then. Cheers. |
Hey Team,
In response to #283 issue.
Before: the
src\connection.ts->Connection.queryOffsetthrew the generic Error with a string variable for any RabbitMQ stream protocol response code including NO_OFFSET (19). See more in [Question] Query offset command returned error with code 19 #283.After: the
src\connection.ts->Connection.queryOffsetthrows the domain exceptionsrc\application\Code51Exception.tswith a dedicated code field. See the usage example in the class JSDoc block.The main changes introduced:
src\application\Code51Exception.tsto carry the response code along the error message, tested withtest\unit\application\Code51Exception.test.tsNoOffsetmember intosrc\util.ts->ResponseCodesrc\application\Code51Exception.ts->TResponseCodetype alias to simplify the response code parameters description.A number of JSDoc blocks in:
src\connection.ts:storeOffset,queryOffsetsrc\util.ts:ResponseCodesrc\client.ts:DeclareConsumerParams,StoreOffsetParams,QueryOffsetParamsThe CI attempt went well.
Thanks.