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

propagate Go context into HostFunctionCallContext #203

Merged
merged 7 commits into from
Feb 7, 2022

Conversation

pkedy
Copy link
Contributor

@pkedy pkedy commented Feb 4, 2022

This PR adds an alternate store.CallFunctionContext(ctx context.Context, moduleName, funcName string, params ...uint64) func so the host can set values in a Go context that are accessible via the context.Value in *wasm.HostFunctionCallContext. This would allow custom data as well as distributed tracing values to flow through the call stack in a way that Go developers would expect.

See examples/host_func_test.go for usage

This is a simpler and more idiomatic alternative to #183 and #184.

/cc @codefromthecrypt

Copy link
Contributor

@codefromthecrypt codefromthecrypt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should rip the bandaid and make Call require a context param. breaking the api has little effect now, and we'll have to break it again later. Otherwise looks great!

wasm/engine.go Outdated Show resolved Hide resolved
wasm/engine.go Outdated Show resolved Hide resolved
examples/host_func_test.go Outdated Show resolved Hide resolved
@@ -37,8 +44,8 @@ func Test_hostFunc(t *testing.T) {
bufAddr := ret[0]

// Store the address info to the memory.
binary.LittleEndian.PutUint32(ctx.Memory.Buffer[retBufPtr:], uint32(bufAddr))
binary.LittleEndian.PutUint32(ctx.Memory.Buffer[retBufSize:], bufferSize)
ctx.Memory.PutUint32(retBufPtr, uint32(bufAddr))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not for this PR, but this reminds me we are overdue making things interfaces as direct access to buffer like this is easy to get wrong! #204

wasm/store.go Outdated Show resolved Hide resolved
wasm/store.go Outdated
@@ -314,6 +315,10 @@ func (s *Store) Instantiate(module *Module, name string) error {
}

func (s *Store) CallFunction(moduleName, funcName string, params ...uint64) (results []uint64, resultTypes []ValueType, err error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can delete this option and then don't have to name it differently.

ex. dapr where there's no option except with context, it is simpler naming

https://github.com/dapr/go-sdk/blob/main/client/client.go

Since this is an early stage, we can break api now

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you know that I work on Dapr or was this coincidence? 😀

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did notice 😎 so decided to speak Lingua Dapra

wasm/engine.go Outdated Show resolved Hide resolved
@codefromthecrypt codefromthecrypt changed the title CallFunctionContext to pass a Go Context through to host calls propagate Go context into HostFunctionCallContext Feb 5, 2022
@codefromthecrypt
Copy link
Contributor

PS context propagation is absolutely important and best to decouple from things like lifecycle hooks. Later, we'll likely build on this with a begin/end hook design which can allow transparent metrics or tracing. This is bedrock for that also.

@mathetake
Copy link
Member

Yeah I like this

@pkedy
Copy link
Contributor Author

pkedy commented Feb 6, 2022

I think we should rip the bandaid and make Call require a context param. breaking the api has little effect now, and we'll have to break it again later.

@codefromthecrypt Totally agree! Changes made.

@pkedy pkedy marked this pull request as ready for review February 6, 2022 14:29
Copy link
Contributor

@codefromthecrypt codefromthecrypt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one doc backfill suggestion, then a question of how or if we want to handle a nil context on the CallFunction API. Otherwise, LGTM

wasm/store.go Show resolved Hide resolved
return fmt.Errorf("calling start function failed: %v", err)
}
}
return nil
}

func (s *Store) CallFunction(moduleName, funcName string, params ...uint64) (results []uint64, resultTypes []ValueType, err error) {
// Note: this API is unstable. See tetratelabs/wazero#170
func (s *Store) CallFunction(ctx context.Context, moduleName, funcName string, params ...uint64) (results []uint64, resultTypes []ValueType, err error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we fail early, fail late or default any nil context here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My gut says to set it to context.Background() so that host calls can assume a valid context is passed. That or fail/return an error.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok let's go with context.Background, and update the docs to say that's what it defaults if nil. TestStore_CallFunction should verify this is never nil

wasm/store.go Outdated
@@ -844,6 +847,7 @@ func DecodeBlockType(types []*TypeInstance, r io.Reader) (*FunctionType, uint64,

// HostFunctionCallContext is the first argument of all host functions.
type HostFunctionCallContext struct {
context.Context
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we don't typically use struct embedding, so we should trailing comment why if we do. Alternatively, we can de-embed this. wdyt @pkedy @mathetake @nullpo-head?

Suggested change
context.Context
context.Context

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah without concrete reason, we would like to avoid embedding

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but this case seems reasonable to me so trailing comments would help

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Embedding context I think is pretty common in web frameworks so you can pass it along. The standard http library does not so it might be a matter of preference. What are the reasons not to embed it? Just curious 😀

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarifying the owner of fields/methods at callsite is one!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sg!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. I have the change ready. Committing now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will say that it will be a little weird that Context() is a func and Memory is a field. But as you said, this will be reworked anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack and I promise I'll do my best to unweird it soon

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also PS I'm not doing this now because I don't want to drift your PR :D

wasm/store.go Outdated Show resolved Hide resolved
@codefromthecrypt
Copy link
Contributor

ps oops on arm drift

# github.com/tetratelabs/wazero/wasm/jit [github.com/tetratelabs/wazero/wasm/jit.test]
[14](https://github.com/tetratelabs/wazero/runs/5087432982?check_suite_focus=true#step:5:14)
Error: wasm/jit/jit_arm64_test.go:40:24: not enough arguments in call to engine.Call
[15](https://github.com/tetratelabs/wazero/runs/5087432982?check_suite_focus=true#step:5:15)
	have (*wasm.FunctionInstance)
[16](https://github.com/tetratelabs/wazero/runs/5087432982?check_suite_focus=true#step:5:16)
	want (context.Context, *wasm.FunctionInstance, ...uint64)

Copy link
Member

@mathetake mathetake left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excellent!

Signed-off-by: Phil Kedy <phil.kedy@gmail.com>
Copy link
Contributor

@codefromthecrypt codefromthecrypt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pkedy will merge when you say go. good work, here

@pkedy
Copy link
Contributor Author

pkedy commented Feb 7, 2022

Good to go. Thanks!

@codefromthecrypt codefromthecrypt merged commit 4819d72 into tetratelabs:main Feb 7, 2022
@pkedy pkedy deleted the call_function_context branch February 7, 2022 12:55
@codefromthecrypt
Copy link
Contributor

ps drift alert that this was renamed to ModuleContext. Also, if you are using something besides tinygo and/or need a WASI API not defined here, please pipe up in the issue #271

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants