VKCOM / kphp

KPHP — a PHP compiler
https://vkcom.github.io/kphp/
GNU General Public License v3.0
1.36k stars 94 forks source link

How to respond to *untyped* RPC ? #1085

Open henrywood opened 3 months ago

henrywood commented 3 months ago

Could someone please provide an ultra-short example of how to respond to an UNTYPED RPC request ?

The documentation only appears to show how to do TYPED RPC ?

Let's say I have a service that takes in a string in 'fullname' member (of the associative array) and I want the service to respond with an int (the age), exactly how would the index.php look ?

This is my user.tl

---types---
messages.ageResult age:int user_id:int fullname:string = messages.AgeResult;

---functions---
messages.getAge user_id:long nameparts:%(Vector string) fullname:string silent:bool = Vector %messages.AgeResult;

This is my client.php

<?php
$host = 'localhost';
$port = 9300;

// this will be mixed[]
$query = [
        '_'        => 'messages.getAge',  // function name
        'user_id'  => 123456,                        // long in TL  => int in PHP
        'nameparts' => ['Henrik', 'Skov'],              // Vector int in TL => int[] in PHP
        'fullname' => 'Henrik Skov',
        'silent'   => false,                         // bool in TL  => bool in PHP
];

$connection = new_rpc_connection($host, $port);
$query_id = rpc_tl_query_one($connection, $query);  // in

// Parse response
$response = rpc_tl_query_result_one($query_id);     // mixed[]
// check for errors
if (isset($response['__error'])) {
        // __error, __error_code
        var_dump($response);
}

// ['result'] is valid unless error
$result = $response['result'];   // mixed

var_dump($result);

Compiling with:

 kphp client.php -M cli -o ./client

Compiles OK.

server.php

 <?php

if ($_SERVER['RPC_REQUEST_ID']) {
        // then it is a query for RPC server
        $request = rpc_server_fetch_request();

        var_dump($request);
        $func = $request->getTLFunctionName();
        var_dump($func);

        //$response = new \tl\RpcFunctionReturnResult();

        //rpc_server_store_response($response);

        // How do I make a response here ???

        exit;

} else {
        die('Unsupported query');
}

Compiling with:

kphp server.php -o ./server.php

DOES NOT compile ?

The error is:

Starting php to cpp transpiling...

Starting make...
objs cnt = 11
objs cnt = 11
Compiling stage started...
  0% [total jobs 12] [left jobs 12] [running jobs 0] [waiting jobs 4]
  8% [total jobs 12] [left jobs 11] [running jobs 7] [waiting jobs 4]
 16% [total jobs 12] [left jobs 10] [running jobs 6] [waiting jobs 4]
 25% [total jobs 12] [left jobs 9] [running jobs 5] [waiting jobs 3]
 33% [total jobs 12] [left jobs 8] [running jobs 5] [waiting jobs 3]
 41% [total jobs 12] [left jobs 7] [running jobs 4] [waiting jobs 2]
 50% [total jobs 12] [left jobs 6] [running jobs 4] [waiting jobs 1]
 58% [total jobs 12] [left jobs 5] [running jobs 4] [waiting jobs 1]
 66% [total jobs 12] [left jobs 4] [running jobs 3] [waiting jobs 1]
 75% [total jobs 12] [left jobs 3] [running jobs 2] [waiting jobs 1]
 83% [total jobs 12] [left jobs 2] [running jobs 1] [waiting jobs 1]
 91% [total jobs 12] [left jobs 1] [running jobs 0] [waiting jobs 0]
100% [total jobs 12] [left jobs 0] [running jobs 0] [waiting jobs 0]
Linking stage started...
/usr/bin/ld: /tmp/rpc/kphp_out/objs/o_82_8e806fd35b58aa13.o: in function `f$src_servere847339ec08c5d9()':
/tmp/rpc/kphp_out/kphp/o_82/src_servere847339ec08c5d9.cpp:18: undefined reference to `f$rpc_server_fetch_request()'
collect2: error: ld returned 1 exit status
pid [1346129] failed or terminated : return code 1
Failed [g++  -o /tmp/rpc/kphp_out/server -Wl,--whole-archive -Wl,--start-group /tmp/rpc/kphp_out/objs/_shape_keys.o /tmp/rpc/kphp_out/objs/globals_allocate.o /tmp/rpc/kphp_out/objs/globals_reset.o /tmp/rpc/kphp_out/objs/init_php_scripts.o /tmp/rpc/kphp_out/objs/_tagger.o /tmp/rpc/kphp_out/objs/main.o /tmp/rpc/kphp_out/objs/const_vars_init.o /tmp/rpc/kphp_out/objs/o_57_5497b566a8c8cf7f.o /tmp/rpc/kphp_out/objs/o_82_8e806fd35b58aa13.o /tmp/rpc/kphp_out/objs/o_const_init_d6cabf9fd688fd59.o /tmp/rpc/kphp_out/objs/o_globals_reset_a8c033df2aa83637.o /usr/share/vkontakte/kphp_source/objs/libkphp-full-runtime.a  -Wl,--end-group -Wl,--no-whole-archive -L/usr/share/vkontakte/kphp_source//objs/flex -ggdb -fno-lto -no-pie /opt/curl7600/lib/libcurl.a -L /usr/local/lib -L /usr/local/lib -l:libpcre.a -l:libre2.a -l:libyaml-cpp.a -l:libh3.a -l:libz.a -l:libzstd.a -l:libnghttp2.a -l:libkphp-timelib.a -l:libssl.a -l:libcrypto.a -l:libnuma.a -l:libvk-flex-data.a -lpthread -lm -ldl -lmysqlclient -lpq -lrt -rdynamic]
Make failed. Waiting for 0 children

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Compilation error at stage: Make, gen by make.cpp:571
  unknown file:0

Linking stage failure

Compilation terminated due to errors

Line 18 is this line:

$request = rpc_server_fetch_request();

Compiling the user.tl file with

sudo tl-compiler -v -e /var/www/vkontakte/data/www/vkontakte.com/tl/scheme.tlo /usr/share/vkontakte/examples/tl-files/common.tl /usr/share/vkontakte/examples/tl-files/tl.tl /usr/share/vkontakte/examples/tl-files/user.tl

gives this error:

Parse ok
No one read/write attribute found for messages.getAge
Fail

Running:

henrik@HSLAPTOP-ASUS:/tmp/rpc$ ./server --rpc-port 9300
[1360370][2024-08-30 15:31:14.781930 limits.cpp  124] failed to set rlimit for core dump size.

Running the client:

henrik@HSLAPTOP-ASUS:/tmp/rpc$ ./client
[1360388][2024-08-30 15:31:20.319415 limits.cpp  124] failed to set rlimit for core dump size.
[1725024680] [1360388] Warning: Storing error:
Function "messages.getAge" not found in tl-scheme
In _unknown_ serializing TL object
------- Stack Backtrace -------
(0) ./client : php_warning(char const*, ...)+0xa4 [0x666884]
(1) ./client : CurrentTlQuery::raise_storing_error(char const*, ...)+0x159 [0x6aa009]
(2) ./client : store_function(mixed const&)+0x32a [0x683d4a]
(3) ./client : rpc_tl_query_impl(class_instance<C$RpcConnection> const&, mixed const&, double, std::tuple<long>&, bool, bool, bool, unsigned long&, bool)+0x87 [0x686fe7]
(4) ./client : f$rpc_tl_query_one(class_instance<C$RpcConnection> const&, mixed const&, double)+0x34 [0x687244]
(5) ./client : f$src_client4f417b90a5796c06()+0x1ca [0x52190a]
(6) ./client : f$src_client4f417b90a5796c06$run()+0xd [0x52159d]
(7) ./client : PhpScript::run()+0xef [0x71e9cf]
(8) /lib/x86_64-linux-gnu/libc.so.6 : +0x5a130 [0x7f6323e60130]
-------------------------------

array(2) {
  ["__error"]=>
  string(14) "Wrong query_id"
  ["__error_code"]=>
  int(-1003)
}
NULL

What am I doing wrong ???

Where exactly should the schema.tlo file be placed ? On the server and/or the client ? And how do I specify the path to it ???

Please help !

DrDet commented 2 months ago

To be able to use RPC from your kphp scripts, you need to pass .tlo scheme to compiler via -T path/to/scheme.tlo. Otherwise, compiler can't generate serialization logic by according to TL scheme and hence you can't communicate via RPC. You can read about other compiler options in our documentation.

To compile .tl scheme to .tlo you need to provide at least one annotaion for each TL function. There's a special annotaion @kphp for TL functions which will be served by kphp RPC server (exactly what you need). Check out examples here https://github.com/VKCOM/kphp/blob/ee1122d36187f97018337792d037ccc48fb6051e/common/tl-files/common.tl#L117

So, you should do the following:

  1. Add @kphp annotation to your TL function.
  2. Compile TL scheme to scheme.tlo
  3. Recompile client and server with -T scheme.tlo

Also, I'd suggest to visit our chat in Telegram. There you probably get much faster answer