Deprecated: Function get_magic_quotes_gpc() is deprecated in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 99

Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 619

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1169

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176
8000 GitHub - lovromazgon/hornet: ๐Ÿ Go plugins using WebAssembly and gRPC.
Nothing Special   »   [go: up one dir, main page]

Skip to content

lovromazgon/hornet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

30 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Hornet

hornet-logo

GitHub License Test Go Report Card Go Reference

Hornet is a Go library that provides a simple way to build plugins in Go applications using WebAssembly (Wasm), Wazero, and gRPC. Write your plugins in Go, compile them to Wasm, and communicate using familiar gRPC patterns with full type safety.

Features

  • Pure Go: Host and plugin can be written entirely in Go, compiled using the standard Go toolchain.
  • gRPC: Use standard gRPC services and protobuf messages.
  • Type-safe: Full compile-time type checking with generated protobuf code.
  • Easy development: Familiar Go patterns for both host and plugin development.
  • High-performance: Built on the wazero runtime.

Installation

Import Hornet in your Go project:

go get github.com/lovromazgon/hornet

Quick Start

Tip

See the examples/calculator directory for a runnable example of a Hornet plugin and host application. That example also shows how an SDK layer can be built on top of Hornet to simplify plugin implementation for end users.

1. Define Your Service

First, define your plugin interface using protobuf and gRPC:

// calculator.proto
syntax = "proto3";

package calculator.v1;

service CalculatorPlugin {
  rpc Add(AddRequest) returns (AddResponse);
  rpc Multiply(MultiplyRequest) returns (MultiplyResponse);
}

message AddRequest {
  int64 a = 1;
  int64 b = 2;
}

message AddResponse {
  int64 result = 1;
}

// ... other messages

Generate the Go code using protoc or buf:

protoc --go_out=. --go-grpc_out=. calculator.proto

2. Create the Plugin

Implementing the plugin is essentially the same as writing a gRPC server in Go. Additionally, you need to initialize the Hornet plugin server in the init function.

//go:build wasm

package main

import (
    "context"

    "github.com/lovromazgon/hornet"
    // Your generated protobuf code
    calculatorv1 "your-project/proto/calculator/v1"
)

func main() {
    // Required by the compiler but never called
}

func init() {
    // Initialize the plugin gRPC server
    srv := hornet.NewServer()
    calculatorv1.RegisterCalculatorPluginServer(srv, &Calculator{})
    hornet.InitPlugin(srv)
}

type Calculator struct {
    calculatorv1.UnimplementedCalculatorPluginServer
}

func (c *Calculator) Add(ctx context.Context, req *calculatorv1.AddRequest) (*calculatorv1.AddResponse, error) {
    result := req.GetA() + req.GetB()
    return &calculatorv1.AddResponse{Result: result}, nil
}

func (c *Calculator) Multiply(ctx context.Context, req *calculatorv1.MultiplyRequest) (*calculatorv1.MultiplyResponse, error) {
    result := req.GetA() * req.GetB()
    return &calculatorv1.MultiplyResponse{Result: result}, nil
}

3. Build the Wasm Plugin

Build the plugin with the standard Go toolchain by targeting the wasip1 OS and wasm architecture:

GOOS=wasip1 GOARCH=wasm go build -o calculator.wasm ./plugin

4. Create the Host Application

package main

import (
    "context"
    "fmt"
    "os"
    
    "github.com/lovromazgon/hornet"
    "github.com/tetratelabs/wazero"
    "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
    // Your generated protobuf code
    calculatorv1 "your-project/proto/calculator/v1"
)

func main() {
    ctx := context.Background()
    
    // Create Wasm runtime
    r := wazero.NewRuntime(ctx)
    defer r.Close(ctx)
    
    // Set up WASI (WebAssembly System Interface)
    wasi_snapshot_preview1.MustInstantiate(ctx, r)
    
    // Load the compiled Wasm plugin
    wasmBytes, err := os.ReadFile("calculator.wasm")
    if err != nil {
        panic(err)
    }
    
    // Instantiate the plugin
    module, client, err := hornet.InstantiateModuleAndClient(
        ctx, r, wasmBytes, 
        calculatorv1.NewCalculatorPluginClient,
    )
    if err != nil {
        panic(err)
    }
    defer module.Close(ctx)
    
    // Use the plugin
    result, err := client.Add(ctx, &calculatorv1.AddRequest{A: 10, B: 32})
    if err != nil {
        panic(err)
    }
    
    fmt.Printf("10 + 32 = %d\n", result.GetResult()) // Output: 10 + 32 = 42
}

Error Handling

Hornet propagates gRPC errors between host and plugin:

// In plugin
func (c *Calculator) Divide(ctx context.Context, req *calculatorv1.DivideRequest) (*calculatorv1.DivideResponse, error) {
    if req.GetB() == 0 {
        return nil, status.Error(codes.InvalidArgument, "division by zero")
    }
    // ... rest of implementation
}

// In host
result, err := client.Divide(ctx, &calculatorv1.DivideRequest{A: 10, B: 0})
if err != nil {
    // Handle gRPC error
    if s, ok := status.FromError(err); ok {
        fmt.Printf("Error: %s (code: %s)\n", s.Message(), s.Code())
    }
}

Limitations

  • No streaming: gRPC streaming is not supported in a Wasm environment.
  • Single-threaded: Wasm plugins run in a single-threaded context. If multiple concurrent calls are made, they will be serialized. If you need true concurrency, consider running multiple plugin instances.
  • Memory constraints: Wasm has a 4GB memory limit (though this is rarely a practical concern)
  • Buffer size: The buffer used for exchanging messages between host and plugin grows as needed. However, the buffer currently doesn't shrink, so if your plugin processes a large message once, the buffer will remain large for the lifetime of the plugin instance.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Acknowledgments

0