suborbital / reactr Goto Github PK
View Code? Open in Web Editor NEWFunction scheduler for Go & WebAssembly
License: Apache License 2.0
Function scheduler for Go & WebAssembly
License: Apache License 2.0
The logger used by wasmInstance should be scoped before use, specifically to add the ident
so that multiple logs from the same function invocation can be grouped together easily.
Since the hive server only provides bytes as input, we need to handle a few things better:
Converting to/from bytes/string at the server/runnable border
Converting to/from bytes/string at the wasmrunner/wasmer border
Something like a "Queen Bee" that can take multiple hivew serve
or h.Serve()
servers and distribute work among them.
The Runnable API should gain the ability to access blob storage such as S3. This would allow Runnables to read and write files to/from blob storage. This should be designed to have multiple backends via an interface. Potential backends include:
Reactr should be able to run jobs on a schedule like cron jobs.
I propose a Coordinator
interface that can respond to regular requests from the scheduler asking if there are any jobs to run.
For example an "Every" coordinator, when asked once per second if there are any new jobs, would only return a new job every minute (as configured)
rt.Coordinate(rt.Every(60, func() *rt.Job { ... }))
This would allow anyone to develop their own repeating or scheduled jobs. The scheduler would run through every registered coordinator once per second and then any jobs they return get scheduled.
The scheduler could even pause these requests if the job queue was too full, giving priority to non-coordinated jobs during bursts.
Should be able to limit the job queue size when registering the job handler, and define the behavior when the queue is full, either:
nil, nil
on the Resultnil, ErrQueueFull
on the ResultWhen a Wasm module is loaded into Reactr, it should be checked for compatibility. This should be done via an FFI function that returns the version of the API it was built against.
This method will acheive two things, firstly it will "prove" that the module is a Runnable, and second it will allow Reactr to check that it is a compatible version (the method of determining compatibility will need to be explored as part of this issue)
Something like hive.Serve()
that exposes some routes:
POST /api/v1/jobs/do/{jobname}
GET /api/v1/results/{resultID}/then
GET /api/v1/results/{resultID}/status
Will need to first add Result IDs and then create a server that holds all the results that came from these requests, and the results need to have a way to get their status.
The Swift Runnable API library should be converted to use C headers for the FFI interface rather than the current method, which forces the Swift Calling Convention rather than the C Calling Convention, which the other languages use.
Once this is complete, the Reactr/Wasmer shim used to generate SCC versions of FFI functions should be removed.
When a pod is mounted with Listen
, a job returning a nil result should cause a reply message of a specific type to be sent, rather than doing nothing.
There are cases when a caller wants to know that a job returned nothing rather than waiting for the Grav timeout and guessing.
Currently Runnables accept an interface{}
as their Job payload. This causes issues with type coercion, and it simply a bad pattern for the long term.
I propose the concept of a Superfunc
which is a 'regular Go function' that returns a Result. This user defined Superfunc would return a function whose signature is understood by Reactr. Reactr would be able to execute it like any other Runnable, and would harldly know the difference. Because the function actually being executed has references to the strongly typed input parameters, this allows for a strongly typed API (that can be codegen'd!) without needing to completely overhaul Reactr.
When RunErr is converted to VKErr, it should only allow error codes that are valid HTTP codes, and set to 500 if not.
If you call run
from within a Run
with the same jobType and attempt to Then
it, that will be a deadlock unless the worker's pool is < 1. See if there are any safeties we can add for that.
Let's do run(job, Ctx)
instead of run(job, doFunc)
as this brings more flexibility.
Reactr should provide a way to DeRegister
Runnables for a given job type. This action would send cancel signals to all workThreads processing those jobs, and after all have ended (or a reasonable timeout), everything related to that job type (workThreads, worker, etc) should be unloaded, effectively removing it from memory. This should be possible to do manually or automatically (for example, it could be possible to set a 'max number of job types`.
Hive should be able to persist job data, and as a job makes its way through the system, the state should be updated.
The Job object should not contain any of the metadata related to the job, but rather only immutable pieces of data such as UUID, JobType, data, and resultData.
Getting/Setting state should not be done on the job object, and should rather be ephemeral and done with getters and setters on the storage interface.
In storage, a Job's metadata should be stored separately from its data.
Hive should be able to "reload state" from storage and re-queue jobs whose state indicate they haven't been run yet
The Swift Runnable API needs to be brought up to parity with Rust. In particular, it needs:
There are two portions to this:
bundle.Runnables
should be renamed to bundle.ModuleRefs
since it's easy to confuse with directive.Runnables
There should be a function in the load
package to load an array of WasmModuleRefs, since a full bundle is not always available.
As with the other Suborbital projects, the Reactr documentation should be migrated to GitBook.
Rather than just passing a cache
implementation to Runnables, create a set of Capabilities
that are passed into Reactr when it's instantiated, and are available to Runnables a part of Ctx
Hi, We are evaluating rwasm/reactr to use in one of our WebAssembly project. As rwasm uses wasmer-go as its wasm engine and its indirect dependency on CGO, we are interested to know its performance. Generally CGO may come with some performance penalties: https://www.cockroachlabs.com/blog/the-cost-and-complexity-of-cgo/. It would be great if you share some performance benchmarks.
Related: suborbital/hive-wasm#2
Should be able to provide a path to a bundle, and then automatically register all of the included Runnables in one line, something like h.RegisterAll({path_to_zip})
Reactr's Handle
method should be renamed as Register
, it makes a bit more sense.
Also, the helper func should be phased out en lieu of 'tasks' from #92
Runnables should have profiles
that dictate which capabilities
they're given access to (per #96).
This would allow more granular control over what Runnables are able to do.
OnChange
will take an event type like Start
or Stop
to allow the Runnable to react to changes in the worker running it.
The Runnable API should support making GraphQL requests. This would allow Runnables to make calls to GraphQL endpoints to access a variety of databases.
Access to the database should be configured when instantiating Reactr, likely via an OptionModifier.
Currently, Hive will only start a workThread upon the first job being received. There should be an option to pre-fill the pool to reduce "cold starts". This is especially needed for Wasm Runnables where startup is non-negligible.
To unleash future use cases, it would be great if fqn
are self-describing and backward-compatible by design so that they can be "universally discoverable". I'd suggest exploring the use of CIDs for this.
An interesting consequence of using CIDs is that we could use a DHT for a decentralize function discovery without a lot of effort.
Currently, a Runnable includes the OnChange
method which allows it to handle events such as adding new instances.
With the Superfunc concept, this method is no longer available, but in order for this to be viable for stateful Runnables, they need to be able to repond to these same events.
I propose that callbacks can be registered, either using traditional functions or via a Grav pod, to allow a callback to respond to these change events.
The current state of AssemblyScript support in Reactr is essentially a prototype that only implements a few of the Runnable API namespaces (log, http). The remaining namespaces should be implemented and tested to bring parity with the Rust API.
Since workThreads are preemtpible, it should now be possible to implement worker autoscaling.
Something like if jobQueue is 5x larger than worker pool size, add new workThreads
or something of that nature.
Same on the other side, if jobQueue is 3x smaller than worker pool size, terminate workThreads
(Moved from a closed PR)
Hi, may I ask you few questions. What is the effect increasing number of goroutines for a job? Is that a kind of prioritizing jobs for executing? If not how we should adjust pool size? Wouldn't it be ideal to make job have capabilities to load balance job among available threads. What happen if a job has blocked or is taking too long, does it process next available request and take care of previously passed context to timeout gorutine that is in idle state?
The progression of this project has made it evident that persisting job state is no longer something that makes sense, and as such the storage interface and the associated JobReference
that was used to facilitate it should be removed so that the project can proceed with less baggage.
The user should be able to determine how many jobs per type can be run at the same time.
If the results of a job are not of any concern, then we should have a Discard()
method as a sibling to Then()
which will read the result and do nothing, so we don't keep any memory or goroutines around.
What should happen? Can they be cleared and re-filled? Should it be an error? Locking behavior?
Should be able to pass a function and have it be executed on goroutine when a result completes.
Reactr should theoretically be able to support multiple Wasm runtime backends. Currently Wasmer is built pretty tightly into rwasm, but this should be refactored to take an object conforming to an interface, and eventually have multiple runtime options such as wasmTime, SSVM, etc.
Per #96 , the Runnable API for Wasm runnables should be re-defined as capabilites loaded into rt
at instantiation time to make them more flexible.
The Ctx object should grow a cache option - an interface that can be bound to in-memory, redis, etc.
Pretty straightforward; get, set, set with TTL, etc.
Now that a Cache interface has been established, and Runnables are able to access it, it needs a "real" backend.
Redis implementation, please!
When submitting a job to Hive FaaS, caller should be able to specify a webhook URL where the results should be sent when the job is completed.
Currently, handlers and workers are partially redundant, and the goroutines that are spawned to handle data are "raw" and will be hard to extend in the future.
Worker should absorb Handler, and the raw goroutines should be wrapped in a WorkerThread
type. This will allow signals to be sent to individual threads, thus allowing future feature such as elastic thread counts.
It appears that log::debug
is incorrectly flagging itself as info. With the following code:
impl Runnable for HelloWorld {
fn run(&self, input: Vec<u8>) -> Result<Vec<u8>, RunErr> {
let in_string = String::from_utf8(input).unwrap();
log::info("This is logged by INFO.");
log::warn("This is logged by WARN.");
log::error("This is logged by ERROR.");
log::debug("This is logged by DEBUG.");
Ok(String::from(format!("hello {}", in_string))
.as_bytes()
.to_vec())
}
}
I get the following logging:
Note the (I)
in "(I) This is logged by DEBUG."
I think it is correct to file this in reactr
because the WASM API code lives here but happy to move the issue.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.