This commit is contained in:
2025-09-14 14:27:26 +02:00
parent 2f1d5e6173
commit d2e817c25f
10 changed files with 56 additions and 260 deletions

View File

@@ -2,21 +2,25 @@
import freeflowuniverse.herolib.hero.heromodels.rpc
println('
#to test the discover function:
echo \'\{"jsonrpc":"2.0","method":"rpc.discover","params":[],"id":1\}\' \\
| nc -U /tmp/heromodels
\'
#to test interactively:
mut http_port := 9933
nc -U /tmp/heromodels
if http_port == 0 {
println('
#to test the discover function:
echo \'\{"jsonrpc":"2.0","method":"rpc.discover","params":[],"id":1\}\' \\
| nc -U /tmp/heromodels
\'
#to test interactively:
then e.g. do
nc -U /tmp/heromodels
\{"jsonrpc":"2.0","method":"comment_set","params":{"comment":"Hello world!","parent":0,"author":42},"id":1\}
then e.g. do
needs to be on one line for openrpc to work
\{"jsonrpc":"2.0","method":"comment_set","params":{"comment":"Hello world!","parent":0,"author":42},"id":1\}
')
needs to be on one line for openrpc to work
rpc.start()!
')
}
rpc.start(http_port: http_port)!

View File

@@ -1,27 +0,0 @@
lets make an openrpc server
over unixsocker
on /tmp/heromodels
put code in lib/hero/heromodels/openrpc
do example for comment.v
make struct called RPCServer
put as methods
- comment_get(args CommentGetArgs)[]Comment! //chose the params well is @[params] struct CommentGetArgs always with id… in this case maybe author. …
- walk over the hset with data, find the one we are looking for based on the args
- comment_set(obj Comment)!
- comment_delete(id…)
- comment_list() ![]u32
- discover()!string //returns a full openrpc spec
make one .v file per type of object now comment_…
we will then do for the other objects too
also generate the openrpc spec based on the methods we have and the objects we return

View File

@@ -1,4 +0,0 @@
example
client_example
server_example
example1

View File

@@ -1,85 +0,0 @@
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
import net.unix
import json
import freeflowuniverse.herolib.ui.console
import freeflowuniverse.herolib.hero.heromodels.openrpc
fn send_request(mut conn unix.StreamConn, request openrpc.JsonRpcRequest) ! {
request_json := json.encode(request)
conn.write_string(request_json)!
}
fn read_response(mut conn unix.StreamConn) !string {
mut buffer := []u8{len: 8192}
bytes_read := conn.read(mut buffer)!
return buffer[..bytes_read].bytestr()
}
console.print_header('HeroModels OpenRPC Client Example')
// Connect to the server
mut conn := unix.connect_stream('/tmp/heromodels')!
defer {
conn.close() or {}
}
console.print_item('Connected to server')
// Test 1: Get OpenRPC specification
console.print_header('Test 1: Discover OpenRPC Specification')
discover_request := openrpc.JsonRpcRequest{
jsonrpc: '2.0'
method: 'discover'
params: 'null'
id: '1'
}
send_request(mut conn, discover_request)!
response := read_response(mut conn)!
console.print_item('OpenRPC Spec received: ${response.len} characters')
// Test 2: Create a comment
console.print_header('Test 2: Create Comment')
comment_json := '{"comment": "This is a test comment from OpenRPC client", "parent": 0, "author": 1}'
create_request := openrpc.JsonRpcRequest{
jsonrpc: '2.0'
method: 'comment_set'
params: comment_json
id: '2'
}
send_request(mut conn, create_request)!
create_response := read_response(mut conn)!
console.print_item('Comment created: ${create_response}')
// Test 3: List all comments
console.print_header('Test 3: List All Comments')
list_request := openrpc.JsonRpcRequest{
jsonrpc: '2.0'
method: 'comment_list'
params: 'null'
id: '3'
}
send_request(mut conn, list_request)!
list_response := read_response(mut conn)!
console.print_item('Comment list: ${list_response}')
// Test 4: Get comment by author
console.print_header('Test 4: Get Comments by Author')
get_args_json := '{"author": 1}'
get_request := openrpc.JsonRpcRequest{
jsonrpc: '2.0'
method: 'comment_get'
params: get_args_json
id: '4'
}
send_request(mut conn, get_request)!
get_response := read_response(mut conn)!
console.print_item('Comments by author: ${get_response}')
console.print_header('All tests completed successfully!')

View File

@@ -1,37 +0,0 @@
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
// Create a user
mut user := new_user('John Doe', 'john@example.com')
// Create a group
mut group := new_group('Development Team', 'Software development group')
group.add_member(user.id, .admin)
// Create a project
mut project := new_project('Website Redesign', 'Redesign company website', group.id)
// Create an issue
mut issue := new_project_issue('Fix login bug', project.id, user.id, .bug)
// Create a calendar
mut calendar := new_calendar('Team Calendar', group.id)
// Create an event
mut event := new_calendar_event('Sprint Planning', 1672531200, 1672534800, calendar.id,
user.id)
calendar.add_event(event.id)
// Create a filesystem
mut fs := new_fs('Team Files', group.id)
// Create a blob for file content
mut blob := new_fs_blob('Hello World!'.bytes())!
println('User ID: ${user.id}')
println('Group ID: ${group.id}')
println('Project ID: ${project.id}')
println('Issue ID: ${issue.id}')
println('Calendar ID: ${calendar.id}')
println('Event ID: ${event.id}')
println('Filesystem ID: ${fs.id}')
println('Blob ID: ${blob.id}')

View File

@@ -1,23 +0,0 @@
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
import freeflowuniverse.herolib.hero.heromodels.openrpc
import freeflowuniverse.herolib.hero.heromodels
import freeflowuniverse.herolib.ui.console
import time
import os
console.print_header('HeroModels OpenRPC Server Example')
// Create and start the server
mut server := openrpc.new_rpc_server(socket_path: '/tmp/heromodels')!
// Start server in a separate thread
spawn server.start()
console.print_item('Server started on /tmp/heromodels')
console.print_item('Press Ctrl+C to stop the server')
// Keep the main thread alive
for {
time.sleep(1 * time.second)
}

View File

@@ -1,47 +0,0 @@
module heromodels
import freeflowuniverse.herolib.schemas.openrpc
// // Re-export core methods from openrpcserver for convenience
// pub fn set[T](mut obj T) !u32 {
// return openrpcserver.set[T](mut obj)!
// }
// pub fn get[T](id u32) !T {
// return openrpcserver.get[T](id)!
// }
// pub fn exists[T](id u32) !bool {
// return openrpcserver.exists[T](id)!
// }
// pub fn delete[T](id u32) ! {
// openrpcserver.delete[T](id)!
// }
// pub fn list[T]() ![]T {
// return openrpcserver.list[T]()!
// }
// // Re-export utility functions
// pub fn tags2id(tags []string) !u32 {
// return openrpcserver.tags2id(tags)!
// }
// pub fn comment_multiset(args []CommentArg) ![]u32 {
// return openrpcserver.comment_multiset(args)!
// }
// pub fn comments2ids(args []CommentArg) ![]u32 {
// return openrpcserver.comments2ids(args)!
// }
// pub fn comment2id(comment string) !u32 {
// return openrpcserver.comment2id(comment)!
// }
// pub fn new_base(args BaseArgs) !Base {
// return openrpcserver.new_base(args)!
// }

View File

@@ -1,18 +1,32 @@
## http based RPC server
```bash
## unix socket based RPC server
curl -s http://localhost:9933/ \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "comment_set",
"params": {
"comment": "Hello world!",
"parent": 0,
"author": 42
},
"id": 1
}' | jq .
see lib/hero/heromodels/rpc/rpc_comment.v for an example of how to implement RPC methods.
```v
import freeflowuniverse.herolib.hero.heromodels.rpc
#starts the rpc server
rpc.start()!
{
"jsonrpc": "2.0",
"result": "46",
"id": 1
}
```
## unix socket based RPC server
```bash
# to test the discover function, this returns the openrpc specification:
echo '{"jsonrpc":"2.0","method":"rpc.discover","params":[],"id":1}' | nc -U /tmp/heromodels

View File

@@ -9,6 +9,7 @@ const openrpc_path = os.join_path(os.dir(@FILE), 'openrpc.json')
pub struct ServerArgs {
pub mut:
socket_path string = '/tmp/heromodels'
http_port int // if 0, no http server will be started
}
pub fn start(args ServerArgs) ! {
@@ -59,5 +60,9 @@ pub fn start(args ServerArgs) ! {
openrpc_handler.register_procedure_handle('user_delete', user_delete)
openrpc_handler.register_procedure_handle('user_list', user_list)
openrpc.start_unix_server(openrpc_handler, socket_path: args.socket_path)!
if args.http_port != 0 {
openrpc.start_http_server(openrpc_handler, port: args.http_port)!
} else {
openrpc.start_unix_server(openrpc_handler, socket_path: args.socket_path)!
}
}

View File

@@ -14,24 +14,22 @@ pub struct Context {
veb.Context
}
// Creates a new HTTPController instance
pub fn new_http_controller(c HTTPController) &HTTPController {
return &HTTPController{
...c
Handler: c.Handler
}
@[params]
pub struct HTTPServerParams {
pub mut:
port int = 9944 // Default to port 9944
}
// Parameters for running the server
@[params]
pub struct RunParams {
pub:
port int = 8080 // Default to port 8080
pub fn start_http_server(handler Handler, params HTTPServerParams) ! {
mut server := HTTPController{
Handler: handler
}
server.start(params)!
}
// Starts the server
pub fn (mut c HTTPController) run(params RunParams) {
veb.run[HTTPController, Context](mut c, 8080)
pub fn (mut c HTTPController) start(params HTTPServerParams) ! {
veb.run[HTTPController, Context](mut c, params.port)
}
// Handles POST requests at the index endpoint
@@ -43,9 +41,7 @@ pub fn (mut c HTTPController) index(mut ctx Context) veb.Result {
}
// Process the JSONRPC request with the OpenRPC handler
response := c.handle(request) or {
return ctx.server_error('Handler error: ${err.msg()}')
}
response := c.handle(request) or { return ctx.server_error('Handler error: ${err.msg()}') }
// Encode and return the handler's JSONRPC Response
return ctx.json(response)