refactor: use new API structure

This commit is contained in:
Peter 2023-09-05 22:06:42 +02:00
parent 8ded4bc17b
commit 04644e99d9
Signed by: prskr
GPG key ID: C1DB5D2E8DB512F9
13 changed files with 172 additions and 162 deletions

16
api.go
View file

@ -6,17 +6,17 @@ import (
"log/slog"
"time"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
commonv1 "code.icb4dc0.de/buildr/api/generated/common/v1"
)
type Category = rpcv1.Category
type Category = commonv1.Category
const (
CategoryTool = rpcv1.Category_CategoryTool
CategoryTask = rpcv1.Category_CategoryTask
CategoryBuild = rpcv1.Category_CategoryBuild
CategoryPackage = rpcv1.Category_CategoryPackage
CategoryRelease = rpcv1.Category_CategoryRelease
CategoryTool = commonv1.Category_CategoryTool
CategoryTask = commonv1.Category_CategoryTask
CategoryBuild = commonv1.Category_CategoryBuild
CategoryPackage = commonv1.Category_CategoryPackage
CategoryRelease = commonv1.Category_CategoryRelease
)
type StateMetadata struct {
@ -39,7 +39,7 @@ type ExecutionContext interface {
type TaskSpec[T Module] struct {
Module T
ModuleName string
Container *rpcv1.ContainerSpec
Container *commonv1.ContainerSpec
OutputDir string
}

View file

@ -2,24 +2,28 @@ package sdk
import (
"context"
"errors"
"log/slog"
_ "github.com/tetratelabs/tinymem"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
commonv1 "code.icb4dc0.de/buildr/api/generated/common/v1"
remotev1 "code.icb4dc0.de/buildr/api/generated/remote/v1"
wasiv1 "code.icb4dc0.de/buildr/api/generated/wasi/v1"
"code.icb4dc0.de/buildr/common/protocol"
"code.icb4dc0.de/buildr/wasi-module-sdk-go/mem"
)
var defaultRegistry = NewTypeRegistry()
var (
defaultRegistry = NewTypeRegistry()
startTaskWrapper = FuncExportWrapper[*remotev1.StartTaskRequest, *wasiv1.StartTaskResponse](StartTask)
inventoryWrapper = FuncExportWrapper[*wasiv1.PluginInventoryRequest, *wasiv1.PluginInventoryResponse](GetInventory)
helpForWrapper = FuncExportWrapper[*wasiv1.HelpRequest, *wasiv1.HelpResponse](HelpForModule)
)
func Register(cat Category, moduleName string, factory Factory) {
defaultRegistry.Add(cat, moduleName, factory)
}
//export inventory
func Inventory() uint64 {
var inventory rpcv1.PluginInventory
func GetInventory(*wasiv1.PluginInventoryRequest) (*wasiv1.PluginInventoryResponse, error) {
var inventory wasiv1.PluginInventoryResponse
for _, t := range defaultRegistry.List() {
m := defaultRegistry.Get(t.Category, t.Type)
@ -33,8 +37,8 @@ func Inventory() uint64 {
panic(err)
}
inventory.Specs = append(inventory.Specs, &rpcv1.PluginInventory_InventorySpec{
ModuleRef: &rpcv1.ModuleReference{
inventory.Specs = append(inventory.Specs, &wasiv1.PluginInventoryResponse_InventorySpec{
ModuleRef: &commonv1.ModuleReference{
ModuleCategory: t.Category,
ModuleType: t.Type,
},
@ -42,57 +46,44 @@ func Inventory() uint64 {
})
}
data, err := inventory.MarshalVT()
if err != nil {
panic(err)
}
return mem.UnifyPtrSize(mem.DataToUnmanagedPtr(data))
return &inventory, nil
}
//export run
func Run(specPtr, specSize uint32) {
var startTask rpcv1.StartTaskRequest
if err := startTask.UnmarshalVT(mem.DataFromPtr(specPtr, specSize)); err != nil {
panic(err)
}
executor := NewExecutor(startTask.Buildr.Repo.Root, startTask.Buildr.OutDir, startTask.Buildr.BinDir)
reference := startTask.GetReference().GetModule()
func StartTask(req *remotev1.StartTaskRequest) (*wasiv1.StartTaskResponse, error) {
executor := NewExecutor(req.Buildr.Repo.Root, req.Buildr.OutDir, req.Buildr.BinDir)
reference := req.GetReference().GetModule()
module := defaultRegistry.Get(reference.GetModuleCategory(), reference.GetModuleType())
if err := protocol.Unmarshal(startTask.GetSpec(), module); err != nil {
if err := protocol.Unmarshal(req.GetSpec(), module); err != nil {
executor.logger.Error("Failed to unmarshal spec", slog.String("error", err.Error()))
panic(err)
return nil, err
}
executor.Run(context.Background(), module)
var startTaskResponse wasiv1.StartTaskResponse
if err := executor.Run(context.Background(), module); err != nil {
startTaskResponse.Error = err.Error()
}
return &startTaskResponse, nil
}
//export help
func HelpFor(pecPtr, specSize uint32) uint64 {
var helpRequest rpcv1.HelpRequest
if err := helpRequest.UnmarshalVT(mem.DataFromPtr(pecPtr, specSize)); err != nil {
panic(err)
}
func HelpForModule(helpRequest *wasiv1.HelpRequest) (*wasiv1.HelpResponse, error) {
module := defaultRegistry.Get(helpRequest.ModuleReference.ModuleCategory, helpRequest.ModuleReference.ModuleType)
if module == nil {
return 0
return nil, errors.New("unknown module")
}
helper, ok := module.(Helper)
if !ok {
return 0
return new(wasiv1.HelpResponse), nil
}
modHelp := helper.Help()
helpResponse := &rpcv1.HelpResponse{
helpResponse := &wasiv1.HelpResponse{
Name: modHelp.Name,
Description: modHelp.Description,
Examples: make([]*rpcv1.TaskExample, 0, len(modHelp.Examples)),
Examples: make([]*wasiv1.TaskExample, 0, len(modHelp.Examples)),
}
for _, e := range modHelp.Examples {
@ -100,10 +91,10 @@ func HelpFor(pecPtr, specSize uint32) uint64 {
if err != nil {
panic(err)
}
helpResponse.Examples = append(helpResponse.Examples, &rpcv1.TaskExample{
helpResponse.Examples = append(helpResponse.Examples, &wasiv1.TaskExample{
Name: e.Name,
Description: e.Description,
TaskSpec: &rpcv1.TaskSpec{
TaskSpec: &commonv1.TaskSpec{
ModuleName: e.Spec.ModuleName,
Container: e.Spec.Container,
OutputDir: e.Spec.OutputDir,
@ -112,10 +103,20 @@ func HelpFor(pecPtr, specSize uint32) uint64 {
})
}
data, err := helpResponse.MarshalVT()
if err != nil {
panic(err)
}
return mem.UnifyPtrSize(mem.DataToUnmanagedPtr(data))
return helpResponse, nil
}
//export /buildr.rpc.v1.WasiExecutorService/PluginInventory
func Inventory(ptr, size uint32) uint64 {
return inventoryWrapper.Call(ptr, size)
}
//export /buildr.rpc.v1.WasiExecutorService/StartTask
func Run(ptr, size uint32) uint64 {
return startTaskWrapper.Call(ptr, size)
}
//export /buildr.rpc.v1.WasiExecutorService/Help
func HelpFor(ptr, size uint32) uint64 {
return helpForWrapper.Call(ptr, size)
}

View file

@ -4,7 +4,7 @@ import (
"fmt"
"io"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
wasiv1 "code.icb4dc0.de/buildr/api/generated/wasi/v1"
"code.icb4dc0.de/buildr/wasi-module-sdk-go/mem"
)
@ -38,7 +38,7 @@ func (c *Command) AddEnv(envToAdd map[string]string) {
}
func (c *Command) Run() error {
execReq := &rpcv1.ProcessStartRequest{
execReq := &wasiv1.ProcessStartRequest{
Command: c.Name,
Args: c.Args,
WorkingDirectory: c.WorkingDir,
@ -70,7 +70,7 @@ func (c *Command) Run() error {
return nil
}
execResp := new(rpcv1.ProcessStartResponse)
execResp := new(wasiv1.ProcessStartResponse)
if err := execResp.UnmarshalVT(mem.PtrToData(resultPtr, resultSize)); err != nil {
return err
}

View file

@ -4,12 +4,12 @@ import (
"errors"
"fmt"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
wasiv1 "code.icb4dc0.de/buildr/api/generated/wasi/v1"
"code.icb4dc0.de/buildr/wasi-module-sdk-go/mem"
)
func LookPath(file string) (string, error) {
lookupPathReq := &rpcv1.LookupPathRequest{
lookupPathReq := &wasiv1.LookupPathRequest{
Command: file,
}
@ -30,7 +30,7 @@ func LookPath(file string) (string, error) {
return "", fmt.Errorf("failed to lookup in path: %s", file)
}
lookupPathResp := new(rpcv1.LookupPathResponse)
lookupPathResp := new(wasiv1.LookupPathResponse)
if err := lookupPathResp.UnmarshalVT(mem.PtrToData(resultPtr, resultSize)); err != nil {
return "", err
}

View file

@ -21,9 +21,7 @@ type Executor struct {
binDir string
}
func (e Executor) Run(ctx context.Context, m Module) {
func (e Executor) Run(ctx context.Context, m Module) error {
execCtx := newWasiExecutionContext(ctx, e.logger, m, e.repoRoot, e.binDir, e.outDir)
if err := m.Execute(execCtx); err != nil {
e.logger.Error("Failed to execute module", slog.String("err", err.Error()))
}
return m.Execute(execCtx)
}

31
export.go Normal file
View file

@ -0,0 +1,31 @@
package sdk
import (
"reflect"
bapi "code.icb4dc0.de/buildr/api"
"code.icb4dc0.de/buildr/wasi-module-sdk-go/mem"
)
type FuncExportWrapper[TRequest bapi.ProtoMessage, TResponse bapi.ProtoMessage] func(req TRequest) (TResponse, error)
func (w FuncExportWrapper[TRequest, TResponse]) Call(reqPtr, reqSize uint32) uint64 {
var req TRequest
if reflect.TypeOf(req).Kind() == reflect.Ptr {
req = reflect.New(reflect.TypeOf(req).Elem()).Interface().(TRequest)
}
if err := req.UnmarshalVT(mem.DataFromPtr(reqPtr, reqSize)); err != nil {
panic(err)
}
if resp, err := w(req); err != nil {
panic(err)
} else if data, err := resp.MarshalVT(); err != nil {
panic(err)
} else if len(data) == 0 {
return 0
} else {
return mem.UnifyPtrSize(mem.DataToUnmanagedPtr(data))
}
}

12
go.mod
View file

@ -3,17 +3,11 @@ module code.icb4dc0.de/buildr/wasi-module-sdk-go
go 1.21
require (
code.icb4dc0.de/buildr/api v0.0.0-20230824061008-9729e3ce7ec3
code.icb4dc0.de/buildr/common v0.0.0-20230823164419-5a757074eaa3
github.com/tetratelabs/tinymem v0.1.0
code.icb4dc0.de/buildr/api v0.0.0-20230905195458-e4d230e5c7fd
code.icb4dc0.de/buildr/common v0.0.0-20230905195627-a3d5bb4f1ee7
)
require (
github.com/golang/protobuf v1.5.3 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/grpc v1.57.0 // indirect
github.com/google/go-cmp v0.5.9 // indirect
google.golang.org/protobuf v1.31.0 // indirect
)

23
go.sum
View file

@ -1,27 +1,12 @@
code.icb4dc0.de/buildr/api v0.0.0-20230824061008-9729e3ce7ec3 h1:CXt7gnJOMzk3lxXdYokRzwTeX6w7ZeceSBayvz8AfAw=
code.icb4dc0.de/buildr/api v0.0.0-20230824061008-9729e3ce7ec3/go.mod h1:eCeIvmMgYp/04nar7GnBDORMdO4jHYQl/RMiNJhyGf8=
code.icb4dc0.de/buildr/common v0.0.0-20230823164419-5a757074eaa3 h1:jWQCCE56vhfNoOuJj4JlCEcfXUB/40iR8L59j5xeh+s=
code.icb4dc0.de/buildr/common v0.0.0-20230823164419-5a757074eaa3/go.mod h1:u0PEZjq0l3ICCUgARZObM6Hc0ZlqkcjK0PBEozhAdNQ=
code.icb4dc0.de/buildr/api v0.0.0-20230905195458-e4d230e5c7fd h1:N4WkVoqphjFXfFwfKpLcEtS5lBCfd9NVytUutiszQ90=
code.icb4dc0.de/buildr/api v0.0.0-20230905195458-e4d230e5c7fd/go.mod h1:eWSjeX25XbbNGKlxVoOf2a8V6xOCIaQh5W65T7nNcL8=
code.icb4dc0.de/buildr/common v0.0.0-20230905195627-a3d5bb4f1ee7 h1:sqBO2IFI0Gs+FiM4kkQjj7QkC0p+AhJKqhCQqCEwlM4=
code.icb4dc0.de/buildr/common v0.0.0-20230905195627-a3d5bb4f1ee7/go.mod h1:biIRy/mBiVPAR/okWN5DFmB3Hnnxt2FP1Qswa4GBMeE=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/tetratelabs/tinymem v0.1.0 h1:Qza1JAg9lquPPJ/CIei5qQYx7t18KLie83O2WR6CM58=
github.com/tetratelabs/tinymem v0.1.0/go.mod h1:WFFTZFhLod6lTL+UetFAopVbGaB+KFsVcIY+RUv7NeY=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw=
google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=

View file

@ -2,7 +2,7 @@
package sdk
func _log_msg(ptr, size uint32) {}
func _log_msg(ptr, size uint32) (ptrSize uint64) { return 0 }
func _get_state(ptr, size uint32) (ptrSize uint64) { return 0 }

View file

@ -4,7 +4,7 @@ package sdk
//go:wasm-module buildr
//go:wasmimport buildr log_msg
func _log_msg(ptr, size uint32)
func _log_msg(ptr, size uint32) (ptrSize uint64)
//go:wasm-module buildr
//go:wasmimport buildr get_state

View file

@ -7,7 +7,7 @@ import (
"context"
"log/slog"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
remotev1 "code.icb4dc0.de/buildr/api/generated/remote/v1"
"code.icb4dc0.de/buildr/wasi-module-sdk-go/mem"
)
@ -28,15 +28,15 @@ func (h WASIHandler) Enabled(_ context.Context, level slog.Level) bool {
}
func (h WASIHandler) Handle(_ context.Context, record slog.Record) error {
taskLog := rpcv1.TaskLog{
taskLog := remotev1.TaskLog{
Time: record.Time.UnixMicro(),
Message: record.Message,
Level: int32(record.Level),
Attributes: make([]*rpcv1.TaskLog_LogAttribute, 0, record.NumAttrs()),
Attributes: make([]*remotev1.TaskLog_LogAttribute, 0, record.NumAttrs()),
}
record.Attrs(func(attr slog.Attr) bool {
taskLog.Attributes = append(taskLog.Attributes, &rpcv1.TaskLog_LogAttribute{
taskLog.Attributes = append(taskLog.Attributes, &remotev1.TaskLog_LogAttribute{
Key: attr.Key,
Value: attr.Value.String(),
})
@ -44,13 +44,10 @@ func (h WASIHandler) Handle(_ context.Context, record slog.Record) error {
return true
})
data, err := taskLog.MarshalVT()
if err != nil {
if _, err := LogMsg(&taskLog); err != nil {
return err
}
_log_msg(mem.DataToManagedPtr(data))
return nil
}
@ -77,3 +74,20 @@ func (h WASIHandler) WithGroup(name string) slog.Handler {
return newHandler
}
func LogMsg(taskLog *remotev1.TaskLog) (*remotev1.Result, error) {
data, err := taskLog.MarshalVT()
if err != nil {
return nil, err
}
resultPtr := _log_msg(mem.DataToManagedPtr(data))
data = mem.PtrToData(mem.UnifiedPtrToSizePtr(resultPtr))
resp := new(remotev1.Result)
if err := resp.UnmarshalVT(data); err != nil {
return nil, err
}
return resp, nil
}

View file

@ -56,10 +56,3 @@ func Allocate(size uint32) uintptr {
alivePointers[unsafePtr] = buf
return unsafePtr
}
//export deallocate
func Deallocate(ptr uintptr) {
pointersLock.Lock()
defer pointersLock.Unlock()
delete(alivePointers, ptr)
}

View file

@ -3,74 +3,68 @@ package sdk
import (
"errors"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
remotev1 "code.icb4dc0.de/buildr/api/generated/remote/v1"
"code.icb4dc0.de/buildr/wasi-module-sdk-go/mem"
)
type StateProxy struct{}
func (s StateProxy) Set(key, state []byte) error {
setCmd := &rpcv1.SetState{
setCmd := &remotev1.SetState{
Key: key,
Data: state,
}
data, err := setCmd.MarshalVT()
if err != nil {
if resp, err := SetState(setCmd); err != nil {
return err
}
result := _set_state(mem.DataToManagedPtr(data))
if result == 0 {
return errors.New("unknown error occurred")
}
resultPtr := uint32(result >> 32)
resultSize := uint32(result)
if resultSize == 0 {
} else if resp.Error != "" {
return errors.New(resp.Error)
} else {
return nil
}
resultMsg := new(rpcv1.Result)
if err := resultMsg.UnmarshalVT(mem.PtrToData(resultPtr, resultSize)); err != nil {
return err
}
if !resultMsg.Success {
if resultMsg.Error != "" {
return errors.New(resultMsg.Error)
}
return errors.New("unknown error occurred")
}
return nil
}
func (s StateProxy) Get(key []byte) (state []byte, meta StateMetadata, err error) {
getCmd := &rpcv1.GetStateRequest{
getCmd := &remotev1.GetStateRequest{
Key: key,
}
data, err := getCmd.MarshalVT()
if err != nil {
if resp, err := GetState(getCmd); err != nil {
return nil, StateMetadata{}, err
} else {
return resp.Data, StateMetadata{}, nil
}
result := _get_state(mem.DataToManagedPtr(data))
if result == 0 {
return nil, StateMetadata{}, errors.New("error occurred while processing request")
}
resultPtr := uint32(result >> 32)
resultSize := uint32(result)
if resultSize == 0 {
return nil, StateMetadata{}, nil
}
getStateResult := new(rpcv1.GetStateResponse)
if err := getStateResult.UnmarshalVT(mem.PtrToData(resultPtr, resultSize)); err != nil {
return nil, StateMetadata{}, err
}
return getStateResult.Data, StateMetadata{}, nil
}
func GetState(req *remotev1.GetStateRequest) (*remotev1.GetStateResponse, error) {
data, err := req.MarshalVT()
if err != nil {
return nil, err
}
resultPtr := _get_state(mem.DataToManagedPtr(data))
data = mem.PtrToData(mem.UnifiedPtrToSizePtr(resultPtr))
resp := new(remotev1.GetStateResponse)
if err := resp.UnmarshalVT(data); err != nil {
return nil, err
}
return resp, nil
}
func SetState(req *remotev1.SetState) (*remotev1.Result, error) {
data, err := req.MarshalVT()
if err != nil {
return nil, err
}
resultPtr := _set_state(mem.DataToManagedPtr(data))
data = mem.PtrToData(mem.UnifiedPtrToSizePtr(resultPtr))
resp := new(remotev1.Result)
if err := resp.UnmarshalVT(data); err != nil {
return nil, err
}
return resp, nil
}