Replies: 2 comments 1 reply
-
|
@jasonmreding - Not sure if you get notified on new discussion threads, but since we had chatted about some of this in previous PRs wanted to ping you. No urgency, just wanted to make sure you knew this was here. |
Beta Was this translation helpful? Give feedback.
0 replies
-
|
Thanks for bringing this up. One thought I have is how two services, sharing the same message would be handled? Would we duplicate the messages into each class(services)? |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment

Uh oh!
There was an error while loading. Please reload this page.
-
I am starting this discussion thread to brainstorm ideas that I’d like to see implemented for a grpc-labview v2.0. I feel like this incorporates many of the suggestions that are in the open issues list, but starting a thread here to try to tie everything together. Comments and discussion are welcome.
These ideas are focused on the gRPC server; I'll create a separate thread for gRPC clients.
Goals
My main goals:
Implementation
To achieve this, I propose that each service is comprised of two classes: a service class and an implementation class.

The service class is generated by the LV gRPC generation tool and inherits from ServiceBase.lvclass (as it does now). The intent is that no user code is present in this service class. Complete re-generation of this class should have no effect on an application.

The implementation class contains all user code and allows for further customization of the server if desired. The LV generation tool would only create stubs for each RPC method. If these stubs are already existing, the generation tool would not replace the method.
To achieve this, each lvlib generated by the LV generation tool would contain a single service only. If multiple services are passed into the generation tool, the tool should create multiple lvlibs/lvclasses. As a result, there is no code inside the lvlib that is not inside a class. All service messages, typedefs, descriptors, etc are now members of the service class.
Service Class
In the generated service class, both

Start Sync.viandStart Async.viwould be populated with calls to implementation methods by the generation tool. (Again, the intent is that the user performs no modification on the generated service class after generation)Implementation Class
The generation tool would create stub methods for each RPC method. This stub would contain a

Get … Request.viand aSet … Response.vimethod to help speed up development. These methods are still used (as opposed to just passing request/response values via the connector pane) to allow for streaming RPC methods, where multiple calls to the Get/Set methods are used.The other intent of the implementation class is the ability to override
Start Sync.viand/orStart Async.vito create a custom service implementation. For example, if one wanted to just have a single VI handle all RPC methods, this can be done by overridingStart Sync.viand creating a new event structure. Of course, the generation tool would not update the customStart Sync.viif/when new methods are added in the future. The intent is that creating these custom implementations would be an edge case and that the standard implementation methods would be used the majority of the time.Another advantage of the implementation class would be if one wanted to purposely “leak” the user event to register directly into their application (and not use any event registration in

Start Sync.vi/Start Async.vi), this could be implemented in the implementation class. My intent would be thatRead Server RPC Methods.viwould move to protected scope, but theServer Internal Message UE.ctltypedef remains in public scope. This way, one has to purposely create a method in the implementation class to “leak” the user events but this can be easily done. Since the typedef from the server class is used, if the typedef is updated for additional RPC methods in the future, this would be automatically propagated through to the custom method.gRPC Server
All control of the gRPC services would be encapsulated into the server methods.

Services would be registered to the gRPC server using a
Register gRPC Services.viserver method. This VI would call the registration methods of those service classes (as was done previously separately).Running the services would be done by the server in the
Run Server.vimethod. This method would asynchronously call theStart.vimethod of all registered services and wait until all services are complete. ExecutingStart Sync.viorStart Async.viis decided by the definedService Modelproperty. If in the future, more models are defined in the base grpc-labview deployment, more selections can be added (For example, I could see eventually adding a truly async/callback-style implementation in the generated code)In addition, this allows for potentially multiple different service implementations, which are chosen at runtime, which can be used with a single service lvclass code as the implementation class is the registered with the server.
Generation Tool
The generation tool should ensure that no user code is deleted during creation of a service.
For a new user creating a gRPC server, I feel like the new implementation class methods are much easier to understand and develop than knowing which event structures need to be modified.
Beta Was this translation helpful? Give feedback.
All reactions