-
-
Notifications
You must be signed in to change notification settings - Fork 100
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: apply traits to standalone messages from components section #214
fix: apply traits to standalone messages from components section #214
Conversation
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.
Welcome to AsyncAPI. Thanks a lot for creating your first pull request.
Keep in mind there are also other channels you can use to interact with AsyncAPI community. For more details check out this issue.
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.
One thing to fix :) Thanks for contribution!
The problem is here parser-js/lib/models/asyncapi.js Line 78 in d35d59a
components . We only traverse schemas in channels.message , components.parameters and component.schemas . @derberg should we fix it in this PR or leave it as a followup?
|
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 tried to give it a shot but I am not really sure if the provided function is at the right place and also how the validateAndConvertMessage function works.
It looks good, thanks a bunch for jumping into it 🙇🏼
@magicmatatjahu explained well what is the purpose of this function. I'm only afraid that with the current implementation we will have messages (the ones from components.messages that are referred to channels) that are validated and converted twice, like this one -> https://github.com/asyncapi/parser-js/pull/214/files#diff-b335089706650932f2429d8b648707a16777501ad4e410fcbd35be14900707d8R14 which is a performance issue in my opinion because in large componentized specs with channels the validation will simply be doubled 🤔 I'm opened for suggestions 😄
I included the "x-parser-schema-id":"" properties in the output schemas as far as I understood them. Unfortunately, they are only generated for messages that are used in a channel and not the standalone messages. I assume you would know how to fix those problems?
a simple fix would bring the same issue as in my previous comment, I think. Anonymous schema id goes only to messages in channels. That would be too much for this PR for you to solve, and anyway it is a different topic that requires separate PR. Could you please create a separate issue, please 🙏🏼
I made code change suggestions that you can apply for now.
Besides, npm run test-browser was not working on my machine (OSX) from the beginning I cloned the repo. I am on node v12.14.1.
it was not working because of the missing condition @magicmatatjahu mentioned in one of his comments. Spec used in the browser test is as simple as
asyncapi: 2.0.0
info:
title: My API
version: 1.0.0
channels:
"/test/tester":
subscribe:
message: {}
so it covers exactly the same case that @magicmatatjahu described, a spec without messages in components, and in fact, no components object at all. It would be awesome if you could add a test case for such a document to parse_test
🙏🏼
As a side note, I will create a PR to console log errors in the browser test, so nobody has to disable the headless mode of the browser and dig every issue on his/her own
last but not least -> you can take this PR out from draft to enable tests as you are pretty advanced with this PR and we anyway jumped into the review
Co-authored-by: Lukasz Gornicki <[email protected]>
Co-authored-by: Lukasz Gornicki <[email protected]>
added the guard that
I tried to give it a thought but I guess that would require to somehow apply the traits in conjunction with resolving the |
@c-pius trying to combine it with resolving of I like your idea about simple remembering that messages were processed already. Just remember it is not just What if we revert the order? like process Messages from components first, and then Channels. Then in the case of
The only real concern is But in general, it makes sense right? to process messages from components first, and then just process those unprocessed that are directly under channels? |
Actually I had already tried this using a check if the Regarding the name of the marker property I don't really mind any. I guess I assume you intended it to be |
@c-pius yeap, |
I'm just afraid about |
actually I would have put checking and setting the async function validateAndConvertMessage(msg, originalAsyncAPIDocument, fileFormat, parsedAsyncAPIDocument, pathToPayload) {
if (xParserValidated in msg && msg[xParserValidated] === true) {
//only validate the message if it has not been done before
return
}
//... function logic
msg[xParserValidated] = true
} or do you prefer it to be only added for components/messages and removed again afterwards? |
you are right, good approach with having the logic in I'm not 100% sure if what about
and default parser should do it too -> https://github.com/asyncapi/parser-js/blob/master/lib/asyncapiSchemaFormatParser.js. And it would just have to be clearly described in the readme that every custom parser must add those fields to the document Thoughts? |
Like the idea. Also similar to the x parser original trait approach then. Updated the PR already. Does that reflect what you meant?
Not sure how to handle this one though? From reading the existing doc I would have assumed to put it in the comment for the |
@c-pius I think adding a comment to |
lib/parser.js
Outdated
@@ -190,6 +195,7 @@ async function validateAndConvertMessage(msg, originalAsyncAPIDocument, fileForm | |||
}); | |||
|
|||
msg.schemaFormat = DEFAULT_SCHEMA_FORMAT; | |||
msg[String(xParserOriginalSchemaFormat)] = schemaFormat; |
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.
code from https://github.com/asyncapi/parser-js/pull/214/files#diff-2f45270c7389933f71b380538ff52e106ee5cb66a0b573d9967467dfdbc11c02R187 runs a message parser for a given mime type, so if in your AsyncAPI file you have a message that has schema provided in avro, then this code runs -> https://github.com/asyncapi/parser-js/pull/214/files#diff-2f45270c7389933f71b380538ff52e106ee5cb66a0b573d9967467dfdbc11c02R187
- 1st the avro parser puts avro mime type under
x-parser-original-schema-format
- 2nd you override it with default schema format, asyncapi one, so we loose information about the original schema format
This is why instead of putting this line here, you need to have it in this parser of default asyncapi schema -> https://github.com/asyncapi/parser-js/blob/master/lib/asyncapiSchemaFormatParser.js
Add support for https://github.com/asyncapi/avro-schema-parser/blob/master/index.js#L7 too and put info about it in the readme as well please 🙏🏼
I also wonder if this knowledge about concerns to performance, and the risk of invoking validation twice is not going to be just our secret here in PR. Not sure though if there is a possible test case that could be added to check this, like check if our default parser was invoked only once? 🤔 |
…to-standalone-messages
lib/asyncapiSchemaFormatParser.js
Outdated
const payload = message.payload; | ||
if (!payload) return; | ||
|
||
// considered save here because default parser handles JSON Schema payloads | ||
message[String(xParserOriginalPayload)] = JSON.parse(JSON.stringify(payload)); |
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.
what about 👇🏼
message[String(xParserOriginalPayload)] = JSON.parse(JSON.stringify(payload)); | |
message[String(xParserOriginalPayload)] = Object.assign({}, payload); |
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.
Object.assign creates a new object but the copied properties are still shallow copies. so the payload object itself will not get a x-parser-schema-id
applied, but for instance a "name" property within the payload will get it applied.
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 are right.. 🤔
we cannot leave JSON.stringify
as it won't work with circular references in schemas
🤔
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.
Unfortunately I am not very deep into the node world (I guess you have noticed already 😄 ). So I would need to let you make the call on what to do best.
Considering that lodash.clonedeep would be available as individual dependency and looking behind the curtains on what would need to be done in an own helper function, I am not sure if manually implementing it is a good idea. On the other hand, I also cannot judge the impact of adding a new dependency to this lib.
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.
lodash is just 3.3kb gziped which is fine, I'm more concerned about performance again. We add something that is not that much needed but will add performance issues to large files again 🤔
I have doubts if this is the way to go. If we should not fall back to the initial idea about adding an additional field that we can use to check if the message was processed or not. Sorry, I just did not take into consideration this issue with copying objects
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.
no worries, got you. and yeah, since the payload is not actually transformed, the x-parser-original-payload
would always include the same structure except the added x-parser
attributes. not sure if there is any use for this except consistency with custom parsers regarding the x-parser-original-payload
being there?
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.
yeah, the use case if for those that have different formats of schemas, like avro for example, so after parsing the document they can still access the content before conversion in case they want to include it in docs or prefer to read original schema, for example in runtime validations.
so, again back to what could be the name of the extension that holds information if the message was already processed or not
😄
@c-pius I added a suggestion. Lodash is always an option but for parser let us try to keep it as slim as possible |
the hardest question of all 😄 as far as I can tell the open options are:
I am still wondering actually if we could also set the Line 182 in b32899e
If so, we would be independent from the custom parsers and wouldn't need an additional property |
@c-pius hey, sorry mate but I and others had a longer break here. 2020 was crazy busy and we needed a few days without asyncapi. Let us have a new property -> |
no worries, I also enjoyed some time off 😉 and happy new year! I reverted the |
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.
lgtm, I just made suggestions to be clear about new functionality, that it is only for messages from components.
@magicmatatjahu anything from your side? can you approve?
@derberg 8 new lines (without tests etc) with 42 comments? 😄 I'll check, give me some time to read whole thread. |
@magicmatatjahu no worries mate, I don't think you have to read it through, we had a long discussion here as we were just looking for the best possible solution on how to run operations on messages just once) in case the message is in components and also ref-ed from the channel. But we are back to the beginning I would say, just introduced a new extension |
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.
LGTM with new label :)
await customChannelsOperations(parsedJSON, asyncapiYAMLorJSON, initialFormat, options); | ||
} | ||
|
||
async function validateAndConvertMessage(msg, originalAsyncAPIDocument, fileFormat, parsedAsyncAPIDocument, pathToPayload) { | ||
//check if the message has been parsed before | ||
if (xParserMessageParsed in msg && msg[String(xParserMessageParsed)] === true) return; |
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 only a question. (xParserMessageParsed in msg) === true
will work?
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.
in general yes, if (xParserMessageParsed in msg)
would work as well as of now. the second check is to check whether the value of x-parser-message-parsed
is also set to boolean value of true. if we omit this we would check the sheer presence of the flag and skip validation. would be okay for me as well. just thought the check for a boolean true value would make it more resilient
Co-authored-by: Lukasz Gornicki <[email protected]>
Co-authored-by: Lukasz Gornicki <[email protected]>
Co-authored-by: Lukasz Gornicki <[email protected]>
Kudos, SonarCloud Quality Gate passed! 0 Bugs No Coverage information |
well, sorry 😆 just some serious thinking going on here 🤓 |
🎉 This PR is included in version 1.3.1 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Finally released. Thanks @c-pius for this PR and patience in the discussion 😄 |
awesome 🥳 thank you for guiding me and for the great work on this project in general 😄 |
* master: (24 commits) chore: Refactored code location for iterators (asyncapi#225) chore(release): 1.3.1 (asyncapi#222) fix: apply traits to standalone messages from components section (asyncapi#214) test: improve feedback loop from browser tests (asyncapi#216) ci: fix the space-issue in bump workflow (asyncapi#218) ci: update global workflows (asyncapi#217) chore(deps): bump ini from 1.3.5 to 1.3.7 (asyncapi#215) ci: rename pr testing job name and test node 14 (asyncapi#213) ci: bump workflow to start on push instead of release (asyncapi#212) chore(release): 1.3.0 (asyncapi#211) feat: add a traverse schema function (asyncapi#198) ci: add workflow that bumps parser in other asyncapi repos (asyncapi#208) ci: fix release workflow step that is responsible for handling twitter (asyncapi#209) ci: update global workflows (asyncapi#206) ci: disable any testing on draft PR (asyncapi#204) chore(release): 1.2.0 (asyncapi#202) feat: extend the components and asyncapi model with has-like functions (asyncapi#192) chore(deps-dev): bump semantic-release from 17.0.6 to 17.2.3 (asyncapi#199) chore(release): 1.1.1 (asyncapi#197) fix: channels with name '/' fail on validation (asyncapi#196) ...
Description
@derberg I tried to give it a shot but I am not really sure if the provided function is at the right place and also how the
validateAndConvertMessage
function works. I included the"x-parser-schema-id":"<anonymous-schema-1>"
properties in the output schemas as far as I understood them. Unfortunately, they are only generated for messages that are used in a channel and not the standalone messages. I assume you would know how to fix those problems?Besided,
npm run test-browser
was not working on my machine (OSX) from the beginning I cloned the repo. I am on nodev12.14.1
.Related issue(s)
Resolves #210