fix actor generation and tests
This commit is contained in:
@@ -1,34 +0,0 @@
|
||||
module actor
|
||||
|
||||
import freeflowuniverse.herolib.schemas.openapi { OpenAPI }
|
||||
import veb
|
||||
|
||||
pub struct Server {
|
||||
veb.Controller
|
||||
}
|
||||
|
||||
pub struct Context {
|
||||
veb.Context
|
||||
}
|
||||
|
||||
pub struct ServerConfig {
|
||||
ClientConfig
|
||||
pub:
|
||||
openapi_spec OpenAPI
|
||||
}
|
||||
|
||||
pub fn new_server(cfg ServerConfig) !&Server {
|
||||
mut s := &Server{}
|
||||
|
||||
openapi_proxy := new_openapi_proxy(
|
||||
client: new_client(cfg.ClientConfig)!
|
||||
specification: cfg.openapi_spec
|
||||
)
|
||||
|
||||
s.register_controller[openapi.Controller, Context]('/openapi', mut openapi_proxy.controller())!
|
||||
return s
|
||||
}
|
||||
|
||||
pub fn (mut server Server) run(params RunParams) {
|
||||
veb.run[Server, Context](mut server, params.port)
|
||||
}
|
||||
@@ -23,6 +23,7 @@ pub fn generate_actor_module(spec ActorSpecification, params Params) !Module {
|
||||
generate_handle_file(spec)!,
|
||||
generate_methods_file(spec)!
|
||||
generate_client_file(spec)!
|
||||
generate_model_file(spec)!
|
||||
]
|
||||
|
||||
mut docs_files := []IFile{}
|
||||
@@ -35,8 +36,10 @@ pub fn generate_actor_module(spec ActorSpecification, params Params) !Module {
|
||||
openrpc_spec := spec.to_openrpc()
|
||||
|
||||
// generate openrpc code files
|
||||
files << generate_openrpc_client_file(openrpc_spec)!
|
||||
files << generate_openrpc_client_test_file(openrpc_spec)!
|
||||
// files << generate_openrpc_client_file(openrpc_spec)!
|
||||
// files << generate_openrpc_client_test_file(openrpc_spec)!
|
||||
files << generate_http_interface_file()!
|
||||
files << generate_openrpc_interface_file()!
|
||||
|
||||
// add openrpc.json to docs
|
||||
docs_files << generate_openrpc_file(openrpc_spec)!
|
||||
|
||||
@@ -3,133 +3,240 @@ module generator
|
||||
import freeflowuniverse.herolib.core.code
|
||||
import freeflowuniverse.herolib.baobab.specification
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import freeflowuniverse.herolib.schemas.openrpc
|
||||
import freeflowuniverse.herolib.schemas.jsonschema
|
||||
import os
|
||||
|
||||
const actor_spec = specification.ActorSpecification{
|
||||
name: 'Pet Store'
|
||||
description: 'A sample API for a pet store'
|
||||
interfaces: [.openrpc, .command]
|
||||
methods: [specification.ActorMethod{
|
||||
name: 'listPets'
|
||||
description: 'List all pets'
|
||||
func: code.Function{
|
||||
interfaces: [.openapi]
|
||||
methods: [
|
||||
specification.ActorMethod{
|
||||
name: 'listPets'
|
||||
params: [code.Param{
|
||||
description: 'Maximum number of pets to return'
|
||||
name: 'limit'
|
||||
typ: code.Type{
|
||||
symbol: 'int'
|
||||
summary: 'List all pets'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'limit'
|
||||
summary: 'Maximum number of pets to return'
|
||||
description: 'Maximum number of pets to return'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
format: 'int32'
|
||||
})
|
||||
}
|
||||
}]
|
||||
}
|
||||
}, specification.ActorMethod{
|
||||
name: 'createPet'
|
||||
description: 'Create a new pet'
|
||||
func: code.Function{
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pets'
|
||||
})
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 400
|
||||
message: 'Invalid request'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'createPet'
|
||||
}
|
||||
}, specification.ActorMethod{
|
||||
name: 'getPet'
|
||||
description: 'Get a pet by ID'
|
||||
func: code.Function{
|
||||
summary: 'Create a new pet'
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 400
|
||||
message: 'Invalid input'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'getPet'
|
||||
params: [code.Param{
|
||||
required: true
|
||||
description: 'ID of the pet to retrieve'
|
||||
name: 'petId'
|
||||
typ: code.Type{
|
||||
symbol: 'int'
|
||||
summary: 'Get a pet by ID'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'petId'
|
||||
summary: 'ID of the pet to retrieve'
|
||||
description: 'ID of the pet to retrieve'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
})
|
||||
}
|
||||
}]
|
||||
}
|
||||
}, specification.ActorMethod{
|
||||
name: 'deletePet'
|
||||
description: 'Delete a pet by ID'
|
||||
func: code.Function{
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Pet'
|
||||
})
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 404
|
||||
message: 'Pet not found'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'deletePet'
|
||||
params: [code.Param{
|
||||
required: true
|
||||
description: 'ID of the pet to delete'
|
||||
name: 'petId'
|
||||
typ: code.Type{
|
||||
symbol: 'int'
|
||||
summary: 'Delete a pet by ID'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'petId'
|
||||
summary: 'ID of the pet to delete'
|
||||
description: 'ID of the pet to delete'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
})
|
||||
}
|
||||
}]
|
||||
}
|
||||
}, specification.ActorMethod{
|
||||
name: 'listOrders'
|
||||
description: 'List all orders'
|
||||
func: code.Function{
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 404
|
||||
message: 'Pet not found'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'listOrders'
|
||||
}
|
||||
}, specification.ActorMethod{
|
||||
name: 'getOrder'
|
||||
description: 'Get an order by ID'
|
||||
func: code.Function{
|
||||
summary: 'List all orders'
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'array'
|
||||
items: jsonschema.Items(jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Order'
|
||||
}))
|
||||
})
|
||||
}
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'getOrder'
|
||||
params: [code.Param{
|
||||
required: true
|
||||
description: 'ID of the order to retrieve'
|
||||
name: 'orderId'
|
||||
typ: code.Type{
|
||||
symbol: 'int'
|
||||
summary: 'Get an order by ID'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'orderId'
|
||||
summary: 'ID of the order to retrieve'
|
||||
description: 'ID of the order to retrieve'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
})
|
||||
}
|
||||
}]
|
||||
}
|
||||
}, specification.ActorMethod{
|
||||
name: 'deleteOrder'
|
||||
description: 'Delete an order by ID'
|
||||
func: code.Function{
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Reference{
|
||||
ref: '#/components/schemas/Order'
|
||||
})
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 404
|
||||
message: 'Order not found'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'deleteOrder'
|
||||
params: [code.Param{
|
||||
required: true
|
||||
description: 'ID of the order to delete'
|
||||
name: 'orderId'
|
||||
typ: code.Type{
|
||||
symbol: 'int'
|
||||
summary: 'Delete an order by ID'
|
||||
parameters: [
|
||||
openrpc.ContentDescriptor{
|
||||
name: 'orderId'
|
||||
summary: 'ID of the order to delete'
|
||||
description: 'ID of the order to delete'
|
||||
schema: jsonschema.SchemaRef(jsonschema.Schema{
|
||||
typ: 'integer'
|
||||
format: 'int64'
|
||||
})
|
||||
}
|
||||
}]
|
||||
}
|
||||
}, specification.ActorMethod{
|
||||
name: 'createUser'
|
||||
description: 'Create a user'
|
||||
func: code.Function{
|
||||
]
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
}
|
||||
errors: [
|
||||
openrpc.ErrorSpec{
|
||||
code: 404
|
||||
message: 'Order not found'
|
||||
}
|
||||
]
|
||||
},
|
||||
specification.ActorMethod{
|
||||
name: 'createUser'
|
||||
summary: 'Create a user'
|
||||
result: openrpc.ContentDescriptor{
|
||||
name: 'result'
|
||||
description: 'The response of the operation.'
|
||||
}
|
||||
}
|
||||
}]
|
||||
objects: [specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'Pet'
|
||||
]
|
||||
objects: [
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'Pet'
|
||||
}
|
||||
},
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'NewPet'
|
||||
}
|
||||
},
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'Pets'
|
||||
}
|
||||
},
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'Order'
|
||||
}
|
||||
},
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'User'
|
||||
}
|
||||
},
|
||||
specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'NewUser'
|
||||
}
|
||||
}
|
||||
}, specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'NewPet'
|
||||
}
|
||||
}, specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'Pets'
|
||||
}
|
||||
}, specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'Order'
|
||||
}
|
||||
}, specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'User'
|
||||
}
|
||||
}, specification.BaseObject{
|
||||
structure: code.Struct{
|
||||
name: 'NewUser'
|
||||
}
|
||||
}]
|
||||
]
|
||||
}
|
||||
|
||||
const destination = '${os.dir(@FILE)}/testdata'
|
||||
|
||||
fn test_generate_actor_module() {
|
||||
fn test_generate_plain_actor_module() {
|
||||
// plain actor module without interfaces
|
||||
actor_module := generate_actor_module(actor_spec)!
|
||||
actor_module.write(destination,
|
||||
format: true
|
||||
overwrite: true
|
||||
compile: true
|
||||
test: true
|
||||
)!
|
||||
}
|
||||
|
||||
fn test_generate_actor_module_with_openrpc_interface() {
|
||||
// plain actor module without interfaces
|
||||
actor_module := generate_actor_module(actor_spec, interfaces: [.openrpc])!
|
||||
actor_module.write(destination,
|
||||
format: true
|
||||
overwrite: true
|
||||
compile: true
|
||||
test: true
|
||||
)!
|
||||
}
|
||||
|
||||
@@ -19,8 +19,12 @@ pub fn generate_client_file(spec ActorSpecification) !VFile {
|
||||
actor.Client
|
||||
}
|
||||
|
||||
fn new_client() Client {
|
||||
return Client{}
|
||||
fn new_client() !Client {
|
||||
mut redis := redisclient.new(\'localhost:6379\')!
|
||||
mut rpc_q := redis.rpc_get(\'actor_\${name}\')
|
||||
return Client{
|
||||
rpc: rpc_q
|
||||
}
|
||||
}'}
|
||||
|
||||
for method in spec.methods {
|
||||
@@ -30,10 +34,10 @@ pub fn generate_client_file(spec ActorSpecification) !VFile {
|
||||
return VFile {
|
||||
imports: [
|
||||
Import{
|
||||
mod: 'freeflowuniverse.herolib.data.paramsparser'
|
||||
mod: 'freeflowuniverse.herolib.baobab.actor'
|
||||
},
|
||||
Import{
|
||||
mod: 'freeflowuniverse.herolib.baobab.actor'
|
||||
mod: 'freeflowuniverse.herolib.core.redisclient'
|
||||
}
|
||||
]
|
||||
name: 'client'
|
||||
|
||||
@@ -2,7 +2,8 @@ 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.schemas.openrpc {ContentDescriptor}
|
||||
import freeflowuniverse.herolib.schemas.jsonschema.codegen {schemaref_to_type}
|
||||
import freeflowuniverse.herolib.baobab.specification {ActorMethod, ActorSpecification}
|
||||
import os
|
||||
import json
|
||||
@@ -15,6 +16,7 @@ fn generate_handle_file(spec ActorSpecification) !VFile {
|
||||
}
|
||||
return VFile {
|
||||
name: 'act'
|
||||
imports: [Import{mod:'freeflowuniverse.herolib.baobab.actions' types:['Action']}]
|
||||
items: items
|
||||
}
|
||||
}
|
||||
@@ -38,11 +40,11 @@ pub fn generate_handle_function(spec ActorSpecification) string {
|
||||
return [
|
||||
'// AUTO-GENERATED FILE - DO NOT EDIT MANUALLY',
|
||||
'',
|
||||
'pub fn (mut actor ${actor_name_pascal}Actor) act(action Action) !Response {',
|
||||
'pub fn (mut actor ${actor_name_pascal}Actor) act(action Action) !Action {',
|
||||
' match action.name {',
|
||||
routes.join('\n'),
|
||||
' else {',
|
||||
' return error("Unknown operation: \${req.operation.operation_id}")',
|
||||
' return error("Unknown operation: \${action.name}")',
|
||||
' }',
|
||||
' }',
|
||||
'}',
|
||||
@@ -52,28 +54,72 @@ pub fn generate_handle_function(spec ActorSpecification) string {
|
||||
pub fn generate_method_handle(actor_name string, method ActorMethod) !string {
|
||||
actor_name_pascal := texttools.name_fix_snake_to_pascal(actor_name)
|
||||
name_fixed := texttools.name_fix_snake(method.name)
|
||||
if name_fixed == "create_pet" {
|
||||
println('debug ${method}')
|
||||
}
|
||||
mut handler := '// Handler for ${name_fixed}\n'
|
||||
handler += "fn (mut actor ${actor_name_pascal}Actor) handle_${name_fixed}(data string) !string {\n"
|
||||
if method.parameters.len > 0 {
|
||||
params_zero := method.parameters[0].name
|
||||
handler += ' params := json.decode(${params_zero}, data) or { return error("Invalid input data: \${err}") }\n'
|
||||
handler += ' result := actor.${name_fixed}(params)\n'
|
||||
} else {
|
||||
handler += ' result := actor.${name_fixed}()\n'
|
||||
if method.parameters.len == 1 {
|
||||
param := method.parameters[0]
|
||||
param_name := texttools.name_fix_snake(param.name)
|
||||
decode_stmt := generate_decode_stmt('data', param)!
|
||||
handler += '${param_name} := ${decode_stmt}\n'
|
||||
}
|
||||
handler += ' return json.encode(result)\n'
|
||||
if method.parameters.len > 1 {
|
||||
handler += 'params_arr := json2.raw_decode(data).arr()\n'
|
||||
for i, param in method.parameters {
|
||||
param_name := texttools.name_fix_snake(param.name)
|
||||
decode_stmt := generate_decode_stmt('params_arr[${i}]', param)!
|
||||
handler += '${param_name} := ${decode_stmt}'
|
||||
}
|
||||
// params_zero := schema_to_type(method.parameters[0].schema)
|
||||
// handler += ' params := json.decode(${params_zero}, data) or { return error("Invalid input data: \${err}") }\n'
|
||||
// handler += ' result := actor.${name_fixed}(params)\n'
|
||||
}
|
||||
call_stmt := generate_call_stmt(method)!
|
||||
handler += '${call_stmt}\n'
|
||||
handler += '${generate_return_stmt(method)!}\n'
|
||||
handler += '}'
|
||||
return handler
|
||||
}
|
||||
|
||||
fn generate_call_stmt(method ActorMethod) !string {
|
||||
mut call_stmt := if schemaref_to_type(method.result.schema)!.vgen().trim_space() != '' {
|
||||
'${method.result.name} := '
|
||||
} else {''}
|
||||
name_fixed := texttools.name_fix_snake(method.name)
|
||||
param_names := method.parameters.map(texttools.name_fix_snake(it.name))
|
||||
call_stmt += 'actor.${name_fixed}(${param_names.join(", ")})!'
|
||||
return call_stmt
|
||||
}
|
||||
|
||||
fn generate_return_stmt(method ActorMethod) !string {
|
||||
if schemaref_to_type(method.result.schema)!.vgen().trim_space() != '' {
|
||||
return 'return json.encode(${method.result.name})'
|
||||
}
|
||||
return "return ''"
|
||||
}
|
||||
|
||||
// generates decode statement for variable with given name
|
||||
fn generate_decode_stmt(name string, param ContentDescriptor) !string {
|
||||
param_type := schemaref_to_type(param.schema)!
|
||||
if param_type.vgen().is_capital() {
|
||||
return 'json2.decode[${schemaref_to_type(param.schema)!.vgen()}](${name})'
|
||||
}
|
||||
// else if param.schema.typ == 'array' {
|
||||
// return 'json2.decode[${schemaref_to_type(param.schema)!.vgen()}](${name})'
|
||||
// }
|
||||
return '${name}.${param_type.vgen()}()'
|
||||
}
|
||||
|
||||
// Helper function to generate a case block for the main router
|
||||
fn generate_route_case(method string, operation_id string) string {
|
||||
name_fixed := texttools.name_fix_snake(operation_id)
|
||||
mut case_block := ' "${operation_id}" {'
|
||||
case_block += '\n response := actor.handle_${name_fixed}(req.body) or {'
|
||||
case_block += '\n return Response{ status: http.Status.internal_server_error, body: "Internal server error: \${err}" }'
|
||||
case_block += '\n response := actor.handle_${name_fixed}(action.params) or {'
|
||||
case_block += '\n return Action{ result: err.msg() }'
|
||||
case_block += '\n }'
|
||||
case_block += '\n return Response{ status: http.Status.ok, body: response }'
|
||||
case_block += '\n return Action{ result: response }'
|
||||
case_block += '\n }'
|
||||
return case_block
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
module generator
|
||||
|
||||
import freeflowuniverse.herolib.core.code { Folder, IFile, VFile, CodeItem, File, Function, Import, Module, Struct, CustomCode }
|
||||
import freeflowuniverse.herolib.core.code { Folder, IFile, VFile, CodeItem, File, Function, Param, Import, Module, Struct, CustomCode }
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.schemas.openrpc
|
||||
import freeflowuniverse.herolib.schemas.openrpc.codegen {content_descriptor_to_parameter}
|
||||
@@ -28,7 +28,8 @@ pub fn generate_method_function(actor_name string, method ActorMethod) !Function
|
||||
return Function{
|
||||
name: texttools.name_fix_snake(method.name)
|
||||
receiver: code.new_param(v: 'mut actor ${actor_name_pascal}Actor')!
|
||||
result: content_descriptor_to_parameter(method.result)!
|
||||
result: Param{...content_descriptor_to_parameter(method.result)!, is_result: true}
|
||||
body:"panic('implement')"
|
||||
summary: method.summary
|
||||
description: method.description
|
||||
params: method.parameters.map(content_descriptor_to_parameter(it)!)
|
||||
|
||||
19
lib/baobab/generator/generate_model.v
Normal file
19
lib/baobab/generator/generate_model.v
Normal file
@@ -0,0 +1,19 @@
|
||||
module generator
|
||||
|
||||
import freeflowuniverse.herolib.core.code { Folder, IFile, VFile, CodeItem, File, Function, Param, Import, Module, Struct, CustomCode }
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.schemas.openrpc
|
||||
import freeflowuniverse.herolib.schemas.openrpc.codegen {content_descriptor_to_parameter}
|
||||
import freeflowuniverse.herolib.baobab.specification {ActorMethod, ActorSpecification}
|
||||
import os
|
||||
import json
|
||||
|
||||
pub fn generate_model_file(spec ActorSpecification) !VFile {
|
||||
actor_name_snake := texttools.name_fix_snake(spec.name)
|
||||
actor_name_pascal := texttools.name_fix_snake_to_pascal(spec.name)
|
||||
|
||||
return VFile {
|
||||
name: 'model'
|
||||
items: spec.objects.map(CodeItem(it.structure))
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,40 @@
|
||||
import os
|
||||
import freeflowuniverse.herolib.baobab.actor {IActor, RunParams}
|
||||
import freeflowuniverse.herolib.baobab.actor
|
||||
import freeflowuniverse.herolib.core.redisclient
|
||||
import freeflowuniverse.herolib.schemas.openapi
|
||||
import time
|
||||
|
||||
const name = '@{actor_name_snake}'
|
||||
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)!
|
||||
|
||||
@@[heap]
|
||||
struct @{actor_name_pascal}Actor {
|
||||
actor.Actor
|
||||
}
|
||||
|
||||
fn new() !@{actor_name_pascal}Actor {
|
||||
return @{actor_name_pascal}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 (mut a @{actor_name_pascal}Actor) handle(method string, data string) !string {
|
||||
action := a.act(
|
||||
name: method
|
||||
params: data
|
||||
)!
|
||||
return action.result
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
// Actor listens to the Redis queue for method invocations
|
||||
pub fn (mut a @{actor_name_pascal}Actor) run() ! {
|
||||
mut redis := redisclient.new('localhost:6379') or { panic(err) }
|
||||
mut rpc := redis.rpc_get(name)
|
||||
|
||||
println('Actor started and listening for tasks...')
|
||||
for {
|
||||
rpc.process(a.handle)!
|
||||
time.sleep(time.millisecond * 100) // Prevent CPU spinning
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
const test_port = 8101
|
||||
|
||||
pub fn test_new() ! {
|
||||
new() or {
|
||||
return error('Failed to create actor:\n@{dollar}{err}')
|
||||
}
|
||||
new() or { return error('Failed to create actor:\n@{dollar}{err}') }
|
||||
}
|
||||
|
||||
pub fn test_run() ! {
|
||||
spawn run()
|
||||
}
|
||||
|
||||
pub fn test_run_server() ! {
|
||||
spawn run_server(port: test_port)
|
||||
pub fn test_actor_run() ! {
|
||||
mut actor := new()!
|
||||
spawn actor.run()
|
||||
}
|
||||
Reference in New Issue
Block a user