trafficserver icon indicating copy to clipboard operation
trafficserver copied to clipboard

[JSONRPC] - Introduce TS Plugin API - Proposal

Open brbzull0 opened this issue 3 years ago • 6 comments

JSONRPC TS API proposal

This draft is based on https://github.com/apache/trafficserver/pull/7478 which holds the JSONRPC 2.0 implementation for ATS.

Current state

Currently If a plugin wants to handle external messages they need to implement the TS_EVENT_LIFECYCLE_MSG hook. This provides a one way only message system for plugins, plugins can only receive the message but cannot respond to them directly.

Proposal

As a part of https://github.com/apache/trafficserver/issues/6633 we have introduced https://github.com/apache/trafficserver/pull/7478 (merged in 10-Dev branch) which let traffic_server to receive and respond to external messages using JSON as standard text-based format, following the JSONRPC 2.0 standard.

The goal of this proposal is to take advantage of this implementation and let plugins be able to expose JSONRPC nodes(handlers) to the exterior and also be able to respond directly to exterior clients(currently not possible).

To achieve this we are proposing to introduce a new set of API:

typedef void (*TSRPCMethodCb)(const char *id, TSYaml params);

JSONRPC callback signature for method calls.


typedef void (*TSRPCNotificationCb)(TSYaml params);

JSONRPC callback signature for notification calls


tsapi TSRPCProviderHandle TSRPCRegister(const char *provider_name, const char *yamlcpp_lib_version);

Method to perform a registration and validation when a plugin is expected to handle JSONRPC calls.

param provider_name: a string with the Plugin's description. param yamlcpp_lib_version: a string with the yamlcpp library version. A null terminated string is expected. Why do we need this? check Binary compatibility with YAMLCPP down below.

This function returns a new TSRPCProviderHandle or nullptr if the yamlcpp_lib_version was not set or the yamlcpp version does not match with the one used internally in TS. The returned TSRPCProviderHandle will be set with the passed provider's name. The caller should pass the returned TSRPCProviderHandle object to each subsequent TSRPCRegisterMethod/Notification call.


tsapi TSReturnCode TSRPCRegisterMethodHandler(const char *name, TSRPCMethodCb callback, TSRPCProviderHandle info, const TSRPCHandlerOptions *opt);

Add a new registered method handler to the JSON RPC server.

param name: Call name to be exposed by the JSONRPC server. param callback: The function to be registered. param info: TSRPCProviderHandle pointer, this will be used to provide more context information about this call. This object param opt: Pointer to TSRPCHandlerOptions object. This will be used to store specifics about a particular call, the rpc manager will use this object to perform certain actions. A copy of this object wil be stored by the rpc manager.


tsapi TSReturnCode TSRPCRegisterNotificationHandler(const char *name, TSRPCNotificationCb callback, TSRPCProviderHandle info, const TSRPCHandlerOptions *opt);

tsapi TSReturnCode TSRPCHandlerDone(TSYaml resp);

Function to notify the JSONRPC server that the current handler is done working. This function must be used only when implementing a method JSONRPC handler. Once the work is done and the response is ready to be sent back to the client, this function should be called. Is expected to set the YAML node as response. If the response is empty a success message will be added to the client's response.

This function returns TS_SUCCESS if there are no issues. TS_ERROR otherwise.


tsapi TSReturnCode TSRPCHandlerError(int code, const char *descr);

Function to notify the JSONRPC server that the current handler is done working and an error has arisen.

This should not be used if you registered your handler as a notification: TSRPCNotificationCb call.

param code: Error code. param descr: A text with a description of the error.

This function returns TS_SUCCESS if there are no issues. TS_ERROR otherwise.


Internals

This JSONRPC implementation is based on an iterative server(his own thread) which handles a single request at a time, this blocks till the response is handed back to the rpc server. For plugins this is a bit different as they need the asynchronous style to deal with some specifics tasks, plugins needs to be able to run tasks possibly on different thread and at a different time that they get called to handle the JSONRPC call, so to achieve this the JSONRPC server implements a notification mechanism(TSRPCHandlerDone, TSRPCHandlerError) which will let the JSONRPC server that the plugin handling is complete, either with an error or with a particular content. Plugins will be able to reschedule the JSONRPC handling work as they see fit. You can find examples in this PR.

To be added into apidefs.h.in

// JSONRPC 2.0 related interface.
typedef struct tsapi_rpcproviderhandle *TSRPCProviderHandle;
typedef struct tsapi_yaml *TSYaml;

Binary compatibility with YAMLCPP

Having plugins with different version of YAMLCPP could be an issue, so as with plugins, we cannot guarantee that a will be compatible across major versions, so It would be feasible to only provide binary compatibility within the lifespan of a major release, no new version of YAMLCPP should be introduced in minor versions. Eventually plugins will need to recompile/link

YAMLCPP version check

To help the plugin developers to spot issues, plugins should check-in (using TSRPCRegister) with TS before registering any handler and validate that their yamlcpp version is the same as used internally in TS. Plugins will inform which version they have and internally we will compare this against the one used in ATS (this could be an issue as we can use an external version of YAMLCPP and not the one shipped with ATS)

See examples in this Draft PR.

You can find this Docs online here and here

brbzull0 avatar Jan 25 '22 14:01 brbzull0

@jrushford is going to take a look at this

bryancall avatar Feb 01 '22 00:02 bryancall

[approve ci autest]

brbzull0 avatar Feb 01 '22 10:02 brbzull0

[approve ci autest rocky]

brbzull0 avatar Feb 28 '22 10:02 brbzull0

[approve ci autest]

brbzull0 avatar Mar 23 '22 14:03 brbzull0

This pull request has been automatically marked as stale because it has not had recent activity. Marking it stale to flag it for further consideration by the community.

github-actions[bot] avatar Jun 22 '22 02:06 github-actions[bot]

This pull request has been automatically marked as stale because it has not had recent activity. Marking it stale to flag it for further consideration by the community.

github-actions[bot] avatar Sep 21 '22 02:09 github-actions[bot]

[approve ci autest]

brbzull0 avatar Oct 04 '22 17:10 brbzull0

[approve ci autest]

brbzull0 avatar Oct 11 '22 12:10 brbzull0

[approve ci autest 3of4]

brbzull0 avatar Oct 11 '22 15:10 brbzull0

[approve ci autest]

bneradt avatar Oct 11 '22 22:10 bneradt