diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 13e942af..4f64778e 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -151,7 +151,7 @@ RUN go${GOLANG_VERSION_HOST} install github.com/sqlc-dev/sqlc/cmd/sqlc@v1.20.0 RUN go${GOLANG_VERSION_HOST} install github.com/princjef/gomarkdoc/cmd/gomarkdoc@latest RUN go${GOLANG_VERSION_HOST} install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest RUN go${GOLANG_VERSION_HOST} install github.com/tetratelabs/wazero/cmd/wazero@v1.5.0 - +RUN go${GOLANG_VERSION_HOST} install github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc@latest #RUN go${GOLANG_VERSION_HOST} install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v${PROTOC_GRPC_VERSION} #RUN go${GOLANG_VERSION_HOST} install github.com/onsi/ginkgo/v2/ginkgo diff --git a/example/helloworld/Makefile b/example/helloworld/Makefile index 4b324659..009c8d33 100644 --- a/example/helloworld/Makefile +++ b/example/helloworld/Makefile @@ -12,7 +12,7 @@ GO_VERSION=1.21.0 .PHONY: test test: GOROOT=/home/parigot/deps/go${GO_VERSION} GOOS=wasip1 GOARCH=wasm go${GO_VERSION} test -c -o tester ./greeting - wasmtime -- tester -test.v + wazero run tester -test.v # first WASM file, compiled with GOOS and GOARCH set .PHONY: hello.p.wasm diff --git a/example/helloworld/README.md b/example/helloworld/README.md index 03132e16..589bdb13 100644 --- a/example/helloworld/README.md +++ b/example/helloworld/README.md @@ -3,8 +3,8 @@ Quickstart: * This is for people that know golang. -* Create a codespace. -* Make sure you are in the `helloworld` directory, not `parigot-example`. +* Create a codespace on github. +* Make sure you are in the `helloworld` directory, not the root of the repo. #### The most important files * `main.go`: the hello world program that calls the greeting service diff --git a/example/helloworld/build/.gitignore b/example/helloworld/build/.gitignore new file mode 100644 index 00000000..cc6293b3 --- /dev/null +++ b/example/helloworld/build/.gitignore @@ -0,0 +1,2 @@ +*.p.wasm + diff --git a/example/helloworld/tester b/example/helloworld/tester index de998f27..2e410767 100755 Binary files a/example/helloworld/tester and b/example/helloworld/tester differ diff --git a/site/content/en/codespaces-scap.png b/site/content/en/codespaces-scap.png new file mode 100644 index 00000000..ae436b83 Binary files /dev/null and b/site/content/en/codespaces-scap.png differ diff --git a/site/content/en/docs/Examples/_index.md b/site/content/en/docs/Examples/_index.md index 131bdb86..67a394ac 100755 --- a/site/content/en/docs/Examples/_index.md +++ b/site/content/en/docs/Examples/_index.md @@ -12,7 +12,7 @@ the `atlanta-0.3` version of parigot. {{% alert title="Repo" color="warning" %}} -You can see all the code of the examples in the -[parigot-examples](http://github.com/iansmith/parigot-examples) repository. +You can see all the code of the examples in the [example](https://github.com/iansmith/parigot/tree/master/example) +directory of the repository. {{% /alert %}} diff --git a/site/content/en/docs/Examples/helloworld.md b/site/content/en/docs/Examples/helloworld.md index 44bf5368..1f079171 100644 --- a/site/content/en/docs/Examples/helloworld.md +++ b/site/content/en/docs/Examples/helloworld.md @@ -36,9 +36,8 @@ textually small program could be self-contained and do something useful. B. Kernighan, 1973. We are going to walk through all the files in the -[helloworld](https://github.com/iansmith/parigot-example/tree/master/helloworld) -example part of the [parigot-expample](http://github.com/iasmith/parigot) -repository. We will pay special attention to the make targets as these are +[helloworld](https://github.com/iansmith/parigot/tree/master/example/helloworld) +example. We will pay special attention to the make targets as these are re-usable and in many cases explain "how to do things" with parigot. ## Boilerplate files @@ -49,7 +48,7 @@ if their content can be largely ignored for now. ### Makefile -The project's [Makefile](https://github.com/iansmith/parigot-example/blob/master/helloworld/Makefile) is really just a repository for useful commands, not +The project's [Makefile](https://github.com/iansmith/parigot/blob/master/example/helloworld/Makefile) is really just a repository for useful commands, not something that does builds by looking at files and computing new files based on recipies. Because golang has a much better build ability than most other languages, typically you can just do `make` anytime and let the Makefile try @@ -62,12 +61,16 @@ is needed. `all` builds the two wasm files that make up the program, `hello.p.wasm` and `greeting.p.wasm`. This is the default command, so it is run if you type - just `make`. - -{{% alert title="Limitation" color="warning" %}} -Currently, parigot uses two different versions of the go compiler from google. -We use go version 1.21RC2 for the guest code and go version 1.20 for the host -side code. This will be remedied as soon as the 1.21 version is fully released. + just `make`. The two wasm files are built into the `build` subdirectory. + The build is sufficiently fast that doing `make clean; make` is also ok. + +{{% alert title="Deep cut" color="info" %}} +parigot uses the traditional go compiler, version 1.21.x, from google's go team for the parigot +infrastructure. However, sometimes the infrastructure needs to build programs +for the local host (native code) such as the `runner` program. Other times it builds +wasm files that +are libraries that your code can use in _wasmland_. When building programs +like example/helloworld it is used only to build wasm code. {{% /alert %}} The `all` command invokes the compiler to build the wasm (guest) code. This @@ -98,7 +101,7 @@ framework. This test command is useful if you want to run unit tests that are completely guest-side code. Because WASM isn't directly executable, `go test` will not work, you have build a "program" that is the test and then run that program -via a Host. This test uses [wasmtime](http://wasmtime.dev) as the +via a Host. This test uses [wazero CLI](https://wazero.io) as the Host, since it is already present in our dev container, but any host should work. @@ -124,7 +127,11 @@ is no longer maintained. "generate" is the most key-to-parigot make target, as it generates stubs. These stubs implement the golang-specific type safe code that makes the parigot programming model work for golang developers. You need to run this anytime you -change the `greeting.proto` protobuf schema definition. +change the `greeting.proto` protobuf schema definition contained in the `proto` +directory. + +The default make target all runs `generate` just to be safe, even if it is not +needed. {{< /blocks/section >}} @@ -136,7 +143,8 @@ The `generate` target is a key part of the Makefile and the build process more generally. This make target runs three key commands. First, it uses [buf](https://buf.build) to run a lint pass over your .proto files. Then it uses buf to generate the typical golang types that derive from your -protobuf schema. Third, it uses `protoc-gen-parigot` which is a plugin for +protobuf schema (contained in the `proto` directory). Third, it uses +`protoc-gen-parigot` which is a plugin for the `protoc` protobuf compiler that generates parigot's stubs. In the case of `helloworld` you'll notice that the file @@ -178,6 +186,11 @@ that other protobuf implementations (perhaps [gogobuf](https://github.com/gogo/p [molecule](https://pkg.go.dev/github.com/richardartoul/molecule)?) will generate code that does not use reflection capabilities that are excluded from Tinygo. +Possibly of interest for dodging the protobuf problem: +* [go-plugin](https://github.com/knqyf263/go-plugin) +* [vtprotobuf](https://github.com/planetscale/vtprotobuf) + + {{%/alert %}} ##### clean @@ -187,25 +200,6 @@ and the compiled binaries (`.p.wasm` files) in `build`. The 'g' stands for gene automated tool's output belongs there. `make clean` does not remove the tools installed by `make tools` in the next section. -{{% alert title="Change coming" color="warning" %}} -Currently, the parigot system library, `syscall.so` is also resident in the -build directory. This will changed soon. -{{% /alert %}} - -##### tools - -`make tools` is something that you should only have to do once, when -you begin working with the source code of `hello world`. This command -downloads, compiles, and installs the two key tools that are needed to -do development using parigot: `runner` and `protoc-gen-parigot`. The former -runs parigot binaries and the latter generates the stubs referred to in the -[generate]({{< ref "#generate" >}}) section above. You will need to run this -again if you change versions of parigot or relaunch the dev container since that -starts with a fresh filesystem. - -`make tools` also installs the -parigot system's key host-side library `syscall.so` in the `plugin` directory. -At the moment, if you remove `plugin/syscall.so` you have to `make tools` again. ### buf.gen.yaml, buf.work.yaml Both of @@ -215,7 +209,7 @@ and are configuration files that most folks do not need to change. The `buf.gen.yaml` file tells `buf` what code generators to use. These are currently the golang (standard) one and the parigot one. The `buf.work.yml` file tells `buf` -where to look for your protobuf schema files, but is recommended by parigot that +where to look for your protobuf schema files, but is recommended that all your protobuf files be in a top level directory called `proto`. ## Source code files @@ -259,33 +253,41 @@ is probably enough for most projects when they are starting out. ### helloworld.toml This file is the [delpoyment -descriptor](https://github.com/iansmith/parigot-example/blob/master/helloworld/helloworld.toml) +descriptor](https://github.com/iansmith/parigot/blob/master/example/helloworld/helloworld.toml) for the hello world program. Its contents tell the [runner]({{< ref "#tools" >}}) program the information about the microservices, tests, and programs that need to be deployed to make the entire application run. The contents as of the time of writing are: ```toml - ## Note that because this is consumed from the hello-world root dir, the paths - ## are relative to that dir, not the root of the parigot-example repository. - - ParigotLibPath="build/syscall.so" - ParigotLibSymbol="ParigotInitialize" - - # the names of the microservices here have no significance, they are just for humans - [microservice.greet] - WasmPath="build/greeting.p.wasm" - Arg=[] - Env=[] - - - # helloworld, it has no services that it implements, it just consumes greet. - [microservice.helloworld] - WasmPath="build/hello.p.wasm" - Arg=[] - Env=[] - # this is the crucial line for parigot. "this is just a client and should run to completion". - Main=true +## Note that because this file is expected to be consumed in a dev container +## so the files have absolute paths that are correct for the container. + +## dev configuration in general +[config.dev] +## Load parigot code from shared object +ParigotLibPath="/workspaces/parigot/build/syscall.so" +ParigotLibSymbol="ParigotInitialize" +Timezone = "US/Eastern" +[config.dev.Timeout] +Startup = 100 # millis +Complete = 20 # millis + + +# greeting service +[config.dev.microservice.greet] +WasmPath="/workspaces/parigot/example/helloworld/build/greeting.p.wasm" +Arg=[] +Env=[] + +# helloworld, it has no services that it implements, it just consumes greet and +# runs to the end of main. +[config.dev.microservice.helloworld] +WasmPath="/workspaces/parigot/example/helloworld/build/hello.p.wasm" +Arg=[] +Env=[] +# this is the crucial line for parigot. "this is just a client and should run to completion". +Main=true ``` ### main.go @@ -319,7 +321,7 @@ import ( The imports are quite straightforward and should be supplied automatically by any sensible IDE (especially if your IDE uses [gopls](https://pkg.go.dev/golang.org/x/tools/gopls#section-readme)). Of mild -interest are the aliases `syscallguest`, `pcontext` and `lib`. +interest are the aliases `syscallguest` and `lib`. * syscallguest: This alias is necessary to not conflict with the import of `github.com/iansmith/parigot/g/syscall/v1` which is imported as `syscall`. @@ -329,14 +331,6 @@ golang. The syscall one is the definitions of the system calls generated from [the proto spec](https://github.com/iansmith/parigot/blob/master/api/proto/syscall/v1/syscall.proto). -* pcontext: This is our standard alias to avoid a conflict between parigot's [context manipulation code](https://github.com/iansmith/parigot/tree/master/context) -and standard library's `context`. - -{{% alert title="Change coming" color="warning" %}} -All of the parigot logging machinery is the in the "pcontext" library. This is going -to be completely overhauled in an upcoming version. -{{% /alert %}} - * lib: The golang guest side library uses the import name "lib" despite being `.../lib/go`. The alias is actually superfluous but was inserted by VSCode. @@ -355,19 +349,19 @@ library will remain as a model for other implementors of language bindings. In the initialization part of `helloworld` there is one key thing to notice: -[futures in launch](https://github.com/iansmith/parigot-example/blob/f10983cf91de637dc46b7cdae5978d00092a7f16/helloworld/main.go#L46) +[futures in launch](https://github.com/iansmith/parigot/blob/19e3202376bb2298a389186cc6fd8ce388bfd4e2/example/helloworld/main.go#L20) -The call to `Launch()` in theory would block the code from proceeding until all of it is +The call to `LaunchClient()` in theory would block the code from proceeding until all of it is dependencies listed above `MustInitClient` are up and running. Since in practice we cannot block, the returned value is a future that we attach success and failure functions to. -[MustRunClient](https://github.com/iansmith/parigot-example/blob/f10983cf91de637dc46b7cdae5978d00092a7f16/helloworld/main.go#L61) - -`MustRunClient` is the "main loop" of the program. It is constantly checking to see if there -are incoming requests or responses to previous calls. +The [mainloop](https://github.com/iansmith/parigot/blob/19e3202376bb2298a389186cc6fd8ce388bfd4e2/example/helloworld/main.go#L42) +of hello world is the critical portion, centered around `ReadOneAndCallClient`. +This is primarily for exposition, the call [MustRunClient](https://github.com/iansmith/parigot/blob/19e3202376bb2298a389186cc6fd8ce388bfd4e2/lib/go/callhelper.go#L37) +is more commonly used in such a situation. -[afterLaunch](https://github.com/iansmith/parigot-example/blob/f10983cf91de637dc46b7cdae5978d00092a7f16/helloworld/main.go#L68) +[afterLaunch](https://github.com/iansmith/parigot/blob/19e3202376bb2298a389186cc6fd8ce388bfd4e2/example/helloworld/main.go#L53) `afterLaunch()` is called from the success branch of the launch future. It does two things. One, it "locates" some service that implements the greeting service protocol. It then calls the method `FetchGreeting()` on the located @@ -384,7 +378,7 @@ has the functions Per our exposition above, this version of the library uses [continuations]({{< ref"continuations" >}}) and you seem them in action with the method call of `FetchGreeting` which is defined by [greeting's protobuf -specification](https://github.com/iansmith/parigot-example/blob/master/helloworld/proto/greeting/v1/greeting.proto). +specification](https://github.com/iansmith/parigot/blob/master/example/helloworld/proto/greeting/v1/greeting.proto). This continuation, in short, means that we do not yet know the outcome of the call, so you need to handle both the `Success` and `Failure` cases. In this example, it just prints out a message on the terminal. @@ -396,23 +390,26 @@ example, it just prints out a message on the terminal. Every service--and every program like helloworld--has a `main()` function to initialize data structures and the like at startup. -[Init](https://github.com/iansmith/parigot-example/blob/f10983cf91de637dc46b7cdae5978d00092a7f16/helloworld/greeting/main.go#L27) +[MustInitClient](https://github.com/iansmith/parigot/blob/19e3202376bb2298a389186cc6fd8ce388bfd4e2/lib/go/callhelper.go#L80) -The service implementation of greet uses the generated function Init() to initialize and +The service implementation of greet uses the generated function [Init()](https://github.com/iansmith/parigot/blob/19e3202376bb2298a389186cc6fd8ce388bfd4e2/example/helloworld/g/greeting/v1/greetingserver.p.go#L54) +to initialize and launch itself. As we saw with the `main()` function of helloworld, we are returned a future that represents the success or failure of launching the program (and waiting -on its dependencies). An additional paramater returned from `Init()` is a set of +on its dependencies). An additional parameter returned from `Init()` is a set of method bindings called `bindings`. This set of bindings is only useful if you want to manipulate the set of methods that this service responds to. It is not something -that many programs will ever need. +that many programs will ever need. This service method map will passed to +the generated [Run()](https://github.com/iansmith/parigot/blob/19e3202376bb2298a389186cc6fd8ce388bfd4e2/example/helloworld/greeting/main.go#L41) method. -[fetchGreeting](https://github.com/iansmith/parigot-example/blob/f10983cf91de637dc46b7cdae5978d00092a7f16/helloworld/greeting/main.go#L59) and -[FetchGreeting](https://github.com/iansmith/parigot-example/blob/f10983cf91de637dc46b7cdae5978d00092a7f16/helloworld/greeting/main.go#L75) are +[fetchGreeting](https://github.com/iansmith/parigot/blob/19e3202376bb2298a389186cc6fd8ce388bfd4e2/example/helloworld/greeting/main.go#L67) and +[FetchGreeting](https://github.com/iansmith/parigot/blob/19e3202376bb2298a389186cc6fd8ce388bfd4e2/example/helloworld/greeting/main.go#L83) are now defined by the implementation of the greeting service. Because the greeting service has a known method, `FetchGreeting`, no futher initialization work is needed and the method can be implemented as `FetchGreeting` (as seen in the greeting.proto file). The of the "split" versions of "FetchGreeting" is so that the true call implementation, `fetchGreeting()` can be called directly from a test. The return value of `FetchGreeting` is naturally a future and these -can be hard to test without running the "main loop" of parigot. See `greeting_test` for how a method like `fetchGreeting` +can be hard to test without running the "main loop" of parigot. See [greeting_test](https://github.com/iansmith/parigot/blob/master/example/helloworld/greeting/greeting_test.go) + for how a method like `fetchGreeting` is tested without using futures. ## The Big Trick @@ -437,7 +434,7 @@ The careful reader will have noticed that this four point definition above could generalized slightly from "processes" to "processes that run on different machines separated by a network" since all the same properties apply. Parigot does indeed generalize this and decides how to _deploy_ the application based on the -[deployment descriptor](http://localhost:1313/docs/examples/helloworld/#helloworldtoml). +[deployment descriptor](https://github.com/iansmith/parigot/blob/master/example/helloworld/helloworld.toml). With the code remaining unchanged but with a different deployment descriptor, you can run your application as these "guest" processes inside a single WASM Host (and on a single host!), or it will create multiple WASM host programs on multiple @@ -449,7 +446,7 @@ are network calls. That's a microservice architecture! The greeting test is quite simple: send one request (not using any parigot machinery) to the private, implementation function -[fetchGreeting](https://github.com/iansmith/parigot-example/blob/f10983cf91de637dc46b7cdae5978d00092a7f16/helloworld/greeting/greeting_test.go#L11). +[fetchGreeting](https://github.com/iansmith/parigot/blob/master/example/helloworld/greeting/greeting_test.go). We test that we got back what we expected in terms of the response object and the error code. Then we repeat the test, but with an out of bounds diff --git a/site/content/en/docs/Getting started/_index.md b/site/content/en/docs/Getting started/_index.md index 5d0b3e1d..981b400a 100644 --- a/site/content/en/docs/Getting started/_index.md +++ b/site/content/en/docs/Getting started/_index.md @@ -23,28 +23,68 @@ environment" or "IDE") and the editor knows how to work with the dev container for doing things like running programs, launching the debugger, using the shell *inside* the container. -#### The quick and mostly easy way +### What to try +Here is a [video](https://youtu.be/gJEEHfl-n6I) that can show you some things +to try in the dev container, like running the hello world example. -* What do your users need to do to start using your project? This could include downloading/installation instructions, including any prerequisites or system requirements. +### Github codespaces -* Introductory “Hello World” example, if appropriate. More complex tutorials should live in the Tutorials section. +You can launch a complete editor and working shell in your browser with parigot's +tooling already configured. You can do this with the `codespaces` tab under +the code button on the github repository. -Consider using the headings below for your getting started page. You can delete any that are not applicable to your project. +[Example screencap](/codespaces-scap.png) -## Prerequisites +Althought this is convenient, the machines that back codespace are quite slow, +and it can take several minutes to do the launch of a codespace. -Are there any system requirements for using your project? What languages are supported (if any)? Do users need to already have any software or tools installed? +### Github classic way -## Installation +* Clone the repo (`http://github.com/iansmith/parigot`) using git +* Launch vscode on our configured workspace, `parigot.code-workspace` at the +root of the repo. If you have vscode installed in the normal way, you +can use `code parigot.code-workspace` at the root of the repo. +* When you get the popup in the lower right of vscode that says "reopen in +dev container" click "Reopen in Container" or other affirmative button. +* You will be given your copy of the repo's code, plus a shell that is +pre-configured to work with parigot, as in the video above. -Where can your user find your project code? How can they install it (binaries, installable package, build from source)? Are there multiple options/versions they can install and how should they choose the right one for them? +[Screencap of VS Code startup](/vscode-scap.png) -## Setup +### Other editors -Is there any initial setup users need to do after installation to try your project? +First, VSCode is the recommended way to edit code in parigot simply because it +is so much easier. -## Try it out! +If you are wanting to use another editor that understands containers, the +Dockerfile that builds the dev container is in `.devcontainer/Dockerfile` and +should build on your local copy of Docker. From this point, you'll have a properly +set up image you can use in your editor. -Can your users test their installation, for example by running a command or deploying a Hello World example? +In the past, we have demonstrated that this method works with [goland](https://www.jetbrains.com/go/) and that one can have an environment much like the VSCode one. + +You can also build and run the container image from a terminal shell. To build the image, run: + +``` +docker build -t iansmith/parigot .devcontainer +``` + +Once you built the image, you will want to start the image by binding the `parigot` +root folder to the path `/workspaces/parigot`, and start the shell: + +``` +docker run --rm -it -v "$(pwd)":/workspaces/parigot iansmith/parigot +``` + +From there, you can run the `helloworld` example by running `make` in both the +root and `examples/helloworld`: + +``` +# In the docker container +make +cd examples/helloworld +make +runner helloworld.toml +``` diff --git a/site/content/en/docs/Reference/api/guest/_index.md b/site/content/en/docs/Reference/api/guest/_index.md index 875745ff..2f964468 100644 --- a/site/content/en/docs/Reference/api/guest/_index.md +++ b/site/content/en/docs/Reference/api/guest/_index.md @@ -1,6 +1,6 @@ --- title: Guest APIs -date: _2023-08-04 +date: _2023-09-08 description: Guest APIs are the guest side APIs (your program) of the built-in services and parigot proper. APIs listed as `syscall` are the calls to the pubilc API of parigot. weight: 5 --- @@ -36,52 +36,57 @@ import "github.com/iansmith/parigot/api/guest/syscall" ## Index -- [func BindMethod\(in \*syscall.BindMethodRequest\) \(\*syscall.BindMethodResponse, syscall.KernelErr\)](<#BindMethod>) +- [func BindMethod\(ctx context.Context, in \*syscall.BindMethodRequest\) \(\*syscall.BindMethodResponse, syscall.KernelErr\)](<#BindMethod>) - [func BindMethod\_\(int32, int32, int32, int32\) int64](<#BindMethod_>) - [func ClientSide\[T proto.Message, U proto.Message\]\(ctx context.Context, t T, u U, fn func\(int32, int32, int32, int32\) int64\) \(outU U, outId int32, signal bool\)](<#ClientSide>) -- [func CompleteCall\(ctx context.Context, cid id.CallId, result \*anypb.Any, resultErr int32\) syscall.KernelErr](<#CompleteCall>) +- [func CompleteCall\(ctx context.Context, hid id.HostId, cid id.CallId, result \*anypb.Any, resultErr int32\) syscall.KernelErr](<#CompleteCall>) - [func CurrentHostId\(\) id.HostId](<#CurrentHostId>) -- [func Dispatch\(inPtr \*syscall.DispatchRequest\) \(\*syscall.DispatchResponse, syscall.KernelErr\)](<#Dispatch>) +- [func CurrentTimezone\(\) \*time.Location](<#CurrentTimezone>) +- [func Dispatch\(ctx context.Context, inPtr \*syscall.DispatchRequest\) \(\*syscall.DispatchResponse, syscall.KernelErr\)](<#Dispatch>) - [func Dispatch\_\(int32, int32, int32, int32\) int64](<#Dispatch_>) - [func Exit\_\(int32, int32, int32, int32\) int64](<#Exit_>) -- [func ExpireMethod\(ctx context.Context\)](<#ExpireMethod>) -- [func Export\(inPtr \*syscall.ExportRequest\) \(\*syscall.ExportResponse, syscall.KernelErr\)](<#Export>) +- [func ExpireMethod\(ctx context.Context, curr time.Time\)](<#ExpireMethod>) +- [func Export\(ctx context.Context, inPtr \*syscall.ExportRequest\) \(\*syscall.ExportResponse, syscall.KernelErr\)](<#Export>) - [func Export\_\(int32, int32, int32, int32\) int64](<#Export_>) - [func Launch\_\(int32, int32, int32, int32\) int64](<#Launch_>) -- [func Locate\(inPtr \*syscall.LocateRequest\) \(\*syscall.LocateResponse, syscall.KernelErr\)](<#Locate>) +- [func Locate\(ctx context.Context, inPtr \*syscall.LocateRequest\) \(\*syscall.LocateResponse, syscall.KernelErr\)](<#Locate>) - [func Locate\_\(int32, int32, int32, int32\) int64](<#Locate_>) -- [func ManufactureGuestContext\(fn string\) context.Context](<#ManufactureGuestContext>) -- [func MatchCompleter\(cid id.CallId, comp future.Completer\)](<#MatchCompleter>) -- [func MustBindMethodName\(in \*syscall.BindMethodRequest\) id.MethodId](<#MustBindMethodName>) +- [func MatchCompleter\(ctx context.Context, t time.Time, hid id.HostId, origHost id.HostId, cid id.CallId, comp future.Completer\)](<#MatchCompleter>) +- [func MustBindMethodName\(ctx context.Context, in \*syscall.BindMethodRequest\) id.MethodId](<#MustBindMethodName>) - [func NewExitCompleter\(f \*ExitFuture\) future.Completer](<#NewExitCompleter>) - [func NewLaunchCompleter\(f \*LaunchFuture\) future.Completer](<#NewLaunchCompleter>) -- [func ReadOne\(in \*syscall.ReadOneRequest\) \(\*syscall.ReadOneResponse, syscall.KernelErr\)](<#ReadOne>) +- [func ReadOne\(ctx context.Context, in \*syscall.ReadOneRequest\) \(\*syscall.ReadOneResponse, syscall.KernelErr\)](<#ReadOne>) - [func ReadOne\_\(int32, int32, int32, int32\) int64](<#ReadOne_>) -- [func Register\(inPtr \*syscall.RegisterRequest\) \(\*syscall.RegisterResponse, syscall.KernelErr\)](<#Register>) +- [func Register\(ctx context.Context, inPtr \*syscall.RegisterRequest\) \(\*syscall.RegisterResponse, syscall.KernelErr\)](<#Register>) - [func Register\_\(int32, int32, int32, int32\) int64](<#Register_>) -- [func Require\(inPtr \*syscall.RequireRequest\) \(\*syscall.RequireResponse, syscall.KernelErr\)](<#Require>) +- [func Require\(ctx context.Context, inPtr \*syscall.RequireRequest\) \(\*syscall.RequireResponse, syscall.KernelErr\)](<#Require>) - [func Require\_\(int32, int32, int32, int32\) int64](<#Require_>) -- [func ReturnValue\(in \*syscall.ReturnValueRequest\) syscall.KernelErr](<#ReturnValue>) +- [func ReturnValue\(ctx context.Context, in \*syscall.ReturnValueRequest\) syscall.KernelErr](<#ReturnValue>) - [func ReturnValue\_\(int32, int32, int32, int32\) int64](<#ReturnValue_>) -- [func SynchronousExit\(in \*syscall.SynchronousExitRequest\) \(\*syscall.SynchronousExitResponse, syscall.KernelErr\)](<#SynchronousExit>) -- [func SynchronousExit\_\(int32, int32, int32, int32\) int64](<#SynchronousExit_>) - [type ExitCompleter](<#ExitCompleter>) - - [func \(l \*ExitCompleter\) CompleteMethod\(ctx context.Context, a proto.Message, e int32\) syscall.KernelErr](<#ExitCompleter.CompleteMethod>) + - [func \(l \*ExitCompleter\) Cancel\(\)](<#ExitCompleter.Cancel>) + - [func \(l \*ExitCompleter\) CompleteMethod\(ctx context.Context, a proto.Message, e int32, orig id.HostId\) syscall.KernelErr](<#ExitCompleter.CompleteMethod>) + - [func \(l \*ExitCompleter\) Completed\(\) bool](<#ExitCompleter.Completed>) - [func \(l \*ExitCompleter\) Failure\(failFunc func\(int32\)\)](<#ExitCompleter.Failure>) - [func \(l \*ExitCompleter\) Success\(succFunc func\(proto.Message\)\)](<#ExitCompleter.Success>) - [type ExitFuture](<#ExitFuture>) - - [func Exit\(exitReq \*syscall.ExitRequest\) \*ExitFuture](<#Exit>) + - [func Exit\(ctx context.Context, inPtr \*syscall.ExitRequest\) \*ExitFuture](<#Exit>) - [func NewExitFuture\(\) \*ExitFuture](<#NewExitFuture>) + - [func \(l \*ExitFuture\) Cancel\(\)](<#ExitFuture.Cancel>) - [func \(l \*ExitFuture\) CompleteMethod\(ctx context.Context, lr \*syscall.ExitResponse, err syscall.KernelErr\)](<#ExitFuture.CompleteMethod>) + - [func \(l \*ExitFuture\) Completed\(\) bool](<#ExitFuture.Completed>) - [func \(l \*ExitFuture\) Failure\(fn func\(syscall.KernelErr\)\)](<#ExitFuture.Failure>) - [func \(l \*ExitFuture\) Success\(fn func\(\*syscall.ExitResponse\)\)](<#ExitFuture.Success>) - [type LaunchCompleter](<#LaunchCompleter>) - - [func \(l \*LaunchCompleter\) CompleteMethod\(ctx context.Context, a proto.Message, e int32\) syscall.KernelErr](<#LaunchCompleter.CompleteMethod>) + - [func \(l \*LaunchCompleter\) Cancel\(\)](<#LaunchCompleter.Cancel>) + - [func \(l \*LaunchCompleter\) CompleteMethod\(ctx context.Context, a proto.Message, e int32, orig id.HostId\) syscall.KernelErr](<#LaunchCompleter.CompleteMethod>) + - [func \(l \*LaunchCompleter\) Completed\(\) bool](<#LaunchCompleter.Completed>) - [func \(l \*LaunchCompleter\) Failure\(failFunc func\(int32\)\)](<#LaunchCompleter.Failure>) - [func \(l \*LaunchCompleter\) Success\(succFunc func\(proto.Message\)\)](<#LaunchCompleter.Success>) - [type LaunchFuture](<#LaunchFuture>) - - [func Launch\(inPtr \*syscall.LaunchRequest\) \*LaunchFuture](<#Launch>) + - [func Launch\(ctx context.Context, inPtr \*syscall.LaunchRequest\) \*LaunchFuture](<#Launch>) - [func NewLaunchFuture\(\) \*LaunchFuture](<#NewLaunchFuture>) + - [func \(l \*LaunchFuture\) Cancel\(\)](<#LaunchFuture.Cancel>) - [func \(l \*LaunchFuture\) CompleteMethod\(ctx context.Context, lr \*syscall.LaunchResponse, err syscall.KernelErr\)](<#LaunchFuture.CompleteMethod>) - [func \(l \*LaunchFuture\) Completed\(\) bool](<#LaunchFuture.Completed>) - [func \(l \*LaunchFuture\) Failure\(fn func\(syscall.KernelErr\)\)](<#LaunchFuture.Failure>) @@ -92,7 +97,7 @@ import "github.com/iansmith/parigot/api/guest/syscall" ## func BindMethod ```go -func BindMethod(in *syscall.BindMethodRequest) (*syscall.BindMethodResponse, syscall.KernelErr) +func BindMethod(ctx context.Context, in *syscall.BindMethodRequest) (*syscall.BindMethodResponse, syscall.KernelErr) ``` @@ -121,7 +126,7 @@ ClientSide does the marshalling and unmarshalling needed to read the T given, wr ## func CompleteCall ```go -func CompleteCall(ctx context.Context, cid id.CallId, result *anypb.Any, resultErr int32) syscall.KernelErr +func CompleteCall(ctx context.Context, hid id.HostId, cid id.CallId, result *anypb.Any, resultErr int32) syscall.KernelErr ``` CompleteCall is called from the ReadOneAndCall handler to cause a prior dispatch call to be completed. The matching is done based on the cid. @@ -133,13 +138,22 @@ CompleteCall is called from the ReadOneAndCall handler to cause a prior dispatch func CurrentHostId() id.HostId ``` +CurrentHostId provides the interface to the runner's chosen host id for our WASM machine. That value is communicated through environment variables. + +## func CurrentTimezone + +```go +func CurrentTimezone() *time.Location +``` + +CurrentTimezone provides the interface to the configuration file's timezone string for our WASM machine. That value is communicated through environment variables. ## func Dispatch ```go -func Dispatch(inPtr *syscall.DispatchRequest) (*syscall.DispatchResponse, syscall.KernelErr) +func Dispatch(ctx context.Context, inPtr *syscall.DispatchRequest) (*syscall.DispatchResponse, syscall.KernelErr) ``` @@ -160,13 +174,13 @@ Dispatch is the primary means that a caller can send an RPC message. If you are func Exit_(int32, int32, int32, int32) int64 ``` -Exit is called from the WASM side to cause the WASM program, or all the WASM programs, to exit. The future the future is called when the exit is recognized, but it is not called when the actual shutdown occurs. The future given here is called when the Exit\(\) itself as has been completed. For something run just before the program stops, use AtExit. +Exit is called from the WASM side to cause the WASM program, or all the WASM programs, to exit. It does not return. ## func ExpireMethod ```go -func ExpireMethod(ctx context.Context) +func ExpireMethod(ctx context.Context, curr time.Time) ``` ExpireMethod\(\) checks the internal list of guest side futures that have no call id associated with them. These futures come about when a implementation of a server function returns a future that is not completed. This future likely exists because the implementation of the server function called another service and the result of the server function thus cannot be calculated immediately. When the call is completed, the Success or Failure functions will be called on the original future. This function exists to maintain a list so that we can expire and cancel futures that have waiting longer than the timeout time. @@ -175,7 +189,7 @@ ExpireMethod\(\) checks the internal list of guest side futures that have no cal ## func Export ```go -func Export(inPtr *syscall.ExportRequest) (*syscall.ExportResponse, syscall.KernelErr) +func Export(ctx context.Context, inPtr *syscall.ExportRequest) (*syscall.ExportResponse, syscall.KernelErr) ``` @@ -202,7 +216,7 @@ Run is starts a service \(or a guest application\) running. Note that this may n ## func Locate ```go -func Locate(inPtr *syscall.LocateRequest) (*syscall.LocateResponse, syscall.KernelErr) +func Locate(ctx context.Context, inPtr *syscall.LocateRequest) (*syscall.LocateResponse, syscall.KernelErr) ``` @@ -218,29 +232,20 @@ Locate is the means of aquiring a handle to a particular service. Most users wil func Locate\(\*syscall.LocateRequest\) \*syscall.LocateResponse - -## func ManufactureGuestContext - -```go -func ManufactureGuestContext(fn string) context.Context -``` - -Manufacture context is used to setup the context for a given state that makes sense for this, the Guest side of the wire. You pass the name of the function you are constructing this in. - ## func MatchCompleter ```go -func MatchCompleter(cid id.CallId, comp future.Completer) +func MatchCompleter(ctx context.Context, t time.Time, hid id.HostId, origHost id.HostId, cid id.CallId, comp future.Completer) ``` -MatchCompleter is a utility for adding a new cid and completer to the tables used to look up the location where response values should be sent. +MatchCompleter is a utility for adding a new cid and completer to the tables used to look up the location where response values should be sent. The time value has be passed in from the outside. ## func MustBindMethodName ```go -func MustBindMethodName(in *syscall.BindMethodRequest) id.MethodId +func MustBindMethodName(ctx context.Context, in *syscall.BindMethodRequest) id.MethodId ``` @@ -267,7 +272,7 @@ func NewLaunchCompleter(f *LaunchFuture) future.Completer ## func ReadOne ```go -func ReadOne(in *syscall.ReadOneRequest) (*syscall.ReadOneResponse, syscall.KernelErr) +func ReadOne(ctx context.Context, in *syscall.ReadOneRequest) (*syscall.ReadOneResponse, syscall.KernelErr) ``` @@ -285,7 +290,7 @@ ReadOne checks to see if any of the service/method pairs have been called. Timeo ## func Register ```go -func Register(inPtr *syscall.RegisterRequest) (*syscall.RegisterResponse, syscall.KernelErr) +func Register(ctx context.Context, inPtr *syscall.RegisterRequest) (*syscall.RegisterResponse, syscall.KernelErr) ``` @@ -303,7 +308,7 @@ Register should be called before any other services are Required, Exported, or L ## func Require ```go -func Require(inPtr *syscall.RequireRequest) (*syscall.RequireResponse, syscall.KernelErr) +func Require(ctx context.Context, inPtr *syscall.RequireRequest) (*syscall.RequireResponse, syscall.KernelErr) ``` @@ -321,7 +326,7 @@ Require is a declaration that a service needs a particular interface. This is no ## func ReturnValue ```go -func ReturnValue(in *syscall.ReturnValueRequest) syscall.KernelErr +func ReturnValue(ctx context.Context, in *syscall.ReturnValueRequest) syscall.KernelErr ``` @@ -335,40 +340,40 @@ func ReturnValue_(int32, int32, int32, int32) int64 ReturnValue is for providing return values for calls that have been made on the local service. - -## func SynchronousExit + +## type ExitCompleter -```go -func SynchronousExit(in *syscall.SynchronousExitRequest) (*syscall.SynchronousExitResponse, syscall.KernelErr) -``` +```go +type ExitCompleter struct { + // contains filtered or unexported fields +} +``` - -## func SynchronousExit\_ + +### func \(\*ExitCompleter\) Cancel ```go -func SynchronousExit_(int32, int32, int32, int32) int64 +func (l *ExitCompleter) Cancel() ``` -SynchronousExit is a request that is sent to a service to tell the service it will exit shortly \(order of milliseconds\) and resources should be cleaned up. Note that this can happen when another service actually made the Exit\(\) call. - - -## type ExitCompleter + +### func \(\*ExitCompleter\) CompleteMethod ```go -type ExitCompleter struct { - // contains filtered or unexported fields -} +func (l *ExitCompleter) CompleteMethod(ctx context.Context, a proto.Message, e int32, orig id.HostId) syscall.KernelErr ``` - -### func \(\*ExitCompleter\) CompleteMethod + + + +### func \(\*ExitCompleter\) Completed ```go -func (l *ExitCompleter) CompleteMethod(ctx context.Context, a proto.Message, e int32) syscall.KernelErr +func (l *ExitCompleter) Completed() bool ``` @@ -406,7 +411,7 @@ type ExitFuture struct { ### func Exit ```go -func Exit(exitReq *syscall.ExitRequest) *ExitFuture +func Exit(ctx context.Context, inPtr *syscall.ExitRequest) *ExitFuture ``` @@ -420,6 +425,15 @@ func NewExitFuture() *ExitFuture NewExitFuture returns an initialized exit future. It is not useful to attempt to determine if the exit has "completed" as the program would no longer exit. + +### func \(\*ExitFuture\) Cancel + +```go +func (l *ExitFuture) Cancel() +``` + + + ### func \(\*ExitFuture\) CompleteMethod @@ -429,6 +443,15 @@ func (l *ExitFuture) CompleteMethod(ctx context.Context, lr *syscall.ExitRespons CompleteMethod is used to complete a previously defined future of type ExitFuture. + +### func \(\*ExitFuture\) Completed + +```go +func (l *ExitFuture) Completed() bool +``` + + + ### func \(\*ExitFuture\) Failure @@ -458,11 +481,29 @@ type LaunchCompleter struct { } ``` + +### func \(\*LaunchCompleter\) Cancel + +```go +func (l *LaunchCompleter) Cancel() +``` + + + ### func \(\*LaunchCompleter\) CompleteMethod ```go -func (l *LaunchCompleter) CompleteMethod(ctx context.Context, a proto.Message, e int32) syscall.KernelErr +func (l *LaunchCompleter) CompleteMethod(ctx context.Context, a proto.Message, e int32, orig id.HostId) syscall.KernelErr +``` + + + + +### func \(\*LaunchCompleter\) Completed + +```go +func (l *LaunchCompleter) Completed() bool ``` @@ -500,7 +541,7 @@ type LaunchFuture struct { ### func Launch ```go -func Launch(inPtr *syscall.LaunchRequest) *LaunchFuture +func Launch(ctx context.Context, inPtr *syscall.LaunchRequest) *LaunchFuture ``` @@ -514,6 +555,15 @@ func NewLaunchFuture() *LaunchFuture + +### func \(\*LaunchFuture\) Cancel + +```go +func (l *LaunchFuture) Cancel() +``` + + + ### func \(\*LaunchFuture\) CompleteMethod @@ -558,20 +608,20 @@ import "github.com/iansmith/parigot/lib/go" ## Index -- [func ClientOnlyReadOneAndCall\(ctx context.Context, binding \*ServiceMethodMap, timeoutInMillis int32\) syscall.KernelErr](<#ClientOnlyReadOneAndCall>) -- [func ExitClient\(ctx context.Context, code int32, myId id.ServiceId, msgSuccess, msgFailure string\)](<#ExitClient>) -- [func Export1\(pkg, name string, serviceId id.ServiceId\) \(\*syscall.ExportResponse, syscall.KernelErr\)](<#Export1>) -- [func FlagParseCreateEnv\(\)](<#FlagParseCreateEnv>) -- [func Getenv\(envvar string\) string](<#Getenv>) +- [func CurrentTime\(ctx context.Context\) \(context.Context, time.Time\)](<#CurrentTime>) +- [func ExitAll\(ctx context.Context, code int32, myId id.ServiceId\) \*syscallguest.ExitFuture](<#ExitAll>) +- [func ExitSelf\(ctx context.Context, code int32, myId id.ServiceId\) \*syscallguest.ExitFuture](<#ExitSelf>) +- [func Export1\(ctx context.Context, pkg, name string, serviceId id.ServiceId\) \(\*syscall.ExportResponse, syscall.KernelErr\)](<#Export1>) - [func LaunchClient\(ctx context.Context, myId id.ServiceId\) \*syscallguest.LaunchFuture](<#LaunchClient>) -- [func LookupEnv\(envvar string\) \(string, bool\)](<#LookupEnv>) -- [func MustInitClient\(ctx context.Context, requirement \[\]MustRequireFunc\) id.ServiceId](<#MustInitClient>) -- [func MustRegisterClient\(ctx context.Context\) id.ServiceId](<#MustRegisterClient>) +- [func MustInitClient\(requirement \[\]MustRequireFunc\) \(context.Context, id.ServiceId\)](<#MustInitClient>) +- [func MustRegisterClient\(\) \(context.Context, id.ServiceId\)](<#MustRegisterClient>) - [func MustRunClient\(ctx context.Context, timeoutInMillis int32\) syscall.KernelErr](<#MustRunClient>) -- [func Require1\(pkg, name string, source id.ServiceId\) \(\*syscall.RequireResponse, syscall.KernelErr\)](<#Require1>) +- [func ReadOneAndCallClient\(ctx context.Context, binding \*ServiceMethodMap, timeoutInMillis int32\) syscall.KernelErr](<#ReadOneAndCallClient>) +- [func Require1\(ctx context.Context, pkg, name string, source id.ServiceId\) \(\*syscall.RequireResponse, syscall.KernelErr\)](<#Require1>) +- [func SetCurrentTime\(ctx context.Context, t ...time.Time\) context.Context](<#SetCurrentTime>) - [type Backgrounder](<#Backgrounder>) -- [type FuncAnyIO](<#FuncAnyIO>) - [type MustRequireFunc](<#MustRequireFunc>) +- [type ReadyChecker](<#ReadyChecker>) - [type ServiceMethodMap](<#ServiceMethodMap>) - [func NewServiceMethodMap\(\) \*ServiceMethodMap](<#NewServiceMethodMap>) - [func \(s \*ServiceMethodMap\) AddServiceMethod\(sid id.ServiceId, mid id.MethodId, serviceName, methodName string, fn future.Invoker\)](<#ServiceMethodMap.AddServiceMethod>) @@ -584,50 +634,43 @@ import "github.com/iansmith/parigot/lib/go" - [func \(s \*ServiceMethodMap\) MethodNameToId\(sid id.ServiceId, methodName string\) id.MethodId](<#ServiceMethodMap.MethodNameToId>) - -## func ClientOnlyReadOneAndCall + +## func CurrentTime ```go -func ClientOnlyReadOneAndCall(ctx context.Context, binding *ServiceMethodMap, timeoutInMillis int32) syscall.KernelErr +func CurrentTime(ctx context.Context) (context.Context, time.Time) ``` -ClientOnlyReadOneAndCall does the waiting for an incoming call and if one arrives, it dispatches the call to the appropriate method. Similarly, it will detect and respond to finished futures. It returns KernelErr\_ReadOneTimeout if the waiting timed out, otherwise the value should be KernelErr\_NoError or an appropriate error code. +CurrentTime returns the current time in the current timezone unless the current time has been set with SetCurrentTime. If that is the case, it returns the values provided to SetCurrentTime, in order. Note that the returned context.Context should be used as a replacement for the context provided as a parameter, because the state of the context changed. - -## func ExitClient +All guest code should use this call rather than time.Now\(\) or similar to provide a convenient way to test time\-dependent behavior. -```go -func ExitClient(ctx context.Context, code int32, myId id.ServiceId, msgSuccess, msgFailure string) -``` - -ExitClient sends a request to exit and attaches hanndlers that print the given strings. It only forces the exit if the Exit call itself fails. Only the values from 0 to 192 are permissable as the code; other values will be changed to 192. - - -## func Export1 + +## func ExitAll ```go -func Export1(pkg, name string, serviceId id.ServiceId) (*syscall.ExportResponse, syscall.KernelErr) +func ExitAll(ctx context.Context, code int32, myId id.ServiceId) *syscallguest.ExitFuture ``` -Export1 is a thin wrapper over syscall.Export so it's easy to export things by their name. This is used by the code generator primarily. +ExitAll sends a request to exit on all hosts and when the future is completed, it will exit. Valid code values must be in the range 0 to 192, inclusive. - -## func FlagParseCreateEnv + +## func ExitSelf ```go -func FlagParseCreateEnv() +func ExitSelf(ctx context.Context, code int32, myId id.ServiceId) *syscallguest.ExitFuture ``` +ExitSelf sends a request to exit and when the future is completed it will exit. Valid code values must be in the range 0 to 192, inclusive. If ExitSelf\(\) is called by the last running guest program then the entire process will exit. - - -## func Getenv + +## func Export1 ```go -func Getenv(envvar string) string +func Export1(ctx context.Context, pkg, name string, serviceId id.ServiceId) (*syscall.ExportResponse, syscall.KernelErr) ``` -This is a workalike for os.Getenv\(\) +Export1 is a thin wrapper over syscall.Export so it's easy to export things by their name. This is used by the code generator primarily. ## func LaunchClient @@ -638,20 +681,11 @@ func LaunchClient(ctx context.Context, myId id.ServiceId) *syscallguest.LaunchFu LaunchClient is a convienence wrapper around Launch\(\) for clients that don't want to create their own request structure. - -## func LookupEnv - -```go -func LookupEnv(envvar string) (string, bool) -``` - -This is a workalike for os.LookupEnv\(\). It can be used to differentiate an empty, but set, environment variable from the an enviroment variable that is simply not present. - ## func MustInitClient ```go -func MustInitClient(ctx context.Context, requirement []MustRequireFunc) id.ServiceId +func MustInitClient(requirement []MustRequireFunc) (context.Context, id.ServiceId) ``` MustInitClient is for clients only. In other words, you should only use this function if you do not implement services, just use them. A common case of this is a demo program or a program that performs a one off task. This function wraps MustRegisterClient and panics if things go wrong. @@ -660,7 +694,7 @@ MustInitClient is for clients only. In other words, you should only use this fun ## func MustRegisterClient ```go -func MustRegisterClient(ctx context.Context) id.ServiceId +func MustRegisterClient() (context.Context, id.ServiceId) ``` MustRegisterClient should be used by the "main" function of a client program that is not service itself, in other words it is a client only. If you are a service, you should use the automagically generated code MustRegister\\(\). @@ -674,15 +708,35 @@ func MustRunClient(ctx context.Context, timeoutInMillis int32) syscall.KernelErr + +## func ReadOneAndCallClient + +```go +func ReadOneAndCallClient(ctx context.Context, binding *ServiceMethodMap, timeoutInMillis int32) syscall.KernelErr +``` + +ReadOneAndCallClient does the waiting for an incoming call and if one arrives, it dispatches the call to the appropriate method. Similarly, it will detect and respond to finished futures. It returns KernelErr\_ReadOneTimeout if the waiting timed out, otherwise the value should be KernelErr\_NoError or an appropriate error code. + ## func Require1 ```go -func Require1(pkg, name string, source id.ServiceId) (*syscall.RequireResponse, syscall.KernelErr) +func Require1(ctx context.Context, pkg, name string, source id.ServiceId) (*syscall.RequireResponse, syscall.KernelErr) ``` Require1 is a thin wrapper over syscall.Require so it's easy to require things by their name. This is used by the code generator primarily. + +## func SetCurrentTime + +```go +func SetCurrentTime(ctx context.Context, t ...time.Time) context.Context +``` + +SetCurrentTime should only be used in tests. Calling this method \_freezes\_ time so that future calls will see a chosen time \(in t\) as the current time. Every call to CurrentTime\(\) receives the next value in the sequence provided by t. If there are more calls than values in t, the sequence is restarted from the beginning, thus providing a single value "stops time" at that point. + +The returned context.Context should be used as a replacement for the context provided as a parameter. + ## type Backgrounder @@ -694,22 +748,24 @@ type Backgrounder interface { } ``` - -## type FuncAnyIO + +## type MustRequireFunc -FuncAnyIO is the type of the guest\-side functions that implement the set and tear down of method implementations in a server. If a method fleazil is defined on a service, it will have FuncAnyIO wrapper that unmarshals input parameters and marshals the return value. +MustRequireFunc is the type of the functions that are created by the code generator from protobuf definitions of the form MustRequireXXXX\(\). These are used in the function RunXXXX\(\) to indicate required services \(dependencies\). ```go -type FuncAnyIO func(*anypb.Any) future.Method[*anypb.Any, int32] +type MustRequireFunc func(context.Context, id.ServiceId) ``` - -## type MustRequireFunc + +## type ReadyChecker + -MustRequireFunc is the type of the functions that are created by the code generator from protobuf definitions of the form MustRequireXXXX\(\). These are used in the function RunXXXX\(\) to indicate required services \(dependencies\). ```go -type MustRequireFunc func(context.Context, id.ServiceId) +type ReadyChecker interface { + Ready(ctx context.Context, sid id.ServiceId) *future.Base[bool] +} ``` @@ -775,7 +831,7 @@ Enable "turns on" a given service/method pair within the map. Thus the pair will func (s *ServiceMethodMap) Func(sid id.ServiceId, mid id.MethodId) future.Invoker ``` -Func returns the FuncAnyIO object associated with the sid and mid pair. If either sid or mid cannot be found, it returns nil. +Func returns the Invoker associated with the sid and mid pair. If either sid or mid cannot be found, it returns nil. ### func \(\*ServiceMethodMap\) Len @@ -815,7 +871,7 @@ import "github.com/iansmith/parigot/lib/go/client" - [type BaseService](<#BaseService>) - [func LocateDynamic\(ctx context.Context, protoPkg, serviceName string, calledBy id.ServiceId\) \(\*BaseService, syscall.KernelErr\)](<#LocateDynamic>) - [func NewBaseService\(ctx context.Context, id id.ServiceId, sm \*lib.ServiceMethodMap\) \*BaseService](<#NewBaseService>) - - [func \(c \*BaseService\) Dispatch\(method id.MethodId, param proto.Message\) \(id.CallId, syscall.KernelErr\)](<#BaseService.Dispatch>) + - [func \(c \*BaseService\) Dispatch\(ctx context.Context, method id.MethodId, param proto.Message\) \(id.HostId, id.CallId, syscall.KernelErr\)](<#BaseService.Dispatch>) - [func \(c \*BaseService\) MethodIdByName\(str string\) \(id.MethodId, bool\)](<#BaseService.MethodIdByName>) - [func \(c \*BaseService\) ServiceId\(\) id.ServiceId](<#BaseService.ServiceId>) - [func \(c \*BaseService\) ServiceMethodMap\(\) \*lib.ServiceMethodMap](<#BaseService.ServiceMethodMap>) @@ -855,7 +911,7 @@ NewBaseService creates. ### func \(\*BaseService\) Dispatch ```go -func (c *BaseService) Dispatch(method id.MethodId, param proto.Message) (id.CallId, syscall.KernelErr) +func (c *BaseService) Dispatch(ctx context.Context, method id.MethodId, param proto.Message) (id.HostId, id.CallId, syscall.KernelErr) ``` Dispatch is called by every client side "method" on the client side service. This funciton is the one that make a system call to the kernel and prepares for handling the result. @@ -1090,9 +1146,11 @@ Completer is the interface that means that a given type can be "completed" at a ```go type Completer interface { - CompleteMethod(ctx context.Context, msg proto.Message, resultErr int32) syscall.KernelErr + CompleteMethod(ctx context.Context, msg proto.Message, resultErr int32, orig id.HostId) syscall.KernelErr Success(func(proto.Message)) Failure(func(int32)) + Completed() bool + Cancel() } ``` @@ -1246,12 +1304,18 @@ import "github.com/iansmith/parigot/api/shared" ## Constants -EntryPointSymbol is what should be used to start up a ready instance. Note that we are turning off the instantiation's normal call to start so that we can control the startup and its entry point. +EntryPointSymbol is what should be used to start up a ready instance. Note that we are turning off the instantiation's normal call to start so that we can control the startup and its entry point. In principle, this could vary by go compiler, but most use this C\-originated convention. ```go const EntryPointSymbol = "_start" ``` +ExitCode is the name of a wasm symbol that holds the exit code of a process. + +```go +const ExitCode = "exit_code_" +``` + ExpectedStackDumpSize is used to allocate space so that stack trace can be placed in it, then read back line by line. ```go @@ -1296,10 +1360,16 @@ const WasmPageSize = 4096 var ControlledExit = "controlled exit via panic:" ``` -all calls to exit use the same Id +this is really a "phantom" serivce, used only for exiting + +```go +var ExitMethod = id.MethodId(id.NewIdTyped[id.DefMethod](^uint64(0), 0xfffffffffffffff2)) +``` + +this is really a "phantom" serivce, used only for exiting ```go -var ExitMethod = id.MethodId(id.NewIdTyped[id.DefMethod](^uint64(0), 0xfffffffffffffff1)) +var ExitService = id.ServiceId(id.NewIdTyped[id.DefService](^uint64(0), 0xfffffffffffffff1)) ``` The amount of time we will wait for a function call to be completed. diff --git a/site/content/en/docs/Reference/api/plugin/_index.md b/site/content/en/docs/Reference/api/plugin/_index.md index aaa7409e..781562a8 100644 --- a/site/content/en/docs/Reference/api/plugin/_index.md +++ b/site/content/en/docs/Reference/api/plugin/_index.md @@ -1,6 +1,6 @@ --- title: Plugin APIs -date: _2023-08-04 +date: _2023-09-08 description: Plugins are used to build parigot services that are "outside" the WASM sandbox. These services use code running inside the __host__ to do their work. The documentation in this section is documentation about the implementation of some plugins used by built-in services. These can serve as examples of how to build your own. @@ -17,7 +17,6 @@ import "github.com/iansmith/parigot/api/plugin" - [Variables](<#variables>) - [func InvokeImplFromStack\[T proto.Message, U proto.Message\]\(ctx context.Context, name string, m api.Module, stack \[\]uint64, fn func\(context.Context, T, U\) int32, t T, u U\)](<#InvokeImplFromStack>) -- [func ManufactureHostContext\(ctx context.Context, funcName string\) context.Context](<#ManufactureHostContext>) - [type ParigotInit](<#ParigotInit>) - [func LoadAndReturnInit\(ctx context.Context, pluginPath, pluginSymbol, \_ string\) \(ParigotInit, error\)](<#LoadAndReturnInit>) @@ -39,15 +38,6 @@ func InvokeImplFromStack[T proto.Message, U proto.Message](ctx context.Context, InvokeImplFromStack is the primary interface between host code and the machinery to communicate with the guest. This function takes the parameters like an api.Module and a section of the stack provided by Wazero and then reads and writes an input and output protocol buffer to the guest memory. The name is provided here just for human error messages. This functions uses pullRequestFromStack and and pushResponseToStack to do the actual work of encoding and decoding the values to/from the guest memory. - -## func ManufactureHostContext - -```go -func ManufactureHostContext(ctx context.Context, funcName string) context.Context -``` - -ManufactureHostContext is a helper to return a context configured for the given function name and set the source to ServerGo. - ## type ParigotInit @@ -55,7 +45,7 @@ ParigotInit is the interface that plugins must meet to be initialized. It is exp ```go type ParigotInit interface { - Init(ctx context.Context, e eng.Engine) bool + Init(ctx context.Context, e eng.Engine, h id.HostId) bool } ``` @@ -77,7 +67,7 @@ import "github.com/iansmith/parigot/api/plugin/file" ## Index - [type FilePlugin](<#FilePlugin>) - - [func \(\*FilePlugin\) Init\(ctx context.Context, e eng.Engine\) bool](<#FilePlugin.Init>) + - [func \(\*FilePlugin\) Init\(ctx context.Context, e eng.Engine, \_ id.HostId\) bool](<#FilePlugin.Init>) - [type FileStatus](<#FileStatus>) - [func \(fs FileStatus\) String\(\) string](<#FileStatus.String>) @@ -95,7 +85,7 @@ type FilePlugin struct{} ### func \(\*FilePlugin\) Init ```go -func (*FilePlugin) Init(ctx context.Context, e eng.Engine) bool +func (*FilePlugin) Init(ctx context.Context, e eng.Engine, _ id.HostId) bool ``` @@ -159,7 +149,7 @@ import "github.com/iansmith/parigot/api/plugin/queue" - [func \(q \*Queries\) UpdateMessageRetrieved\(ctx context.Context, arg UpdateMessageRetrievedParams\) error](<#Queries.UpdateMessageRetrieved>) - [func \(q \*Queries\) WithTx\(tx \*sql.Tx\) \*Queries](<#Queries.WithTx>) - [type QueuePlugin](<#QueuePlugin>) - - [func \(\*QueuePlugin\) Init\(ctx context.Context, e eng.Engine\) bool](<#QueuePlugin.Init>) + - [func \(\*QueuePlugin\) Init\(ctx context.Context, e eng.Engine, \_ id.HostId\) bool](<#QueuePlugin.Init>) - [type RetrieveMessageParams](<#RetrieveMessageParams>) - [type UpdateMessageRetrievedParams](<#UpdateMessageRetrievedParams>) @@ -416,7 +406,7 @@ type QueuePlugin struct{} ### func \(\*QueuePlugin\) Init ```go -func (*QueuePlugin) Init(ctx context.Context, e eng.Engine) bool +func (*QueuePlugin) Init(ctx context.Context, e eng.Engine, _ id.HostId) bool ``` This init functions points the host functions at the functions that are the ones to a short setup before calling the real implementation. @@ -455,12 +445,8 @@ import "github.com/iansmith/parigot/api/plugin/syscall" ## Index - [Variables](<#variables>) -- [type HostFinder](<#HostFinder>) -- [type OutChannel](<#OutChannel>) -- [type Service](<#Service>) -- [type SyscallData](<#SyscallData>) - [type SyscallPlugin](<#SyscallPlugin>) - - [func \(\*SyscallPlugin\) Init\(ctx context.Context, e eng.Engine\) bool](<#SyscallPlugin.Init>) + - [func \(\*SyscallPlugin\) Init\(ctx context.Context, e eng.Engine, \_ id.HostId\) bool](<#SyscallPlugin.Init>) ## Variables @@ -471,140 +457,6 @@ import "github.com/iansmith/parigot/api/plugin/syscall" var ParigotInitialize apiplugin.ParigotInit = &SyscallPlugin{} ``` - -## type HostFinder - -HostFinder returns information about a host in the format used by the syscall struct. It is convention to use the fully qualified name of the service for the name. - -```go -type HostFinder interface { - // FindByName finds the correct host by the name field. - // If the name cannot be found, it returns nil. - FindByName(name string) *hostInfo - // FindById finds the correct host by the id field. - // If the id cannot be found it returns nil. - FindById(id id.HostId) *hostInfo - // AddHost is used to add a record to the set of hosts - // that are know. This call will panic if either the - // name or id is not set. - AddHost(name string, hid id.HostId) syscall.KernelErr -} -``` - - -## type OutChannel - - - -```go -type OutChannel struct { - // contains filtered or unexported fields -} -``` - - -## type Service - -Service is the logical representation of a service. This is used internally and is not intended for external use. - -```go -type Service interface { - Id() id.ServiceId - // Name returns a human readable name of the service. - Name() string - // Package returns the package name (not the proto package name) - // of the service. - Package() string - // Short returns a nice-to-read version of the service's id. - Short() string - // String returns the full id of the service. - String() string - // RunRequested returns true if the service has requested - // to run, but its dependencies are not yet satisfied. Once - // they are met, the service can start and the Started() - // method will return true. - RunRequested() bool - // Started returns true if the service has started. - Started() bool - // Exported returns true if some service provider has said that - // they implement this service. - Exported() bool - // Export causes this service to be marked as exported, thus - // future calls to Exported() will return true. This should - // called in response to the system call of the same name only. - // The value returned is the previous value of the exported flag, - // or false when Export() is called the first time. - Export() bool - // Method returns all the pairs of MethodName and MethodId - // for a service known to the SyscallData. You provide the - // service to this method to know which set of pairs you want. - Method() []*syscall.MethodBinding - // AddMethod is called by the syscall bind method to add a - // given name/id pair to this service. - AddMethod(string, id.MethodId) - //Run is badly named. This really means "block until everything - //I need is ready." - Run(context.Context) syscall.KernelErr - // WakeUp can be called to have this service check to see if the - // dependencies it has are met. Note that this need not be called - // from the "outside" (user code, or even syscall code) because if - // the graph has no cycles, the calls on this method due to other - // services finding their requirements have been met is sufficient. - // A call on this method does not guarantee that the service will start - // to run, only that it will _check_ to see if that is possible. - WakeUp() -} -``` - - -## type SyscallData - -SyscallData is the interface used by the kernel methods \(syscallhost.go\) to get information about the status of a startup sequence. - -```go -type SyscallData interface { - // SetService puts a service into SyscallData. This should only be - // called once for each package_ and name pair. It returns the - // ServiceId for the service named, creating a new one if necessary. - // The client flag should be set to true only when the requesting - // party is a client. All services should pass false here. This - // flag effectively means that the requester (package_,name) does not - // to export their service to be ready to run. - // If the bool result is false, then the pair already existed and - // we made no changes to it. - SetService(ctx context.Context, package_, name string, client bool) (Service, bool) - // Export finds a service by the given sid and then marks that - // service as being exported. This function returns nil if - // there is no such service. - Export(ctx context.Context, svc id.ServiceId) Service - // Import introduces a dendency between the sourge and dest - // services. Thus, dest must be running before source can run. - // This function returns a kernel error in two primary cases. - // 1. one of the src or destination could not be found. 2. The - // newly introduced edge would create a cycle. - Import(ctx context.Context, src, dest id.ServiceId) syscall.KernelErr - // Launch blocks the caller until all the prerequistes have been - // launched. It returns false if it returned because of - // a timeout or the service id cannot be found, otherwise true. - Launch(context.Context, id.ServiceId) syscall.KernelErr - // PathExists returns true if there is a sequence of dependency - // graph vertices that eventually leads from source to target. - PathExists(ctx context.Context, source, target string) bool - //ServiceByName looks up a service and returns it based on the - //values package_ and name. If this returns nil, the service could - //not be found. - ServiceByName(ctx context.Context, package_, name string) Service - //ServiceById looks up a service and returns it based on the - //value sid. If this returns nil, the service could - //not be found. - ServiceById(ctx context.Context, sid id.ServiceId) Service - //ServiceByIdString looks up a service based on the printed representation - //of the service id. If the service cannot be found ServiceByIdString - //returns nil. - ServiceByIdString(ctx context.Context, str string) Service -} -``` - ## type SyscallPlugin @@ -619,7 +471,7 @@ type SyscallPlugin struct { ### func \(\*SyscallPlugin\) Init ```go -func (*SyscallPlugin) Init(ctx context.Context, e eng.Engine) bool +func (*SyscallPlugin) Init(ctx context.Context, e eng.Engine, _ id.HostId) bool ``` diff --git a/site/content/en/docs/Reference/api/proto/_index.md b/site/content/en/docs/Reference/api/proto/_index.md index 7cba2adf..1ba59e9d 100644 --- a/site/content/en/docs/Reference/api/proto/_index.md +++ b/site/content/en/docs/Reference/api/proto/_index.md @@ -1,6 +1,6 @@ --- title: Protobuf Schema -date: _2023-08-04 +date: _2023-09-08 description: These are the protobuf definitions for [parigot itself]({{< ref "#syscall_v1_syscall-proto" >}}) and the built in services. --- @@ -54,6 +54,7 @@ description: These are the protobuf definitions for [parigot itself]({{< ref "#s - [LocateRequest](#syscall-v1-LocateRequest) - [LocateResponse](#syscall-v1-LocateResponse) - [MethodBinding](#syscall-v1-MethodBinding) + - [MethodBundle](#syscall-v1-MethodBundle) - [ReadOneRequest](#syscall-v1-ReadOneRequest) - [ReadOneResponse](#syscall-v1-ReadOneResponse) - [RegisterRequest](#syscall-v1-RegisterRequest) @@ -68,8 +69,6 @@ description: These are the protobuf definitions for [parigot itself]({{< ref "#s - [ServiceByNameRequest](#syscall-v1-ServiceByNameRequest) - [ServiceByNameResponse](#syscall-v1-ServiceByNameResponse) - [ServiceMethodCall](#syscall-v1-ServiceMethodCall) - - [SynchronousExitRequest](#syscall-v1-SynchronousExitRequest) - - [SynchronousExitResponse](#syscall-v1-SynchronousExitResponse) - [KernelErr](#syscall-v1-KernelErr) - [MethodDirection](#syscall-v1-MethodDirection) @@ -101,6 +100,8 @@ description: These are the protobuf definitions for [parigot itself]({{< ref "#s - [File-level Extensions](#protosupport_v1_protosupport-proto-extensions) - [File-level Extensions](#protosupport_v1_protosupport-proto-extensions) - [File-level Extensions](#protosupport_v1_protosupport-proto-extensions) + - [File-level Extensions](#protosupport_v1_protosupport-proto-extensions) + - [File-level Extensions](#protosupport_v1_protosupport-proto-extensions) - [queue/v1/queue.proto](#queue_v1_queue-proto) - [CreateQueueRequest](#queue-v1-CreateQueueRequest) @@ -620,11 +621,8 @@ DispatchRequest is a request by a client to invoke a particular method with the | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| service_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | | -| method_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | | +| bundle | [MethodBundle](#syscall-v1-MethodBundle) | | | | param | [google.protobuf.Any](#google-protobuf-Any) | | inside is another Request object, but we don't know its type | -| call_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | reserved for internal use | -| host_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | reserved for internal use | @@ -643,6 +641,7 @@ to map to additional info about the call. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | call_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | reserved for internal use | +| target_host_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | reserved for internal use | @@ -682,6 +681,7 @@ services running that need to be notified. | call_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | reserved for internal use | | host_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | reserved for internal use | | method_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | reserved for internal use | +| shutdown_all | [bool](#bool) | | | @@ -691,13 +691,8 @@ services running that need to be notified. ### ExitResponse -ExitResponse is needed because the exit request does -not cause the shutdown immediately. It causes the -exit machinery to be invoked at some (soonish) point -in the future. Note that due to concurrent calls to Exit() the exit -code received may not be the same as the one sent via ExitRequest! -Note that _only_ the caller of Exit() receives this response; if other -processes need to be shutdown, that is handled via SynchExit. +ExitResponse will not happen. The stack will unwind before this +message could be received. | Field | Type | Label | Description | @@ -859,6 +854,26 @@ service's "location". + + +### MethodBundle +MessageBundle tells the receiver all the necessary info to make a call +on a method. Note that when this is sent to a particular server, the HostId +is the host id of the _caller_ not the place where the service is implemented. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| host_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | | +| service_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | | +| method_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | | +| call_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | | + + + + + + ### ReadOneRequest @@ -877,7 +892,6 @@ point in the execution of the calling program. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| call | [ServiceMethodCall](#syscall-v1-ServiceMethodCall) | repeated | | | timeout_in_millis | [int32](#int32) | | | | host_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | | @@ -917,11 +931,11 @@ it may be nil. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | timeout | [bool](#bool) | | | -| call | [ServiceMethodCall](#syscall-v1-ServiceMethodCall) | | | -| call_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | | -| param | [google.protobuf.Any](#google-protobuf-Any) | | | +| bundle | [MethodBundle](#syscall-v1-MethodBundle) | | | +| param_or_result | [google.protobuf.Any](#google-protobuf-Any) | | | +| result_err | [int32](#int32) | | | | resolved | [ResolvedCall](#syscall-v1-ResolvedCall) | | | -| exit | [bool](#bool) | | | +| exit | [ExitPair](#syscall-v1-ExitPair) | | | @@ -931,15 +945,14 @@ it may be nil. ### RegisterRequest -Register informs the kernel you are one of the known services -that can be accessed. Clients use this so they can participate -in the dependency graph for startup order. +Register informs the kernel you are one of the running services +and you want a service id. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| fqs | [FullyQualifiedService](#syscall-v1-FullyQualifiedService) | | | | host_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | | +| debug_name | [string](#string) | | | @@ -955,7 +968,7 @@ the new service or not. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | | +| service_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | | | existed_previously | [bool](#bool) | | | @@ -996,13 +1009,16 @@ RequireResponse is currently empty. ### ResolvedCall ResolvedCall is used to hold the output of a service/method call while we -are waiting for the future to be resolved. +are waiting for the future to be resolved. Note that the host_id here is the +host id of the SENDER of this message, so the place that the result was +calculated. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | host_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | | | call_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | | +| method_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | | | result | [google.protobuf.Any](#google-protobuf-Any) | | | | result_error | [int32](#int32) | | | @@ -1021,8 +1037,7 @@ of a call to a service/method function. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| host_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | | -| call_id | [protosupport.v1.IdRaw](#protosupport-v1-IdRaw) | | | +| bundle | [MethodBundle](#syscall-v1-MethodBundle) | | | | result | [google.protobuf.Any](#google-protobuf-Any) | | | | result_error | [int32](#int32) | | | @@ -1122,40 +1137,6 @@ ServiceMethodCall is the structure that holds "what's been called" i - - - -### SynchronousExitRequest -SynchronousExit is sent to a program (a service) that is being told -by the parigot system to run its cleanup (AtExit) handlers because it -is going down. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| pair | [ExitPair](#syscall-v1-ExitPair) | | | - - - - - - - - -### SynchronousExitResponse -Synchronous exit response is sent to the at exit handlers for a service or -program. There is no way to stop the shutdown once this is received, it -can be used only to clean up resources that need to be released. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| pair | [ExitPair](#syscall-v1-ExitPair) | | | - - - - - @@ -1169,7 +1150,7 @@ can be used only to clean up resources that need to be released. | NoError | 0 | | | LocateError | 1 | LocateError is return when the kernel cannot find the requested service, given by a package name and service name pair. | | UnmarshalFailed | 2 | UnmarshalFailed is used to indicate that in unmarshaling a request or result, the protobuf layer returned an error. | -| IdDispatch | 3 | IdDispatch means that a dispatch call failed due to an MethodId or ServiceId was not found. | +| IdDispatch | 3 | IdDispatch means that a dispatch call failed due to an MethodId or ServiceId was not found. This is also used when binding a method if the name is invalid. | | NamespaceExhausted | 4 | NamespaceExhausted is returned when the kernel can no along accept additional packages, services, or methods. This is used primarily to thwart attempts at DOS attacks. | | NotFound | 5 | NotFound means that a package, service, or method that was requested could not be found. | | DataTooLarge | 6 | DataTooLarge means that the size of some part of method call was bigger than the buffer allocated to receive it. This could be a problem either on the call side or the return side. | @@ -1196,7 +1177,10 @@ can be used only to clean up resources that need to be released. | NotRequired | 28 | NotRequired that a service has tried to Locate() another service that that the first service did not Require() previously. | | RunTimeout | 29 | RunTimeout means that the programs timeout has expired when waiting for all the required dependencies to be fulfilled. | | ReadOneTimeout | 30 | ReadOneTimeout means that the program was trying to request a service/method pair to invoke, but the request timed out. | -| BadCallId | 31 | BadCallId is returned when trying to match up the results and the call of a function resulting in a promise. It is returned if either there is no such cid registered yet or the cid is already in use. | +| WriteTimeout | 31 | WriteTimeout means that the program was trying to send a request to another service, but timed out before it could do so. | +| BadCallId | 32 | BadCallId is returned when trying to match up the results and the call of a function resulting in a promise. It is returned if either there is no such cid registered yet or the cid is already in use. | +| ChannelClosed | 33 | ChannelClosed indicates that one of the internal channels used in waiting for input has been closed unexpectedly. is already in use. | +| ExitFailed | 34 | ExitFailed means that we were tyring to send an orderly shutdown but could not reach all the of the hosts that we needed to notify. | @@ -1566,6 +1550,8 @@ may be delivered out of order or delivered multiple times. | parigot_error | bool | .google.protobuf.EnumOptions | 543211 | | | host_func_name | string | .google.protobuf.MethodOptions | 543212 | | | error_id_name | string | .google.protobuf.ServiceOptions | 543213 | | +| implements_reverse_api | string | .google.protobuf.ServiceOptions | 543215 | | +| is_reverse_api | bool | .google.protobuf.ServiceOptions | 543214 | | diff --git a/site/content/en/docs/knowhowitworks.md b/site/content/en/docs/knowhowitworks.md index 5698f4cf..dd8c0172 100644 --- a/site/content/en/docs/knowhowitworks.md +++ b/site/content/en/docs/knowhowitworks.md @@ -1,7 +1,7 @@ +++ title= "I know how this works" description= """Quick start for folks that know about distributed systems.""" -date='2023-07-31' +date='2023-08-08' weight= 2 +++ @@ -16,34 +16,42 @@ parigot is an RPC toolkit for building microservices. By virtue of its API, it as a single process (e.g. a debugger works) or a separate processes connected by a network. #### Setup -* Start with the hello world [Makefile](https://github.com/iansmith/parigot-example/blob/master/helloworld/Makefile) -* Use `make tools` from the Makefile to download a copy of program `runner`, a copy of -the protobuf plugin `protoc-gen-parigot` and the library `syscall.so`. +* Start with the [hello world example](https://github.com/iansmith/parigot/tree/master/example/helloworld) +* Copy all the files in helloworld to a new directory under `examples`, like `examples/myprog`. #### a simple program -* Define the protocols between your services as a .proto file -* Generate code via the `make generate` approach from the Makefile. -* Define a `main()` that is your program, like [helloworld](https://github.com/iansmith/parigot-example/blob/master/helloworld/main.go). - * Use `Launch()` to start your program. It'll return a future. - * On `Success()` proceed to your program proper. - * Call methods on other services via the [generated guest code](https://github.com/iansmith/parigot-example/tree/master/helloworld/g/greeting/v1). - * You _must_ run the loop that checks for events. For clients, - [MustRunClient](https://github.com/iansmith/parigot-example/blob/ddb4801f62167aff79e9d36005b21280f2e378b2/helloworld/main.go#L55) is the usual approach. - * Use the `Exit()` and its returned future to exit. +* "program" here means a program that runs to completion. +* Define the protocols between your services as a .proto file. You can look at +[the greeting service](https://github.com/iansmith/parigot/tree/master/example/helloworld). +* The .proto should be placed in the same place as they are in helloworld, the +top level directory "proto". +* Generate code via the [make generate](https://github.com/iansmith/parigot/blob/19e3202376bb2298a389186cc6fd8ce388bfd4e2/example/helloworld/Makefile#L30) approach +from the helloworld Makefile. +* Define a `main()` that is your program, like [helloworld](https://github.com/iansmith/parigot-example/blob/master/helloworld/main.go). It is expected that this +program will use `ExitSelf()` to end at some point. +* Use `LaunchClient()` to start your program. It'll return a future. +* On `Success()` proceed to your program proper. +* Call methods on other services via the generated guest code like [this](https://github.com/iansmith/parigot/tree/master/example/helloworld/g/greeting/v1) for greeting service. +* You _must_ run the loop that checks for events. For programs that run to completion, +[MustRunClient](https://github.com/iansmith/parigot/blob/19e3202376bb2298a389186cc6fd8ce388bfd4e2/lib/go/callhelper.go#L131) is the usual approach. #### a simple service -* A simple service should probably start with [greenting/main.go](https://github.com/iansmith/parigot-example/blob/master/helloworld/greeting/main.go) -* As above, you need to launch the service and deal with the future on startup. +* A simple service should have a main that sets up the service. Here is the +example from [greenting/main.go](https://github.com/iansmith/parigot-example/blob/master/helloworld/greeting/main.go) +* As above, you need to launch the service and deal with the future on startup. Although, +the generated `Init()` function for your type is easier than doing a bunch of setup. +Here is the [generated Init](https://github.com/iansmith/parigot/blob/19e3202376bb2298a389186cc6fd8ce388bfd4e2/example/helloworld/g/greeting/v1/greetingserver.p.go#L54) from greeting service. * If you need references to other services to implement your services, do that -in the [Ready](https://github.com/iansmith/parigot-example/blob/ddb4801f62167aff79e9d36005b21280f2e378b2/helloworld/greeting/main.go#L87) method that is called just after launch. +in the [Ready](https://github.com/iansmith/parigot/blob/19e3202376bb2298a389186cc6fd8ce388bfd4e2/example/helloworld/greeting/main.go#L101) method that is called just after launch. * Use `Locate()`to find the other service. Locate is defined by the generated code of - the other service. + the other service,e.g. ServiceINeed.Locate(). * Implement the methods from the .proto. It's best to do them with the -[two parts](https://github.com/iansmith/parigot-example/blob/ddb4801f62167aff79e9d36005b21280f2e378b2/helloworld/greeting/main.go#L52) that different by a capital first letter. +two parts that differ by a capital first letter. It makes for easier unit testing. +An example is [here](https://github.com/iansmith/parigot/blob/19e3202376bb2298a389186cc6fd8ce388bfd4e2/example/helloworld/greeting/main.go#L67C1-L93C2) * Methods defined in the .proto will automatically be hooked up to the event loop. -* You can call [Run()](https://github.com/iansmith/parigot-example/blob/ddb4801f62167aff79e9d36005b21280f2e378b2/helloworld/greeting/main.go#L29) and -the implementations of your methods will be called when other services or +* You can call [Run()] that has been generated for your type. +The implementations of your methods will be called when other services or programs call them. diff --git a/site/content/en/logo.png b/site/content/en/logo.png deleted file mode 100644 index 989ee057..00000000 Binary files a/site/content/en/logo.png and /dev/null differ diff --git a/site/content/en/vscode-scap.png b/site/content/en/vscode-scap.png new file mode 100644 index 00000000..3cc5d05b Binary files /dev/null and b/site/content/en/vscode-scap.png differ