asyncapi / spec

The AsyncAPI specification allows you to create machine-readable definitions of your asynchronous APIs.
https://www.asyncapi.com
Apache License 2.0
4.12k stars 262 forks source link

Add a View property to the info section to change the perspective of subscribe and publish operations. #390

Closed damaru-inc closed 9 months ago

damaru-inc commented 4 years ago

The specification regards publishing and subscribing from the point of view of what a client is allowed to do. For example, if the spec has a publish operation, then applications will actually be subscribing. This is consistent with OpenAPI server side code, where if one sees a GET, it is not the server that does the GET but rather other applications.

However some users of AsyncAPI find it more intuitive to consider things from the opposite perspective. If they have a document with a publish operation and want to generate code, they expect that the code will publish, not subscribe.

I propose adding a parameter called 'view' that can have two values:

'client' - this is consistent with the current specification. It means that the document says what a client of the application can do. 'provider' - this means that the document describes what the provider of the service is doing, i.e. a subscribe operation means that the application is subscribing.

Can't it be tackled using specification extensions? It can be done using specification extensions, but so far there are three generator templates using their own extensions and terminology - it would be nice to make this consistent.

Describe the solution you'd like I would like to see an addition to the info section that supports this parameter, e.g.

info:
   view: provider

Describe alternatives you've considered The java-spring-cloud-stream and paho-python templates currently support this through the use of specification extentions and parameters. The java-template also has this feature but uses different terminology.

jessemenning commented 3 years ago

the "verb confusion" would remain, true: it can only be resolved by a backwards-incompatible renaming: trivial to do and trivial to automate "upgrade" tooling for AsyncAPI docs.

but it seems that all other restrictions of the v2 spec can be resolved by introducing fully backwards-compatible relaxations of what's required (say, channel) and what can be referenced via an $ref rather than having to be specified there-and-then by containment (similar to how #531 relaxes the association between channels and servers in a backwards-compatible way).

@GeraldLoeffler, thanks, I think I understand what you're getting at. It seems very similar to @jhigginbotham suggestion as well. Let me spend some time today working through the implications and writing up some examples to solidify things a bit more in my mind.

It's helpful to understand what's "easy" and "hard" in terms of breaking changes. @nictownsend and @dalelane , how much would changing publish to sends (or something similar) and subscribe to receives (or something similar) affect your product?

nictownsend commented 3 years ago

how much would changing publish to sends (or something similar) and subscribe to receives (or something similar) affect your product?

Breaking changes in the spec can definitely be accounted for

jessemenning commented 3 years ago

It may not be your intent, but note that a channel is not necessarily constrained to a particular message schema. Yes, the DataType Channel pattern would constrain a channel to a single message type, but I don't think that AsyncAPI should constrain to just one type.

I agree with @iancooper that we shouldn't constrain a channel to one data type. This is particularly important with Avro over Kafka, where LightMeasured v1 schema and LightMeasured v2 schema might both be presented on the same topic.

However, I do think for decoupling purposes, data types should be properties of the channel, not the endpoint. If the purpose of a channel is to eliminate dependencies between information providers and information consumers, forcing consumers to determine what datatypes each provider sends would undermine that.

jhigginbotham commented 3 years ago

This is particularly important with Avro over Kafka, where LightMeasured v1 schema and LightMeasured v2 schema might both be presented on the same topic.

Interesting point, as that brings up the definition of a channel and message type, including their relationship cardinality.

Clarifying these definitions and providing copious examples will likely clarify intent across this discussion, avoid confusion in the future, and lay the groundwork for future spec documentation + examples. It sounds like a few people are doing that now, so as part of the work, I'd recommend defining what you mean with each term introduced to ensure alignment as part of the write-ups and examples being produced. In some cases, we may end up talking about the same thing, but in other cases we may be using the words in different contexts.

jessemenning commented 3 years ago

@GeraldLoeffler So, I've been trying to piece together an example. I think there is general agreement that publish and subscribe are not generic enough for all async use cases. You suggested replace subscribe with applicationSent replace publish with applicationReceived. Based on @iancooper 's [helpful suggestion] (https://github.com/asyncapi/spec/issues/390#issuecomment-884269174) , I've taken the liberty of changing them to endpointSends and endpointReceives

The as-is API representation of the Streetlights Control Hub then becomes:

channels:
    light/measured:
        endpointSends:  #breaking change
            summary: Inform about environmental lighting conditions for a particular streetlight.
            operationId: onLightMeasured
            message:
                name: LightMeasured

    control/lightOn:
        endpointReceives:  #breaking change
            summary: Commands lights on
            operationId: lightOn
            message:
                name: LightControl

In this use, it is assumed the API describes:

In other words, the endpoint may choose tosend onLightMeasured events, and may choose to receive controlLightOn commands. (I find this still to be a bit of mental gymnastics, but maybe that's just me.) It sounds like for your use case, those are appropriate assumptions.

For those with different assumptions, requirements, use cases and/or perspectives, in proposed v3 it becomes possible--though not mandatory--to explicitly create endpoints and/or classes of endpoints.

endpoint:
    StreetLight:
        endpointSends:  
                        light/measured
                                $ref: /uri/channels/light/measured
        endpointReceives:  
            control/lightOn
                               $ref: /uri/channels/control/lightOn
channels:
    light/measured:
               message:
               name: LightMeasured  
    control/lightOn:
            message:
                name: LightControl

In the optional v3 usage the API describes how either

To accomplish this--and this basically just restating @GeraldLoeffler--:

As @iancooper stated, the devil is in the details, but this seems like a way to make the spec evolve towards more enterprise functionality, while (mostly) maintaining backwards compatibility through reasonable assumptions. However, I'd be interested in the opinions of those making tooling. Does having this flexibility make it harder/impossible to generate code, for instance?

jessemenning commented 3 years ago

To make the issue title better reflective of the primary topic of conversation, I have opened a new issue centered on the endpoint proposal

599

fmvilas commented 3 years ago

Leaving here the discussion @dalelane and I had during the last ThinkingOutLoud episode: https://youtu.be/Qsu_yC-5YYM?t=64. I hope it serves as a basement for those who are still reluctant to get involved in the discussion.

Key takeaways

fmvilas commented 3 years ago

Also, please if you think your proposal is very different from this one submit a new one separately as @jmenning-solace did with #599 🙏 Just so the discussion is easier to follow. I'm tracking all of them on #520.

fmvilas commented 3 years ago

Yo folks. As a result of the Thinking Out Loud episodes, I've come up with a proposal of how to solve this problem. Hope it makes sense and captures the feedback and ideas that y'all gave me: https://github.com/asyncapi/spec/issues/618.