Skip to content

Commit

Permalink
chore: refactor to use straight wasm
Browse files Browse the repository at this point in the history
Signed-off-by: Mark Phelps <[email protected]>
  • Loading branch information
markphelps committed Aug 14, 2024
1 parent 1e14906 commit f73bdc6
Show file tree
Hide file tree
Showing 9 changed files with 396 additions and 105 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace]
resolver = "2"
members = ["./flipt-engine-ffi", "./flipt-engine-wasm-js", "./flipt-evaluation"]
members = ["./flipt-engine-ffi", "./flipt-engine-wasm", "./flipt-engine-wasm-js", "./flipt-evaluation"]

[profile.release]
strip = true
Expand Down
89 changes: 80 additions & 9 deletions flipt-client-go/evaluation.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package evaluation

import (
"bytes"
"context"
"encoding/json"
"fmt"
Expand All @@ -11,7 +12,7 @@ import (
)

var (
//go:embed ext/flipt_evaluation_wasi.wasm
//go:embed ext/flipt_evaluation_wasm.wasm
wasm []byte
)

Expand All @@ -20,6 +21,8 @@ type Client struct {
namespace string
instance *wasmtime.Instance
store *wasmtime.Store
memory *wasmtime.Memory
enginePtr int32
}

// NewClient constructs a Client.
Expand Down Expand Up @@ -54,15 +57,55 @@ func NewClient(opts ...clientOption) (*Client, error) {
return nil, err
}

f := instance.GetFunc(store, "new")
f := instance.GetFunc(store, "initialize_engine")
if f == nil {
return nil, fmt.Errorf("new function not found")
return nil, fmt.Errorf("initialize_engine function not found")
}

if _, err := f.Call(store, "default", "{}"); err != nil {
namespace := "default"
lenNamespace := len(namespace)

payload := "{\"namespace\": {\"key\": \"default\"}, \"flags\": []}"
lenPayload := len(payload)

// allocate memory for the strings
allocate := instance.GetFunc(store, "allocate")
if allocate == nil {
return nil, fmt.Errorf("allocate function not found")
}

namespacePtr, err := allocate.Call(store, lenNamespace)
if err != nil {
return nil, err
}
payloadPtr, err := allocate.Call(store, lenPayload)
if err != nil {
return nil, err
}

// get a pointer to the memory
memoryInstance := instance.GetExport(store, "memory").Memory()
if memoryInstance == nil {
return nil, fmt.Errorf("memory not found in WASM instance")
}

// need to keep this around for the lifetime of the client
// so it doesn't get garbage collected
client.memory = memoryInstance

// write namespace and payload to memory
data := memoryInstance.UnsafeData(store)
copy(data[uint32(namespacePtr.(int32)):], []byte(namespace))
copy(data[uint32(payloadPtr.(int32)):], []byte(payload))

// initialize_engine
enginePtr, err := f.Call(store, namespacePtr, lenNamespace, payloadPtr, lenPayload)
if err != nil {
return nil, err
}

client.enginePtr = enginePtr.(int32)

client.instance = instance
client.store = store

Expand Down Expand Up @@ -123,19 +166,47 @@ func (e *Client) EvaluateVariant(_ context.Context, flagKey, entityID string, ev
return nil, err
}

f := e.instance.GetFunc(e.store, "evaluate-variant")
lenEreq := len(ereq)
// allocate memory for the strings
allocate := e.instance.GetFunc(e.store, "allocate")
if allocate == nil {
return nil, fmt.Errorf("allocate function not found")
}

deallocate := e.instance.GetFunc(e.store, "deallocate")
if deallocate == nil {
return nil, fmt.Errorf("deallocate function not found")
}

ereqPtr, err := allocate.Call(e.store, lenEreq)
if err != nil {
return nil, err
}

defer deallocate.Call(e.store, ereqPtr, lenEreq)

// copy the evaluation request to the memory
data := e.memory.UnsafeData(e.store)
copy(data[uint32(ereqPtr.(int32)):], ereq)

f := e.instance.GetFunc(e.store, "evaluate_variant")
if f == nil {
return nil, fmt.Errorf("evaluate-variant function not found")
return nil, fmt.Errorf("evaluate_variant function not found")
}

result, err := f.Call(e.store, ereq)
resultPtr, err := f.Call(e.store, e.enginePtr, ereqPtr, lenEreq)
if err != nil {
return nil, err
}

var vr *VariantResult
result := e.memory.UnsafeData(e.store)[uint32(resultPtr.(int32)):]
n := bytes.IndexByte(result, 0)
if n < 0 {
n = 0
}

if err := json.Unmarshal([]byte(result.(string)), &vr); err != nil {
var vr *VariantResult
if err := json.Unmarshal(result[:n], &vr); err != nil {
return nil, err
}

Expand Down
4 changes: 1 addition & 3 deletions flipt-engine-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ tokio = { version = "1.33.0", features = ["full"] }
futures = "0.3"
openssl = { version = "0.10", features = ["vendored"] }
thiserror = "1.0.63"

[dependencies.flipt-evaluation]
path = "../flipt-evaluation"
flipt-evaluation = { path = "../flipt-evaluation" }

[dev-dependencies]
mockall = "0.13.0"
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "flipt-evaluation-wasi"
name = "flipt-evaluation-wasm"
version = "0.1.0"
edition = "2021"

Expand All @@ -8,10 +8,9 @@ edition = "2021"
[lib]
crate-type = ["cdylib"]

[build]
target = "wasm32-wasi"

[dependencies]
wit-bindgen = "0.29.0"
libc = "0.2.150"
serde = { version = "1.0.147", features = ["derive"] }
serde_json = { version = "1.0.89", features = ["raw_value"] }
thiserror = "1.0.63"
flipt-evaluation = { path = "../flipt-evaluation" }
Loading

0 comments on commit f73bdc6

Please sign in to comment.