zig-protobuf icon indicating copy to clipboard operation
zig-protobuf copied to clipboard

Can we also generate services along with outputting types?

Open niteshbalusu11 opened this issue 1 year ago • 11 comments

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?

niteshbalusu11 avatar Mar 07 '24 23:03 niteshbalusu11

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 avatar Mar 10 '24 13:03 Arwalk

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.

Arwalk avatar Mar 10 '24 14:03 Arwalk

Thank you

niteshbalusu11 avatar Mar 10 '24 14:03 niteshbalusu11

@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?

Arwalk avatar Mar 12 '24 14:03 Arwalk

with implementations possibly like that, see test below.

looks good to me!

niteshbalusu11 avatar Mar 12 '24 17:03 niteshbalusu11

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?

Arwalk avatar Mar 12 '24 23:03 Arwalk

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

niteshbalusu11 avatar Mar 13 '24 01:03 niteshbalusu11

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

Arwalk avatar Mar 13 '24 09:03 Arwalk