implement openrpc and http interface generation for actor

This commit is contained in:
timurgordon
2025-01-03 01:48:04 -05:00
parent 6ba89a8b9c
commit 357000ef13
7 changed files with 198 additions and 59 deletions

View File

@@ -0,0 +1,22 @@
module generator
import freeflowuniverse.herolib.core.code { Folder, IFile, VFile, CodeItem, File, Function, Import, Module, Struct, CustomCode }
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.schemas.openrpc
import freeflowuniverse.herolib.baobab.specification {ActorMethod, ActorSpecification}
import os
import json
fn generate_openrpc_interface_file() !VFile {
return VFile {
name: 'interface_openrpc'
items: [CustomCode{$tmpl('./templates/interface_openrpc.v.template')}]
}
}
fn generate_http_interface_file() !VFile {
return VFile {
name: 'interface_http'
items: [CustomCode{$tmpl('./templates/interface_http.v.template')}]
}
}

View File

@@ -0,0 +1,33 @@
import os
import freeflowuniverse.herolib.baobab.actor {IActor, RunParams}
import freeflowuniverse.herolib.schemas.openapi
const openapi_spec_path = '@{dollar}{os.dir(@@FILE)}/specs/openapi.json'
const openapi_spec_json = os.read_file(openapi_spec_path) or { panic(err) }
const openapi_specification = openapi.json_decode(openapi_spec_json)!
struct @{actor_name_pascal}Actor {
actor.Actor
}
fn new() !@{actor_name_pascal}Actor {
return @{actor_name_pascal}Actor {
actor.new('@{actor_name_snake}')
}
}
pub fn run() ! {
mut a_ := new()!
mut a := IActor(a_)
a.run()!
}
pub fn run_server(params RunParams) ! {
mut a := new()!
mut server := actor.new_server(
redis_url: 'localhost:6379'
redis_queue: a.name
openapi_spec: openapi_specification
)!
server.run(params)
}

View File

@@ -0,0 +1,17 @@
import freeflowuniverse.herolib.schemas.openapi { OpenAPI }
import freeflowuniverse.herolib.baobab.actor {Client, ClientConfig}
import freeflowuniverse.herolib.schemas.openrpc { OpenRPC }
import freeflowuniverse.herolib.baobab.interfaces { HTTPServer, Context }
import veb
pub fn new_http_server() !&HTTPServer {
mut s := interfaces.new_http_server()!
mut openrpc_controller := new_openrpc_http_controller()!
s.register_controller[openrpc.HTTPController, Context]('/openrpc', mut openrpc_controller)!
return s
}
pub fn run_http_server() ! {
mut server := new_http_server()!
veb.run[HTTPServer, Context](mut server, 8082)
}

View File

@@ -0,0 +1,20 @@
import freeflowuniverse.herolib.baobab.interfaces
import freeflowuniverse.herolib.schemas.openrpc
const specification_path = os.join_path(os.dir(@@FILE), '/testdata/openrpc.json')
const specification = openrpc.new(path: specification_path)!
pub fn new_openrpc_interface() !&interfaces.OpenRPCInterface {
// create OpenRPC Handler with actor's client
client := new_client()!
return interfaces.new_openrpc_interface(client.Client)
}
// creates HTTP controller with the actor's OpenRPC Handler
// and OpenRPC Specification
pub fn new_openrpc_http_controller() !&openrpc.HTTPController {
return openrpc.new_http_controller(
specification: specification
handler: new_openrpc_interface()!
)
}

View File

@@ -1,77 +1,77 @@
module actor
module interfaces
import veb
import freeflowuniverse.herolib.schemas.openapi { Context, Controller, OpenAPI, Request, Response }
import freeflowuniverse.herolib.baobab.action { ProcedureError }
import os
import time
import json
import x.json2
import net.http
import freeflowuniverse.herolib.schemas.jsonschema
import freeflowuniverse.herolib.clients.redisclient
import freeflowuniverse.herolib.core.redisclient
pub struct OpenAPIProxy {
client Client
specification OpenAPI
}
// pub struct OpenAPIProxy {
// pub:
// client Client
// specification OpenAPI
// }
// creates and OpenAPI Proxy Controller
pub fn new_openapi_proxy(proxy OpenAPIProxy) OpenAPIProxy {
return proxy
}
// // creates and OpenAPI Proxy Controller
// pub fn new_openapi_proxy(proxy OpenAPIProxy) OpenAPIProxy {
// return proxy
// }
// creates and OpenAPI Proxy Controller
pub fn (proxy OpenAPIProxy) controller() &Controller {
// Initialize the server
mut controller := &Controller{
specification: proxy.specification
handler: Handler{
client: proxy.client
}
}
return controller
}
// // creates and OpenAPI Proxy Controller
// pub fn (proxy OpenAPIProxy) controller() &Controller {
// // Initialize the server
// mut controller := &Controller{
// specification: proxy.specification
// handler: Handler{
// client: proxy.client
// }
// }
// return controller
// }
@[params]
pub struct RunParams {
pub:
port int = 8080
}
// @[params]
// pub struct RunParams {
// pub:
// port int = 8080
// }
fn (proxy OpenAPIProxy) run(params RunParams) {
mut controller := proxy.controller()
veb.run[Controller, Context](mut controller, params.port)
}
// fn (proxy OpenAPIProxy) run(params RunParams) {
// mut controller := proxy.controller()
// veb.run[Controller, Context](mut controller, params.port)
// }
pub struct Handler {
pub mut:
client Client
}
// pub struct Handler {
// pub mut:
// client Client
// }
fn (mut handler Handler) handle(request Request) !Response {
// Convert incoming OpenAPI request to a procedure call
call := rpc.openapi_request_to_procedure_call(request)
// fn (mut handler Handler) handle(request Request) !Response {
// // Convert incoming OpenAPI request to a procedure call
// call := rpc.openapi_request_to_procedure_call(request)
// Process the procedure call
procedure_response := handler.client.dialogue(call, Params{
timeout: 30 // Set timeout in seconds
}) or {
// Handle ProcedureError
if err is ProcedureError {
return Response{
status: http.status_from_int(err.code()) // Map ProcedureError reason to HTTP status code
body: json.encode({
'error': err.msg()
})
}
}
return error('Unexpected error: ${err}')
}
// // Process the procedure call
// procedure_response := handler.client.dialogue(call, Params{
// timeout: 30 // Set timeout in seconds
// }) or {
// // Handle ProcedureError
// if err is ProcedureError {
// return Response{
// status: http.status_from_int(err.code()) // Map ProcedureError reason to HTTP status code
// body: json.encode({
// 'error': err.msg()
// })
// }
// }
// return error('Unexpected error: ${err}')
// }
// Convert returned procedure response to OpenAPI response
return Response{
status: http.Status.ok // Assuming success if no error
body: procedure_response.result
}
}
// // Convert returned procedure response to OpenAPI response
// return Response{
// status: http.Status.ok // Assuming success if no error
// body: procedure_response.result
// }
// }

View File

@@ -1,5 +1,9 @@
module interfaces
import freeflowuniverse.herolib.baobab.actor {Client}
import freeflowuniverse.herolib.schemas.jsonrpc
import freeflowuniverse.herolib.baobab.actions
// handler for test echoes JSONRPC Request as JSONRPC Response
fn handler(request jsonrpc.Request) !jsonrpc.Response {
return jsonrpc.Response {

View File

@@ -0,0 +1,43 @@
module interfaces
import freeflowuniverse.herolib.schemas.openapi { OpenAPI }
import freeflowuniverse.herolib.baobab.actor {Client, ClientConfig}
import freeflowuniverse.herolib.schemas.openrpc { OpenRPC }
import veb
pub struct HTTPServer {
veb.Controller
}
pub struct Context {
veb.Context
}
pub struct HTTPServerConfig {
ClientConfig
pub:
openapi_specification OpenAPI
openrpc_specification OpenRPC
}
pub fn new_http_server() !&HTTPServer {
mut s := &HTTPServer{}
// client := actor.new_client(cfg.ClientConfig)!
// openapi_proxy := new_openapi_proxy(
// client: new_client(cfg.ClientConfig)!
// specification: cfg.openapi_spec
// )
// mut openrpc_controller := openrpc.new_http_controller(
// specification: cfg.openrpc_specification
// handler: new_openrpc_interface(client)
// )
// s.register_controller[openrpc.HTTPController, Context]('/openrpc', mut openrpc_controller)!
return s
}
pub fn (mut server HTTPServer) run() {
veb.run[HTTPServer, Context](mut server, 8082)
}