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

Can we also generate services along with outputting types? #39

Open
niteshbalusu11 opened this issue Mar 7, 2024 · 8 comments
Open
Labels
enhancement New feature or request on hold for async this issue requires async to come back into zig

Comments

@niteshbalusu11
Copy link

Taking this proto file as an example:

https://github.com/lightningnetwork/lnd/blob/master/lnrpc/invoicesrpc/invoices.proto#L29

The rpc services functions are not getting generated. Only the types are. Is it possible to also add this?

@Arwalk
Copy link
Owner

Arwalk commented Mar 10, 2024

Hello,

I have no plan of implementing the full gRPC protocol by myself, but i guess we could generate interface structures that the user would fill with the implementations.

something naive like

// generated part
const SubscribeSingleInvoiceRequest = struct {
    // generated struct
};

const Invoice = struct {
    // generated struct
};


pub fn InvoiceServicesImplementations(comptime ServerContext: type) type {
    return struct {
        SubscribeSingleInvoiceMethod : *const fn(server: *ServerContext, request: SubscribeSingleInvoiceRequest) Invoice
    };
}

pub fn InvoicesService(comptime ServerContext: type) type {
    return struct {
        context: *ServerContext,
        implementations: InvoiceServicesImplementations(ServerContext),

        const Self = @This();

        pub fn SubscribeSingleInvoice(self: *Self, request: SubscribeSingleInvoiceRequest) Invoice {
            return self.implementations.SubscribeSingleInvoiceMethod(self.context, request);
        }
    };
}

// user defined part
const Server = struct {
    something: u32
};

fn implementation(server: *Server, _: SubscribeSingleInvoiceRequest) Invoice {
    server.something = 1;
    std.debug.print("doing stuff", .{});
    return Invoice{};
}

test "services" {
    var server = Server{
        .something = 0,
    };

    var service = InvoicesService(Server){
        .context = &server,
        .implementations = .{
            .SubscribeSingleInvoiceMethod = implementation
        }
    };

    _ = service.SubscribeSingleInvoice(SubscribeSingleInvoiceRequest{});
    try testing.expectEqual(1, server.something);
}

would probably be a good starting block, even for a future gRPC implementation.

@Arwalk
Copy link
Owner

Arwalk commented Mar 10, 2024

Actually, i thought services in proto files were meant to be only gRPC services, but no, you can define your own transport protocol according to the spec itself

So i guess we were missing this part entirely.

I'll work on it soon-ish, thanks for the heads up.

@niteshbalusu11
Copy link
Author

Thank you

@Arwalk
Copy link
Owner

Arwalk commented Mar 12, 2024

@niteshbalusu11 ongoing work in #40 , i'm going for the common interface pattern found in the standard library. services will look like this with implementations possibly like that, see test below.

This is a draft, i plan on bringing a bit more stuff around, but that's the idea.

Would that be ok?

@niteshbalusu11
Copy link
Author

with implementations possibly like that, see test below.

looks good to me!

@Arwalk
Copy link
Owner

Arwalk commented Mar 12, 2024

I realized that error handling was completely missing in what i was about to propose.

The thing is, i'm not sure how to handle it correctly. I have two ideas about it:

  • making the error type a specialization of the interface, giving full control to the end user but losing the completely generic interface. Can be seen in this example
  • Making sensible default error types, with a CustomError escape latch that implementation can use to refer to some error saved in the process. This can be seen here.

First method loses the generic interface, which i don't like.
Second method keeps the generic interface but makes it slightly harder for precise error handling for end users.

@niteshbalusu11 any opinion?

@menduz got any idea, considering you're my only reviewer around?

@niteshbalusu11
Copy link
Author

I honestly don't know. Maybe it's good to check how the other parsing libraries do it?

@Arwalk
Copy link
Owner

Arwalk commented Mar 13, 2024

I think i'll go with solution 2, i prefer to keep the generic interfaces.

@Arwalk Arwalk added enhancement New feature or request on hold for async this issue requires async to come back into zig labels Aug 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request on hold for async this issue requires async to come back into zig
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants