Skip to content

RPC

RPC (Remote Procedure Call) is a way to call PostgreSQL function through Raiden. When start Raiden's project, the PostgreSQL function will automatically imported to internal/rpc directory. Or you can also import manually by running using imports command:

sh
raiden imports

Here is an example of function on PostgreSQL:

plsql
CREATE OR REPLACE FUNCTION hello(name varchar)
RETURNS text AS $$
BEGIN
  RETURN 'Hello, ' || name || '!';
END;
$$ LANGUAGE plpgsql;

The function above will automatically generated as Go code:

go
package rpc

import (
    "github.com/sev-2/raiden"
)

type HelloParams struct {
    // Input parameters
    Name string `json:"name" column:"name:name;type:varchar"`
}

// Return type
type HelloResult string

type Hello struct {
    raiden.RpcBase
    Params   *HelloParams `json:"-"`
    Return   HelloResult `json:"-"`
}

func (r *Hello) GetName() string {
    return "hello"
}

func  (r *Hello) UseParamPrefix() bool {
    return false
}

func (r *Hello) GetReturnType() raiden.RpcReturnDataType {
    return raiden.RpcReturnDataTypeVarcharAlias
}

func (r *Hello) GetRawDefinition() string {
    return `
      BEGIN RETURN
        'Hello, ' || :name || '!';
      END;`
}

You can also define it as Go code, then publish it to PostgreSQL function by running apply command.

RPC Structure

Every RPC definition struct must embed raiden.RpcBase and declare two fields:

FieldTypeDescription
ParamsPointer to params structInput parameters for the PostgreSQL function. Use column tag to define name and type.
ReturnAny typeReturn type of the function (scalar, struct, or slice).

Required Methods

MethodDescription
GetName() stringReturns the PostgreSQL function name.
GetReturnType() raiden.RpcReturnDataTypeReturns the PostgreSQL return type constant.
GetRawDefinition() stringReturns the SQL function body. Use :paramName for parameter placeholders.

Optional Methods

MethodDefaultDescription
UseParamPrefix() booltrueWhen true, parameters are prefixed with in_ (e.g., in_name). Set to false if your SQL uses bare parameter names.
GetLanguage() string"plpgsql"The language of the PostgreSQL function.
GetSecurity() raiden.RpcSecurityTypeRpcSecurityTypeInvokerSecurity context: RpcSecurityTypeInvoker or RpcSecurityTypeDefiner.
GetBehavior() raiden.RpcBehaviorTypeRpcBehaviorVolatileFunction behavior: RpcBehaviorVolatile, RpcBehaviorStable, or RpcBehaviorImmutable.
BindModels()No-opOverride to bind model aliases used in the SQL definition.

Parameter Types

Use the column tag on param struct fields to define parameter name, type, and optional default.

go
type MyParams struct {
    UserId   int64  `json:"user_id" column:"name:user_id;type:bigint"`
    Status   string `json:"status" column:"name:status;type:varchar;default:active"`
}

Available column tag values for RPC params:

NameDescription
nameParameter name in the PostgreSQL function.
typePostgreSQL data type (see table below).
defaultDefault value. Parameters with defaults are skipped when their value is zero/nil.

Supported parameter data types:

ConstantPostgreSQL Type
integerINTEGER
bigintBIGINT
numericNUMERIC
realREAL
double precisionDOUBLE PRECISION
textTEXT
varcharCHARACTER VARYING
booleanBOOLEAN
byteaBYTEA
timestampTIMESTAMP WITHOUT TIME ZONE
timestampzTIMESTAMP WITH TIME ZONE
jsonJSON
jsonbJSONB
uuidUUID
dateDATE
pointPOINT

Array types are also supported by appending [] (e.g., uuid[], integer[], text[]).

Return Types

ConstantPostgreSQL TypeDescription
RpcReturnDataTypeTextTEXTReturns a text value.
RpcReturnDataTypeVarcharAliasVARCHARReturns a varchar value.
RpcReturnDataTypeIntegerINTEGERReturns an integer.
RpcReturnDataTypeBigIntBIGINTReturns a big integer.
RpcReturnDataTypeBooleanBOOLEANReturns a boolean.
RpcReturnDataTypeJSONJSONReturns a JSON value.
RpcReturnDataTypeJSONBJSONBReturns a JSONB value.
RpcReturnDataTypeVoidVOIDReturns nothing.
RpcReturnDataTypeSetOfSETOFReturns a set of records (use with a model struct).
RpcReturnDataTypeTableTABLEReturns a table-shaped result.
RpcReturnDataTypeRecordRECORDReturns a record (tuple).
RpcReturnDataTypeTriggerTRIGGERUsed for trigger functions.

Model Binding

For complex SQL that references table names, use BindModels() to map model structs to aliases. In the SQL definition, use :alias as a placeholder that gets replaced with the actual table name.

go
type GetUserStats struct {
    raiden.RpcBase
    Params *GetUserStatsParams `json:"-"`
    Return []GetUserStatsResult `json:"-"`
}

func (r *GetUserStats) BindModels() {
    r.BindModel(models.Users{}, "users")
    r.BindModel(models.Orders{}, "orders")
}

func (r *GetUserStats) GetRawDefinition() string {
    return `
      BEGIN
        RETURN QUERY
        SELECT u.id, u.name, count(o.id) as order_count
        FROM :users u
        JOIN :orders o ON o.user_id = u.id
        WHERE u.id = :user_id
        GROUP BY u.id, u.name;
      END;`
}

The :users and :orders placeholders will be replaced with the actual table names derived from the model struct names (converted to snake_case).

Security

TypeConstantDescription
InvokerRpcSecurityTypeInvokerFunction runs with the privileges of the calling user (default).
DefinerRpcSecurityTypeDefinerFunction runs with the privileges of the user who created it.
go
func (r *MyRpc) GetSecurity() raiden.RpcSecurityType {
    return raiden.RpcSecurityTypeDefiner
}

Behavior

TypeConstantDescription
VolatileRpcBehaviorVolatileFunction may modify data and return different results on each call (default).
StableRpcBehaviorStableFunction does not modify data and returns consistent results within a single query.
ImmutableRpcBehaviorImmutableFunction does not modify data and always returns the same result for the same arguments.
go
func (r *MyRpc) GetBehavior() raiden.RpcBehaviorType {
    return raiden.RpcBehaviorStable
}

RPC Controller

To expose an RPC function as an API endpoint, you need to create a controller. The routing for RPC controllers is convention-based, derived from the controller's folder structure.

For example, if you have an RPC function hello and you create a controller at controllers/rpc/hello/rpc.go:

go
package hello

import (
    "app/internal/rpc"
    "github.com/sev-2/raiden"
)

type RpcHelloController struct {
    raiden.ControllerBase
    Payload *rpc.HelloParams
    Result  rpc.HelloResult
}

func (c *RpcHelloController) Post(ctx raiden.Context) error {
    rpcFunc := rpc.Hello{Params: c.Payload, Return: c.Result}
    return ctx.SendRpc(&rpcFunc)
}

This controller would automatically be accessible at the /rest/v1/rpc/hello endpoint. The Post method is typically used for RPC calls.

For multi-word RPC names, use kebab-case for the folder name:

go
package get_user_stats

import (
    "app/internal/rpc"
    "github.com/sev-2/raiden"
)

type GetUserStatsController struct {
    raiden.ControllerBase
    Payload *rpc.GetUserStatsParams
    Result  []rpc.GetUserStatsResult
}

func (c *GetUserStatsController) Post(ctx raiden.Context) error {
    rpcFunc := rpc.GetUserStats{Params: c.Payload}
    return ctx.SendRpc(&rpcFunc)
}

This registers the endpoint at /rest/v1/rpc/get-user-stats.

For a detailed explanation of Raiden's convention-based routing, including dynamic routes and folder naming conventions, please refer to the Controller documentation and Project Structure.

Released under the MIT License.