Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(docs): Event handling in JS #96

Open
wants to merge 32 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
a44d784
init mvm build docs
boneyard93501 Dec 26, 2023
b470c64
add glossary +
boneyard93501 Dec 26, 2023
06fa289
clean up
boneyard93501 Dec 26, 2023
47f0b75
update and add sections
boneyard93501 Jan 1, 2024
475b1d5
warn on borken links
boneyard93501 Jan 1, 2024
11b845c
rm comments
boneyard93501 Jan 1, 2024
df4e645
update getting started
boneyard93501 Jan 3, 2024
b97e9ef
add first lambda section
boneyard93501 Jan 3, 2024
9b4732f
update
boneyard93501 Jan 3, 2024
739f191
add curl example
boneyard93501 Jan 4, 2024
faaea76
update, fix sp
boneyard93501 Jan 4, 2024
bb2566a
init local storage section
boneyard93501 Jan 4, 2024
bcca708
update, fix sp
boneyard93501 Jan 5, 2024
ac3a8e4
change lambda to functions
boneyard93501 Jan 22, 2024
96fcbe3
update first functions
boneyard93501 Feb 4, 2024
d64b75a
add sections
boneyard93501 Feb 5, 2024
416b53d
update title
boneyard93501 Feb 5, 2024
7135029
update intro
boneyard93501 Feb 5, 2024
4b3bb05
update link
boneyard93501 Feb 5, 2024
65638b9
add info
boneyard93501 Feb 5, 2024
bbfca9f
fix functions reference
boneyard93501 Feb 5, 2024
45925e0
update sidebars, project files
boneyard93501 Feb 5, 2024
847e2de
update project indexes
boneyard93501 Feb 5, 2024
dd13848
fix file reference
boneyard93501 Feb 5, 2024
5200024
Event handling doc
akim-bow Feb 6, 2024
30c5ae0
Remove obsolete docs
akim-bow Feb 7, 2024
1b2f2d2
Drop ipfs section
akim-bow Feb 11, 2024
2026c9c
Improve and merge doc
akim-bow Feb 15, 2024
5775cbc
Update docs/build-mvm/tutorials/event-handling-in-js/4-hello-world.md
akim-bow Feb 22, 2024
b3aba37
Update docs/build-mvm/tutorials/event-handling-in-js/1-event-handling.md
akim-bow Feb 22, 2024
b0161fd
Merge remote-tracking branch 'origin/main' into event-handling-in-js
akim-bow Feb 26, 2024
f184a98
merging main
akim-bow Feb 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions docs/build-mvm/tutorials/event-handling-in-js/1-event-handling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Introduction

> Make sure you've read ***Getting Started*** and ***Quickstart*** pages.

Fluence Cloud Functions are hosted on distributed peers in the Fluence network waiting to be called. That is, your functions need to be triggered in order to do some work. Event triggers may arise from a multitude of sources ranging from browser click-events to changes in a database column. Regardless of the source, the event needs to trigger the function(s) which, as you already know from the introduction and quickstart chapters, requires Aqua to orchestrate the invocation of your distributed compute function(s).
Copy link
Collaborator

Choose a reason for hiding this comment

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

terminology is outdated and needs to be updated through out. see https://github.com/fluencelabs/docs/tree/res-32-glossary.
also, for denver all we need is the concept piece not the tutorial. there is no need and no capacity.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is too broad comment

  • Which part are you considering tutorial? Exchanging events between clients paragraph?
  • Where exactly does glossary not match?
    I would like to see more details from you.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You also have kind of events-in-js doc in main branch already and it makes me confused.

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Fluence Cloud Functions are hosted on distributed peers in the Fluence network waiting to be called. That is, your functions need to be triggered in order to do some work. Event triggers may arise from a multitude of sources ranging from browser click-events to changes in a database column. Regardless of the source, the event needs to trigger the function(s) which, as you already know from the introduction and quickstart chapters, requires Aqua to orchestrate the invocation of your distributed compute function(s).
Fluence Cloud Functions are hosted on distributed peers in the Fluence Network waiting to be called. That is, your functions need to be triggered in order to do some work. Event triggers may arise from a multitude of sources ranging from browser click-events to changes in a database column. Regardless of the source, the event needs to trigger the functions which, as you already know from the introduction and quickstart chapters, requires Aqua to orchestrate the invocation of your distributed compute functions.


One way of triggering the orchestration of your function(s) is interactively with the Fluence CLI: `fluence run -f 'your function(args)'`. However, events may require (near) real-time processing which in turn requires the orchestration of your function(s) immediately after the event occurred. Whether this is in the browser or some other application, we need to trigger the appropriate Aqua script from a (embedded) client peer.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
One way of triggering the orchestration of your function(s) is interactively with the Fluence CLI: `fluence run -f 'your function(args)'`. However, events may require (near) real-time processing which in turn requires the orchestration of your function(s) immediately after the event occurred. Whether this is in the browser or some other application, we need to trigger the appropriate Aqua script from a (embedded) client peer.
One way of triggering the orchestration of your functions is interactively with the Fluence CLI: `fluence run -f 'your function(args)'`. However, events may require near real-time processing which in turn requires the orchestration of your functions immediately after the event occurred. Whether this is in the browser or some other application, we need to trigger the appropriate Aqua script from a embedded client peer.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd recommend not to use the excessive braces like that. There's no semantic advantages in hinting at alternatives (like singular/plural), or may even mislead, but extra syntactic elements get in the way when reading.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Need to ask @boneyard93501 is there any specific meaning in these braces.


The [js-client](https://github.com/fluencelabs/js-client) provides this functionality and can be used in your frontend web app or nodejs application to provide the connection to the Fluence network via a relay peer. See Figure 1.

Figure 1: Using js-client to trigger compute function
mermaid
```mermaid
sequenceDiagram

box Application
participant A as Application
participant C as Client Peer
end

box Network
participant R as Relay
participant Pk as Peer k
end

A ->> A: event capture
A ->> C: event trigger with embedded js-client
C ->> R: Aqua script choreography dispatch
R ->> Pk: compute function invocation
```

## Interaction with deployed services

### Motivation
Imagine you've deployed your services to Fluence Network and now wondering how to interact with them, e.g., call Aqua function.

Let's forget about CLI for a minute because CLI relies on the described below event handling process.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Let's forget about CLI for a minute because CLI relies on the described below event handling process.
Let's forget about CLI for a minute, because CLI relies on the described below event handling process.


To interact with peers of Fluence network, i.e., to execute an Aqua functions, the "client" has to be a peer.
Such client peers don't have to be publicly accessible or long-running in nature, but they need to follow the protocol.

For this reason, Fluence provides thin and simple client peer for interacting with Fluence network - JS client.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
For this reason, Fluence provides thin and simple client peer for interacting with Fluence network - JS client.
For this reason, Fluence provides thin and simple JS client peer for interacting with Fluence network.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Client peer could be JS or Python or could be written in any other language

Actually, FCLI relies on JS client when interacts with Fluence Network by executing Aqua functions.
The client is dedicated to JavaScript ecosystems.
It works seamlessly in browser, Node.js and other JS environments.

It's a perfect fit for JS projects because the client is easy to install and manage.

Moreover, client have additional unique features, which extend Fluence protocol.

- Host services locally in contrast with the hosting logic remotely on peers in Fluence Network.
- Send and receive Fluence network events
- Exchange events between multiple JS clients.

### Specification

`js-client` easily embeds into any frontend or Node.js application to invoke remote compute functions. For example, your Node.js application maybe processing sensor inputs on an IoT device or scan a database for changes. See Figure 2.

Figure 2: Triggering Compute Functions with js-client
```mermaid
sequenceDiagram

participant E as Environment
participant A as nodejs app with embedded js-client
participant C as app's client peer
participant N as Fluence Network

E ->> A: new data event
A ->> C: create client peer
C ->> N: choreograph the invocation of compute function(s)
```

## Exchanging events between clients

Let's imagine that we're building a secret chat app atop Fluence Network
Chat is secret because messages aren't stored anywhere.

The Chat app consists of minimum two peers or JS clients connected to Fluence network.
Each JS client is running in the browser because that's where the app is.
JS client uses the **relay** as a proxy to Fluence network because direct connection is not always possible due to network limitation, e.g., provider allows connection to a limited set of IP addresses.
Publicly accessible relays (in contract with regular Fluence peers, which could be publicly inaccessible) allow the chat participants to communicate with each other from any location.
Fluence network acknowledged about connected peers via relays and events could be passed forth and back. More peers could be involved in this communication.

Let's check the figure 3 and review the possible interactions between two participants in the chat.

Figure 3: Secret chat interaction diagram
```mermaid
sequenceDiagram
box Alice's Application
participant A1 as Alice
participant C1 as Alice's Client Peer
end

box Network
participant R1 as Alice's Relay
participant R2 as Bob's Relay
participant Pk as Peer k
end

A1 ->> A1: event capture (Alice sends the message)
A1 ->> C1: event trigger with embedded js-client
C1 ->> R1: Aqua script choreography dispatch
R1 ->> Pk: compute function invocation
Pk ->> R2: compute function invocation
R2 ->> R2: event dispatched to Bob's JS client
```

## Examples

- Try to run `fluence init --env kras --template ts frontend`. After that you can review `./frontend/src/gateway` and `./frontend/src/gateway` folders and check their code.
- Check out more examples in the [example repo](https://github.com/fluencelabs/examples/tree/main/js-client-examples); You can find browser to browser interaction example there.

Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Extending Fluence functions (experimental)

> This section is experimental as the API is not stable and probably will change.

## Intro

As you already know, JS client allows you to process incoming event and dispatch events to execute Aqua.
Additionally, JS client provides API for creating not just JavaScript services but essentially with any programming language which support WASI compilation, e.g. rust, go.

## Use cases

Here are the reasons why you might want to write a Marine JS WASI service instead of writing a regular JavaScript service for JS client:
- A service which works both on Nox peer and JS client peer, thus you eliminate the need to copy-paste the codelogic.
- Heavy computations, CPU intensive tasks. Some languages cope with that better than high-level JavaScript.
- Would prefer to write a service in Rust or other language with compilation to WASI (at this moment only Rust is officially supported)

## What is Marine JS

When JS client starts up, it starts with initialization of Marine JS runtime.
The runtime hosts wasm services and even allows you to register your own wasm services.
For example, AquaVM service (which process event data) resides in Marine JS.
That's why Marine JS is a foundation of JS client.

## Extending JS client with Marine services

> Currently only [pure](https://fluence.dev/docs/build/glossary#pure-module) single-module services are supported.

Using Marine services is pretty straight forward. The first thing to do is to load a compiled WASM file into your environment.

### Loading module binary

Here are the examples of how to load your wasm file in browser or Node.js

**Node.js**

```javascript
import { readFile } from 'fs/promises';

const wasm = await readFile('path/to/wasm/file.wasm', 'base64');
```

**Browser**

> Need to install additional external package in browser env - `js-base64`

```javascript
import { fromUint8Array } from 'js-base64';

const wasmBinary = await fetch('https://wasm.com/url/to/wasm').then(res => res.arrayBuffer());
const wasm = fromUint8Array(new Uint8Array(greetingWasm));
```


### Registering service in JS client

JS client doesn't provide any specific interface for creating services in Marine JS.
However, the client loads wasm content through its own special service called `Srv`.
This is JS client's specific API that's why you need to add `Srv` definition in your Aqua project.

Add the following aqua file in your project near the other aqua files.

```
data ServiceCreationResult:
success: bool
service_id: ?string
error: ?string

data RemoveResult:
success: bool
error: ?string

alias ListServiceResult: []string

service Srv("single_module_srv"):
-- Used to create a service on a certain node
-- Arguments:
-- bytes – a base64 string containing the .wasm module to add.
-- Returns: service_id – the service ID of the created service.
create(wasm_b64_content: string) -> ServiceCreationResult

-- Used to remove a service from a certain node
-- Arguments:
-- service_id – ID of the service to remove
remove(service_id: string) -> RemoveResult

-- Returns a list of services ids running on a peer
list() -> ListServiceResult
```
Also, you need Aqua function which will call the service above.
Here is an example of what that function could look like in a simple form.

> In this example, wasm binary loaded as a string (see above) passed to Aqua function param.

```
service GreetingService("service-id"): -- (1)
greeting: string -> string

func hello(name: string, wasm_content: string) -> string:
created_service <- Srv.create(wasm_content) -- (2)
Greeting created_service.service_id! -- (3)
<- Greeting.greeting(name) -- (4)
```

- (1) Service definition for the passed module
- (2) Using JS client `Srv` service to register module as a service in Marine JS.
- (3) Creating service variable. It will allow you to call methods from service definition
- (4) Interacting with your single module service

Then you need to pass `wasm` variable above as a second parameter in the function.

> You can load and register as many WASM modules as you want. Remember to keep each of them in a separate service.

There is a working marine service example in [examples repo](https://github.com/fluencelabs/examples/tree/main/js-client-examples/marine-service).