Skip to main content

RPC Microservices

Nidus enables native socket-based RPC communication between services. A server publishes named handlers; clients invoke them by name over TCP.

Server side

1. Choose a provider

Two transport providers are included:

ProviderUnitNotes
IndyNidus.Server.IndyTRPCServerIndy
SynapseNidus.Server.SynapseTRPCServerSynapse

Both inherit from TRPCProviderServer (Nidus.RPC.Server).

2. Register and publish

uses
Nidus,
Nidus.RPC.Server,
Nidus.Server.Indy; // or Nidus.Server.Synapse

var LServer: TRPCServerIndy;
begin
LServer := TRPCServerIndy.Create('0.0.0.0', 9900);

GetNidus
.UseRPC(LServer)
.PublishRPC('GetUser', TGetUserRPCResource)
.PublishRPC('CreateOrder', TCreateOrderRPCResource)
.Start(TAppModule.Create);
end;

UseRPC calls IRPCProviderServer.Start to begin listening. PublishRPC registers a name → TRPCResourceClass mapping in the TRPCRouteHandle registry.

3. Implement an RPC resource

uses
Nidus.RPC.Resource;

type
TGetUserRPCResource = class(TRPCResource)
public
function Execute(const ARequest: string): string; override;
end;

function TGetUserRPCResource.Execute(const ARequest: string): string;
begin
// ARequest is the raw JSON payload sent by the client
Result := '{"id":1,"name":"Isaque"}';
end;

TRPCResourceClass = class of TRPCResource — defined in Nidus.RPC.Resource.

4. Dispatch (internal)

TRPCRouteHandle.ExecuteRPC(ARequest) parses the request (via TRPCParse), looks up the registered class by name, instantiates it, calls Execute, and returns the result string.

Client side

uses
Nidus.RPC.Client,
Nidus.Client.Indy; // or Nidus.Client.Synapse

var LClient: TRPCClientIndy;
begin
LClient := TRPCClientIndy.Create('127.0.0.1', 9900);
try
var LResponse := LClient.ExecuteRPC('{"rpc":"GetUser","payload":{"id":1}}');
// process LResponse
finally
LClient.Free;
end;
end;

TRPCProviderClient.ExecuteRPC is the abstract base; TRPCClientIndy / TRPCClientSynapse provide the actual TCP transport.

JSON envelope (confirmed from Nidus.RPC.Parse and Nidus.RPC.RouteHandle):

Request sent to the server:

{ "id": "1", "method": "MethodName", "params": ["arg1", "arg2"] }

Success response:

{ "jsonrpc": "2.0", "result": <return_value>, "id": "1" }

Error response (method not found):

{ "jsonrpc": "2.0", "error": { "code": -32601, "message": "Method MethodName not found" }, "id": "1" }

Unpublishing

// via TRPCPublish directly (if you hold a reference)
LPublish.UnPublishRPC('GetUser');

Source: Nidus.RPC.PublishTRPCPublish.UnPublishRPC.

Architecture

TNidus.UseRPC(IRPCProviderServer)
└── IRPCProviderServer.Start (Indy / Synapse TCP listener)

TNidus.PublishRPC(name, class)
└── IRPCProviderServer.PublishRPC
└── TRPCRouteHandle.PublishRPC
└── TRPCPublish registry (name → TRPCResourceClass)

Incoming TCP request
└── TRPCProviderServer.ExecuteRPC(raw)
└── TRPCRouteHandle.ExecuteRPC
└── TRPCParse → name lookup → TRPCResource.Execute