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

Nested routes in sysl file and code gen #75

Open
suipinglu opened this issue Apr 16, 2020 · 8 comments
Open

Nested routes in sysl file and code gen #75

suipinglu opened this issue Apr 16, 2020 · 8 comments
Labels
P1 Medium priority

Comments

@suipinglu
Copy link

suipinglu commented Apr 16, 2020

Hi everyone,

come across to a problem. we want to avoid repeating our code while implementing business logic.

what we want to describe as a sysl file:

Example "app description" [package="example"]:
    @version = "0.0.1"
    @description =:
        | This is the definition of ......

    /v1: 
        /customer/{custId<:string}/abc:
            GET:
                | No description.
                Downstream <- POST /form/{FormId}/refresh/{ContextId}  
                return ok <: returnExampleTypeA

        /customer/{custId<:string}/efg/calculate: 
            GET:
                Example <- GET /v1/customer/{custId}/abc  #REUSE THE ABOVE HTTP CALL
                Downstream <- POST /what/so/ever/abc
                return ok <: sequence of returnExampleTypeB

        /customer/{custId<:string}/xyz: 
            GET:
                Example <- GET /v1/customer/{custId}/abc #REUSE THE ABOVE HTTP CALL
                Downstream <- POST /what/so/ever/efg
                return ok <: returnExampleTypeC

The reason we want to reuse that "GET /v1/customer/{custId}/abc" is due to a large number of calls will repeat the code inside and it is not quite follow the "DRY" concept.

Cheers,
Ping

@joshcarp
Copy link
Contributor

What's the actual problem?
You don't want to repeat GET /v1/customer/{custId}/abc in the sysl?
I don't understand the sentence The reason we want to reuse that "GET /v1/customer/{custId}/abc" is due to a large number of calls will repeat the code inside and it is not quite follow the "DRY" concept.

@suipinglu
Copy link
Author

we basically need to repeat "Logic A" in Endpoint_A, Endpoint_B, Endpoint_C. They are the same code repeating for each of the above endpoints.

@andrewemeryanz
Copy link
Contributor

Sysl describes relationships between applications (or systems).

If your shared logic is internal to the application then it doesn't need to be defined in the specification, just write a method and call it in the required endpoints.

If your shared logic is on a separate application then model it as a separate application.

@springwiz
Copy link
Contributor

springwiz commented Apr 17, 2020

Just to be clear the issue here is around reusing code, and not the calls. The business flow will still make the same no of calls. Any custom code written to aggregate calls would make it convoluted in sysl file and would make diagramming impossible. I am not sure if there is a solution in Sysl and codegen at this moment.

@suipinglu
Copy link
Author

Have a discussion with @springwiz just now, i walked him through what we are facing for the moment while consuming the downstream. He is fully understand what we are facing in a code and business logic level.

@andrewemeryanz, yes, i can see your points here. We can write our http call code which will do that logic, but moving that out ends up removing the related sysl file from:

        /customer/{custId<:string}/efg/calculate: 
            GET:
                Example <- GET /v1/customer/{custId}/abc
                return ok <: sequence of returnExampleTypeB

to

        /customer/{custId<:string}/efg/calculate: 
            GET:
                return ok <: sequence of returnExampleTypeB

which mean when we generate the diagram and swagger file will not be accurate.

As @springwiz requests, this is not a simple decision that we could make to bring forward, thus looping @anzdaddy in as well.

Cheers,
Ping

@ghost
Copy link

ghost commented Apr 17, 2020

@suipinglu Sindhu asked me to comment on this issue, I completely mis-understood the initial issue at first, I didn't realise the Example <- GET /v1/customer/{custId}/abc was the line you had issues with duplicating. Please in the future be sure to make your issues more obvious (pretend you're trying to explain the issue to a 5 year old!)

Anyway, as it turns out I think my answer I was going to give would be pretty close to the solution you want.

I think you want the sysl to basically look like this:

Example "app description" [package="example"]:
    @version = "0.0.1"
    @description =:
        | This is the definition of ......

    /v1/customer/{custId<:string}/abc:
             | No description.
             Downstream <- POST /form/{FormId}/refresh/{ContextId}
             return returnExampleTypeA

        /efg/calculate: 
            GET:
                return ok <: sequence of returnExampleTypeB

        /xyz: 
            GET:
                return ok <: returnExampleTypeC

where /v1/customer/{custId<:string}/abc would handle the actual downstream and pass the returnExampleTypeA object down into the two nested endpoint handlers automatically? This is trivial in go to write up but I have no idea how complicated it would be to implement in the current sysl codegen :( (also the /abc endpoint without the METHOD name isnt legal sysl)

@ghost ghost closed this as completed Apr 17, 2020
@ghost ghost reopened this Apr 17, 2020
@suipinglu
Copy link
Author

If i have made any confusion to you guys, sorry for that. :)
If you are free, I am more than happy to spend some time with you in a call to walk you though in the code level.
Sometime, cuz here is public, not ideal to put details in.

@uynap
Copy link

uynap commented Apr 17, 2020

I think I have a resolution.
I think what you want to do is, you have an endpoint /a and you want to use the data responded by endpoint /b.

    /a
        GET:
            Fxxxxxx <- POST /whatever_api
            Fxxxxxx <- GET /whatever_api
            return ok <: RespA
    /b
        GET:
            Fxxxxxx <- POST /whatever_api
            Fxxxxxx <- GET /whatever_api
            return ok <: RespB

    !type RespA:
        Name <: string:
            @json_tag = "Name"
        RespB <: RespB:
            @json_tag = "RespB"

    !type RespB:
        Data <: string

Now, what you are going to do next is: call the handler b from the handler a.

Assuming the BFF handler struct for /a and /b are HandlerA and HandlerB. In the handler function A, you can create a HandlerB struct easily because both 2 endpoints share the same downstream APIs.

Once you have the HandlerB struct in handler A, then you can call handler b freely from handler a.

@ChloePlanet ChloePlanet added P0 Highest priority: important and urgent P1 Medium priority and removed P0 Highest priority: important and urgent labels Apr 19, 2020
ChloePlanet pushed a commit that referenced this issue Oct 9, 2020
andrewemeryanz pushed a commit that referenced this issue Jun 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P1 Medium priority
Projects
None yet
Development

No branches or pull requests

6 participants