Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring, and add helpers for calling functions #226

Merged
merged 4 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- Lowercase model name before invoking for hypermode hosted models [#221](https://github.com/gohypermode/runtime/pull/221)
- Improve HTTP error messages [#222](https://github.com/gohypermode/runtime/pull/222)
- Add host function for direct logging [#224](https://github.com/gohypermode/runtime/pull/224)
- Refactoring, and add helpers for calling functions [#226](https://github.com/gohypermode/runtime/pull/226)

## 2024-06-03 - Version 0.8.2

Expand Down
35 changes: 9 additions & 26 deletions functions/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

"hmruntime/logger"
"hmruntime/plugins"
"hmruntime/wasmhost"
)

var Functions = make(map[string]FunctionInfo)
Expand All @@ -19,38 +18,22 @@ type FunctionInfo struct {
Plugin *plugins.Plugin
}

func MonitorRegistration(ctx context.Context) {
go func() {
for {
select {
case <-wasmhost.RegistrationRequest:
r := newRegistration()
r.registerAll(ctx)
r.cleanup(ctx)
case <-ctx.Done():
return
}
}
}()
}

type registration struct {
functions map[string]bool
types map[string]bool
}

func newRegistration() *registration {
return &registration{
func RegisterFunctions(ctx context.Context, plugins []plugins.Plugin) {
r := &registration{
functions: make(map[string]bool),
types: make(map[string]bool),
}
}

func (r *registration) registerAll(ctx context.Context) {
var plugins = wasmhost.Plugins.GetAll()
for _, plugin := range plugins {
r.registerPlugin(ctx, &plugin)
}

r.cleanup(ctx)
}

type registration struct {
functions map[string]bool
types map[string]bool
}

func (r *registration) registerPlugin(ctx context.Context, plugin *plugins.Plugin) {
Expand Down
38 changes: 38 additions & 0 deletions hostfunctions/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
import (
"context"
"errors"
"fmt"
"strings"

"hmruntime/functions"
"hmruntime/functions/assemblyscript"

wasm "github.com/tetratelabs/wazero/api"
Expand Down Expand Up @@ -112,3 +115,38 @@
// err6 := readParam[T6](ctx, mod, p6, v6)
// return errors.Join(err1, err2, err3, err4, err5, err6)
// }

func callFunction(ctx context.Context, mod wasm.Module, fnName string, inputValues ...any) (any, error) {

Check failure on line 119 in hostfunctions/helpers.go

View workflow job for this annotation

GitHub Actions / lint

func `callFunction` is unused (unused)
info, ok := functions.Functions[fnName]
if !ok {
return nil, fmt.Errorf("no function registered named %s", fnName)
}

parameters := make(map[string]any, len(inputValues))
for i, value := range inputValues {
name := info.Function.Parameters[i].Name
parameters[name] = value
}

return functions.CallFunction(ctx, mod, info, parameters)
}

func verifyFunctionSignature(fnName string, expectedTypes ...string) error {
info, ok := functions.Functions[fnName]
if !ok {
return fmt.Errorf("no function registered named %s", fnName)
}

if len(expectedTypes) == 0 {
return errors.New("expectedTypes must not be empty")
}
l := len(expectedTypes)
expectedSig := fmt.Sprintf("(%s):%s", strings.Join(expectedTypes[:l-1], ","), expectedTypes[l-1])

sig := info.Function.Signature()
if sig != expectedSig {
return fmt.Errorf("function %s has signature %s, expected %s", fnName, sig, expectedSig)
}

return nil
}
46 changes: 46 additions & 0 deletions hostfunctions/helpers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2024 Hypermode, Inc.
*/

package hostfunctions

import (
"hmruntime/functions"
"hmruntime/plugins"
"testing"
)

func Test_VerifyFunctionSignature(t *testing.T) {

functions.Functions["myFunction"] = functions.FunctionInfo{
Function: plugins.FunctionSignature{
Name: "myFunction",
Parameters: []plugins.Parameter{
{Name: "param1", Type: plugins.TypeInfo{Name: "int"}},
{Name: "param2", Type: plugins.TypeInfo{Name: "string"}},
},
ReturnType: plugins.TypeInfo{Name: "bool"},
}}

err := verifyFunctionSignature("myFunction", "int", "string", "bool")
if err != nil {
t.Errorf("verifyFunctionSignature failed: %v", err)
}

functions.Functions["anotherFunction"] = functions.FunctionInfo{
Function: plugins.FunctionSignature{
Name: "anotherFunction",
ReturnType: plugins.TypeInfo{Name: "bool"},
},
}

err = verifyFunctionSignature("anotherFunction", "bool")
if err != nil {
t.Errorf("verifyFunctionSignature failed: %v", err)
}

err = verifyFunctionSignature("nonExistentFunction", "float64")
if err == nil {
t.Error("verifyFunctionSignature should have returned an error for non-existent function")
}
}
4 changes: 0 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"hmruntime/aws"
"hmruntime/config"
"hmruntime/db"
"hmruntime/functions"
"hmruntime/graphql"
"hmruntime/logger"
"hmruntime/manifestdata"
Expand Down Expand Up @@ -81,9 +80,6 @@ func initRuntimeServices(ctx context.Context) {
// Initialize the metadata database
db.Initialize(ctx)

// Watch for function registration requests
functions.MonitorRegistration(ctx)

// Load app data and monitor for changes
manifestdata.MonitorManifestFile(ctx)

Expand Down
32 changes: 32 additions & 0 deletions plugins/plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package plugins
import (
"context"
"fmt"
"strings"
"time"

"hmruntime/utils"
Expand Down Expand Up @@ -38,6 +39,37 @@ type FunctionSignature struct {
ReturnType TypeInfo `json:"returnType"`
}

func (f *FunctionSignature) String() string {
b := strings.Builder{}
b.WriteString(f.Name)
b.WriteString("(")
for i, p := range f.Parameters {
if i > 0 {
b.WriteString(", ")
}
b.WriteString(p.Name)
b.WriteString(": ")
b.WriteString(p.Type.Name)
}
b.WriteString("): ")
b.WriteString(f.ReturnType.Name)
return b.String()
}

func (f *FunctionSignature) Signature() string {
b := strings.Builder{}
b.WriteString("(")
for i, p := range f.Parameters {
if i > 0 {
b.WriteString(",")
}
b.WriteString(p.Type.Name)
}
b.WriteString("):")
b.WriteString(f.ReturnType.Name)
return b.String()
}

type TypeDefinition struct {
Id uint32 `json:"id"`
Size uint32 `json:"size"`
Expand Down
5 changes: 3 additions & 2 deletions wasmhost/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"fmt"
"time"

"hmruntime/functions"
"hmruntime/logger"
"hmruntime/plugins"
"hmruntime/storage"
Expand Down Expand Up @@ -49,8 +50,8 @@ func MonitorPlugins(ctx context.Context) {
}
sm.Changed = func(errors []error) {
if len(errors) == 0 {
// Signal that we need to register functions
RegistrationRequest <- true
plugins := Plugins.GetAll()
functions.RegisterFunctions(ctx, plugins)
}
}
sm.Start(ctx)
Expand Down
3 changes: 0 additions & 3 deletions wasmhost/wasmhost.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ import (
// Global runtime instance for the WASM modules
var RuntimeInstance wazero.Runtime

// Channel used to signal that registration is needed
var RegistrationRequest chan bool = make(chan bool)

// Global, thread-safe registry of all plugins loaded by the host
var Plugins = plugins.NewPluginRegistry()

Expand Down
Loading