Skip to content

Use new metadata format #130

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

Merged
merged 2 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 4 additions & 4 deletions functions/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ func registerFunctions(ctx context.Context, gqlSchema string) error {
logger.Info(ctx).
Str("resolver", resolver).
Str("function", fnName).
Str("plugin", plugin.Metadata.Name).
Str("build_id", plugin.Metadata.BuildId).
Str("plugin", plugin.Name()).
Str("build_id", plugin.BuildId()).
Msg("Registered function.")
}
}
Expand All @@ -84,8 +84,8 @@ func registerFunctions(ctx context.Context, gqlSchema string) error {
logger.Info(ctx).
Str("resolver", resolver).
Str("function", info.FunctionName()).
Str("plugin", info.Plugin.Metadata.Name).
Str("build_id", info.Plugin.Metadata.BuildId).
Str("plugin", info.Plugin.Name()).
Str("build_id", info.Plugin.BuildId()).
Msg("Unregistered function.")
}
}
Expand Down
56 changes: 31 additions & 25 deletions host/management.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,27 @@ func loadPlugin(ctx context.Context, filename string) error {
}

// Get the metadata for the plugin.
metadata, foundMetadata := getPluginMetadata(&cm)

// Use the filename as the plugin name if no metadata is found.
if !foundMetadata {
metadata.Name = strings.TrimSuffix(filename, ".wasm")
metadata, err := getPluginMetadata(&cm)

// Apply fallback rules for missing metadata.
if err == errPluginMetadataNotFound {
var found bool
metadata, found = getPluginMetadata_old(&cm)
if found {
defer logger.Warn(ctx).
Str("filename", filename).
Str("plugin", metadata.Plugin).
Msg("Deprecated metadata format found in plugin. Please recompile your plugin using the latest version of the Hypermode Functions library.")
} else {
// Use the filename as the plugin name if no metadata is found.
metadata.Plugin = strings.TrimSuffix(filename, ".wasm")
defer logger.Warn(ctx).
Str("filename", filename).
Str("plugin", metadata.Plugin).
Msg("No metadata found in plugin. Please recompile your plugin using the latest version of the Hypermode Functions library.")
}
} else if err != nil {
return err
}

// Create and store the plugin.
Expand All @@ -93,12 +109,6 @@ func loadPlugin(ctx context.Context, filename string) error {

// Log the details of the loaded plugin.
logPluginLoaded(ctx, plugin)
if !foundMetadata {
logger.Warn(ctx).
Str("filename", filename).
Str("plugin", plugin.Metadata.Name).
Msg("No metadata found in plugin. Please recompile your plugin using the latest version of the Hypermode Functions library.")
}

return nil
}
Expand All @@ -109,12 +119,10 @@ func logPluginLoaded(ctx context.Context, plugin Plugin) {

metadata := plugin.Metadata

if metadata.Name != "" {
evt.Str("plugin", metadata.Name)
}

if metadata.Version != "" {
evt.Str("version", metadata.Version)
if metadata.Plugin != "" {
name, version := parseNameAndVersion(metadata.Plugin)
evt.Str("plugin", name)
evt.Str("version", version)
}

lang := plugin.Language()
Expand All @@ -130,12 +138,10 @@ func logPluginLoaded(ctx context.Context, plugin Plugin) {
evt.Time("build_ts", metadata.BuildTime)
}

if metadata.LibraryName != "" {
evt.Str("hypermode_library", metadata.LibraryName)
}

if metadata.LibraryVersion != "" {
evt.Str("hypermode_library_version", metadata.LibraryVersion)
if metadata.Library != "" {
name, version := parseNameAndVersion(metadata.Library)
evt.Str("hypermode_library", name)
evt.Str("hypermode_library_version", version)
}

if metadata.GitRepo != "" {
Expand All @@ -151,8 +157,8 @@ func logPluginLoaded(ctx context.Context, plugin Plugin) {

func unloadPlugin(ctx context.Context, plugin Plugin) error {
logger.Info(ctx).
Str("plugin", plugin.Metadata.Name).
Str("build_id", plugin.Metadata.BuildId).
Str("plugin", plugin.Name()).
Str("build_id", plugin.BuildId()).
Msg("Unloading plugin.")

Plugins.Remove(plugin)
Expand Down
2 changes: 1 addition & 1 deletion host/pluginregistry.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (pr *pluginRegistry) Remove(plugin Plugin) {
defer pr.mutex.Unlock()

for i, p := range pr.plugins {
if p == plugin {
if p.Name() == plugin.Name() {
pr.plugins[i] = pr.plugins[len(pr.plugins)-1]
pr.plugins = pr.plugins[:len(pr.plugins)-1]
break
Expand Down
72 changes: 59 additions & 13 deletions host/plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
package host

import (
"encoding/json"
"fmt"
"strings"
"time"

Expand All @@ -18,14 +20,24 @@ type Plugin struct {
}

type PluginMetadata struct {
Name string
Version string
LibraryName string
LibraryVersion string
BuildId string
BuildTime time.Time
GitRepo string
GitCommit string
Plugin string `json:"plugin"`
Library string `json:"library"`
BuildId string `json:"buildId"`
BuildTime time.Time `json:"buildTs"`
GitRepo string `json:"gitRepo"`
GitCommit string `json:"gitCommit"`
Functions []FunctionSignature `json:"functions"`
}

type FunctionSignature struct {
Name string `json:"name"`
Parameters []FunctionParameter `json:"parameters"`
ReturnType string `json:"returnType"`
}

type FunctionParameter struct {
Name string `json:"name"`
Type string `json:"type"`
}

type PluginLanguage int
Expand All @@ -48,11 +60,17 @@ func (lang PluginLanguage) String() string {
}

func (p *Plugin) Name() string {
return p.Metadata.Name
name, _ := parseNameAndVersion(p.Metadata.Plugin)
return name
}

func (p *Plugin) BuildId() string {
return p.Metadata.BuildId
}

func (p *Plugin) Language() PluginLanguage {
switch p.Metadata.LibraryName {
libName, _ := parseNameAndVersion(p.Metadata.Library)
switch libName {
case "@hypermode/functions-as":
return AssemblyScript
case "gohypermode/functions-go":
Expand All @@ -70,7 +88,35 @@ func parseNameAndVersion(s string) (name string, version string) {
return s[:i], s[i+1:]
}

func getPluginMetadata(cm *wazero.CompiledModule) (metadata PluginMetadata, found bool) {
func getCustomSectionData(cm *wazero.CompiledModule, name string) (data []byte, found bool) {
for _, sec := range (*cm).CustomSections() {
if sec.Name() == name {
data = sec.Data()
found = true
break
}
}
return data, found
}

var errPluginMetadataNotFound = fmt.Errorf("no metadata found in plugin")

func getPluginMetadata(cm *wazero.CompiledModule) (PluginMetadata, error) {
metadataJson, found := getCustomSectionData(cm, "hypermode_meta")
if !found {
return PluginMetadata{}, errPluginMetadataNotFound
}

metadata := PluginMetadata{}
err := json.Unmarshal(metadataJson, &metadata)
if err != nil {
return PluginMetadata{}, fmt.Errorf("failed to parse plugin metadata: %w", err)
}

return metadata, nil
}

func getPluginMetadata_old(cm *wazero.CompiledModule) (metadata PluginMetadata, found bool) {
for _, sec := range (*cm).CustomSections() {
name := sec.Name()
data := sec.Data()
Expand All @@ -83,10 +129,10 @@ func getPluginMetadata(cm *wazero.CompiledModule) (metadata PluginMetadata, foun
metadata.BuildTime, _ = time.Parse(time.RFC3339, string(data))
found = true
case "hypermode_library":
metadata.LibraryName, metadata.LibraryVersion = parseNameAndVersion(string(data))
metadata.Library = string(data)
found = true
case "hypermode_plugin":
metadata.Name, metadata.Version = parseNameAndVersion(string(data))
metadata.Plugin = string(data)
found = true
case "git_repo":
metadata.GitRepo = string(data)
Expand Down
4 changes: 2 additions & 2 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ func handleRequest(w http.ResponseWriter, r *http.Request) {
}

// Add plugin details to the context
ctx = context.WithValue(ctx, logger.PluginNameContextKey, info.Plugin.Metadata.Name)
ctx = context.WithValue(ctx, logger.BuildIdContextKey, info.Plugin.Metadata.BuildId)
ctx = context.WithValue(ctx, logger.PluginNameContextKey, info.Plugin.Name())
ctx = context.WithValue(ctx, logger.BuildIdContextKey, info.Plugin.BuildId())

// Get a module instance for this request.
// Each request will get its own instance of the plugin module,
Expand Down