mirror of
https://github.com/fluencelabs/gitbook-docs
synced 2024-12-04 15:20:24 +00:00
commit
0912df3a9e
62
SUMMARY.md
62
SUMMARY.md
@ -4,58 +4,20 @@
|
||||
* [Thinking In Aquamarine](p2p.md)
|
||||
* [Concepts](concepts.md)
|
||||
* [Quick Start](quick-start.md)
|
||||
* [Quick Start](quick_start/README.md)
|
||||
* [Setup](quick_start/quick_start_setup.md)
|
||||
* [Using a Service](quick_start/quick_start_using_a_service.md)
|
||||
* [Building An Application From Multiple Services](quick_start/quick_start_building_from_multiple_services.md)
|
||||
* [Adding A Storage Service](quick_start/quick_start_add_persistence/README.md)
|
||||
* [Setting Up](quick_start/quick_start_add_persistence/quick_start_persistence_setup.md)
|
||||
* [CRUD All the Way](quick_start/quick_start_add_persistence/quick_start_persistence_crud.md)
|
||||
* [What's Next](quick_start/quick_start_summary.md)
|
||||
* [Developing Modules And Services](development_development/README.md)
|
||||
* [Overview](development_development/development_overview.md)
|
||||
* [From Module To Service](development_development/developmet_build_modules.md)
|
||||
* [Building The Reward Block Application](development_development/development_reward_block_app/README.md)
|
||||
* [Ethereum Request Service](development_development/development_reward_block_app/development_eth_calls.md)
|
||||
* [SQLite Service](development_development/development_reward_block_app/development_sqlite.md)
|
||||
* [Blocks To Database](development_development/development_reward_block_app/development_persisting_blocks.md)
|
||||
* [Additional Concepts](development_development/development_reward_block_app/development_additional_concepts.md)
|
||||
* [Summary](development_development/summary.md)
|
||||
* [Knowledgebase](knowledge_knowledge/README.md)
|
||||
* [Overview](knowledge_knowledge/knowledge_overview.md)
|
||||
* [Concepts](knowledge_knowledge/knowledge_concepts.md)
|
||||
* [Tools](knowledge_knowledge/knowledge_tools.md)
|
||||
* [Aquamarine](knowledge_knowledge/knowledge_aquamarine/README.md)
|
||||
* [Aqua](knowledge_knowledge/knowledge_aquamarine/hll/README.md)
|
||||
* [Aqua VM](knowledge_knowledge/knowledge_aquamarine/hll/vm.md)
|
||||
* [AIR](knowledge_knowledge/knowledge_aquamarine/hll/knowledge_aquamarine_air.md)
|
||||
* [Marine](knowledge_knowledge/knowledge_aquamarine/marine/README.md)
|
||||
* [Marine CLI](knowledge_knowledge/knowledge_aquamarine/marine/marine-cli.md)
|
||||
* [Marine Repl](knowledge_knowledge/knowledge_aquamarine/marine/marine-repl.md)
|
||||
* [Marine Rust SDK](knowledge_knowledge/knowledge_aquamarine/marine/marine-rs-sdk.md)
|
||||
* [Node](knowledge_knowledge/node/README.md)
|
||||
* [Overview](knowledge_knowledge/node/overview.md)
|
||||
* [Services](knowledge_knowledge/node/knowledge_node_services.md)
|
||||
* [TrustGraph](knowledge_knowledge/trustgraph.md)
|
||||
* [Security](knowledge_knowledge/knowledge_security.md)
|
||||
* [Aquamarine](knowledge_aquamarine/README.md)
|
||||
* [Aqua](knowledge_aquamarine/hll.md)
|
||||
* [Marine](knowledge_aquamarine/marine/README.md)
|
||||
* [Marine CLI](knowledge_aquamarine/marine/marine-cli.md)
|
||||
* [Marine Repl](knowledge_aquamarine/marine/marine-repl.md)
|
||||
* [Marine Rust SDK](knowledge_aquamarine/marine/marine-rs-sdk.md)
|
||||
* [Tools](knowledge_tools.md)
|
||||
* [Node](node.md)
|
||||
* [Security](knowledge_security.md)
|
||||
* [Tutorials](tutorials_tutorials/README.md)
|
||||
* [Setting Up Your Environment](tutorials_tutorials/recipes_setting_up.md)
|
||||
* [Deploy A Local Fluence Node](tutorials_tutorials/tutorial_run_local_node.md)
|
||||
* [Deploy A Private Fluence Network](tutorials_tutorials/running-a-fluence-network.md)
|
||||
* [cUrl As A Service](tutorials_tutorials/curl-as-a-service.md)
|
||||
* [Add Your Own Builtins](tutorials_tutorials/add-your-own-builtin.md)
|
||||
* [TrustGraph In Action](tutorials_tutorials/tutorial_trustgraph.md)
|
||||
* [Securing Services](tutorials_tutorials/securing-services.md)
|
||||
* [Developing a Frontend Application with JS-SDK](tutorials_tutorials/developing-a-frontend-application-with-js-sdk.md)
|
||||
* [Building a Chat Appplication](tutorials_tutorials/building-a-chat-appplication.md)
|
||||
* [Building a Collaborative Editor](tutorials_tutorials/building-a-collaborative-editor.md)
|
||||
* [Recipes](recipes_recipes/README.md)
|
||||
* [Setting Up Your Environment](recipes_recipes/recipes_setting_up.md)
|
||||
* [cUrl as a Service](recipes_recipes/recipes_curl.md)
|
||||
* [Error Management and Testing Of Services](recipes_recipes/error-management-and-testing-of-services.md)
|
||||
* [Sqlite](recipes_recipes/sqlite.md)
|
||||
* [Redis](recipes_recipes/redis.md)
|
||||
* [Local Filesystem](recipes_recipes/local-filesystem.md)
|
||||
* [IPFS](recipes_recipes/ipfs.md)
|
||||
* [Data Replication](recipes_recipes/data-replication.md)
|
||||
* [Building a Frontend with JS-SDK](tutorials_tutorials/building-a-frontend-with-js-sdk.md)
|
||||
* [Research, Papers And References](research-papers-and-references.md)
|
||||
* [FAQ](faq_faq.md)
|
||||
|
||||
|
@ -124,7 +124,11 @@ The Fluence protocol offers an alternative to node selection, i.e. connection an
|
||||
[TrustGraph](https://github.com/fluencelabs/trust-graph) is currently under active development. Please check the repo for progress.
|
||||
{% endhint %}
|
||||
|
||||
## **Scaling Applications**
|
||||
# **Application**
|
||||
|
||||
An application is the "frontend" to one or more services and their execution sequence. Applications are developed by coordinating one or more services into a logical compute unit and tend to live outside the Fluence network**,** e.g., the browser as a peer-client. They can be executed in various runtime environments ranging from browsers to backend daemons.
|
||||
|
||||
### **Scaling Applications**
|
||||
|
||||
As discussed previously, decoupling at the network and business logic levels is at the core of the Fluence protocol and provides the major entry points for scaling solutions.
|
||||
|
||||
|
20
faq_faq.md
20
faq_faq.md
@ -1,20 +0,0 @@
|
||||
# FAQ
|
||||
|
||||
Coming soon. If you really need this section, contact us through any of the social media channels or Github.
|
||||
|
||||
## Setting Up The Development Environment
|
||||
|
||||
## Deploying A Node
|
||||
|
||||
## Accessing A Network
|
||||
|
||||
## Developing Modules & Services
|
||||
|
||||
## Securing Services
|
||||
|
||||
## AIR
|
||||
|
||||
## HLL
|
||||
|
||||
## TrustGraph
|
||||
|
8
knowledge_aquamarine/README.md
Normal file
8
knowledge_aquamarine/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
# Aquamarine
|
||||
|
||||
Fluence's Aquamarine stack is comprised of Aqua and Marine. Aqua is a programming language and runtime environment for peer-to-peer workflows. Marine, on the other hand, is a general purpose runtime that executes hosted code on nodes, whereas Aqua facilitates the programming of workflows composed from hosted code. In combination, Aqua and Marine enable any distributed application.
|
||||
|
||||
At the core of Aqua is the design ideal and idea to pair concurrent systems, and especially decentralized networks, with a programming and execution tool chain to avoid centralized bottlenecks commonly introduced with workflow engines and business rule engines. To this end, Aqua manages the communication and coordination between services, devices, and APIs without introducing a centralized gateway and can be used to express various distributed systems: from simple request-response models to comprehensive network consensus algorithms.
|
||||
|
||||
|
||||
|
6
knowledge_aquamarine/hll.md
Normal file
6
knowledge_aquamarine/hll.md
Normal file
@ -0,0 +1,6 @@
|
||||
# Aqua
|
||||
|
||||
At the core of Fluence is the open-source language **Aqua** that allows for the programming of peer-to-peer scenarios separately from the computations on peers.
|
||||
|
||||
Please see the[ Aqua book ](https://doc.fluence.dev/aqua-book/)for an introduction to the language and reference materials.
|
||||
|
6
knowledge_aquamarine/hll/README.md
Normal file
6
knowledge_aquamarine/hll/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# Aqua
|
||||
|
||||
## Aquamarine High Level Language
|
||||
|
||||
_**Stay Tuned -- Coming Soon To A Repo Near You**_
|
||||
|
55
knowledge_aquamarine/hll/knowledge_aquamarine_air.md
Normal file
55
knowledge_aquamarine/hll/knowledge_aquamarine_air.md
Normal file
@ -0,0 +1,55 @@
|
||||
# AIR
|
||||
|
||||
The Aquamarine Intermediate Representation \(AIR\) is a low level language to program both distributed networks and the services deployed on them. The language is comprised of a small number of instructions:
|
||||
|
||||
* _**call**_: : execution
|
||||
* _**seq**_ : sequential
|
||||
* _**par** :_ parallel
|
||||
* _**fold**_ : iteration
|
||||
* _**xor** :_ branching & error handling
|
||||
* _**null**_ : empty instruction
|
||||
|
||||
which operate on _peer-id_ \(location\), _service-id_, and _service method_ over an argument list, see Figure 1.
|
||||
|
||||
**Figure 1: AIR Instruction Definition** ![Execution](../../.gitbook/assets/air_call_execution_1.png)
|
||||
|
||||
## Instructions
|
||||
|
||||
AIR instructions are intended to launch the execution of a service method as follows:
|
||||
|
||||
1. The method is executed on the peer specified by the peer id \(location\) parameter
|
||||
2. The peer is expected to have the Wasm service specified by the service id parameter
|
||||
3. The service must have a callable method specified be the method parameter
|
||||
4. The arguments specified by the argument list are passed to the method
|
||||
5. The result of the method returned under the name output name
|
||||
|
||||
**Figure 2: Sequential Instruction** ![Execution](../../.gitbook/assets/air_sequential_2%20%281%29%20%281%29%20%281%29%20%281%29%20%281%29%20%282%29%20%283%29%20%284%29%20%284%29%20%284%29%20%281%29.png)
|
||||
|
||||
The _**seq**_ instruction takes two instructions at most as its arguments and executes them sequentially, one after the other.
|
||||
|
||||
**Figure 3: Parallel Instruction** ![Execution](../../.gitbook/assets/air_par_3.png)
|
||||
|
||||
The _**par**_ instruction takes two instructions at most as its arguments and particles may execute on parallel paths iff each service referenced is hosted on a different node otherwise particles execute sequentially
|
||||
|
||||
TODO: add better graphic showing the disticntion of branching vs seq.
|
||||
|
||||
**Figure 4: Fold Instruction** ![Execution](https://github.com/fluencelabs/gitbook-docs/tree/84e814d02d9299034c9c031adf7f081bb59898b9/.gitbook/assets/air_fold_4%20%281%29%20%282%29%20%281%29.png)
|
||||
|
||||
The _**fold**_ instruction iterates over the elements of an array and workds as follows:
|
||||
|
||||
* _**fold**_ instruction takes three arguments: an array, a variable and an instruction
|
||||
* At each iteration, the variable is assigned an element of the array and the argument-instruction is executed
|
||||
* The argument-instruction can access the variable and uses the next statement to trigger the next iteration
|
||||
|
||||
Figure 5: Branching Instruction ![Execution](../../.gitbook/assets/air_xor_5.png)
|
||||
|
||||
This instruction is intended for organizing branches in the flow of execution as well as for handling errors:
|
||||
|
||||
* The _**XOR**_ instruction takes two instructions as its arguments
|
||||
* The first instruction is executed and if the execution is successful, then the second instruction is ignored
|
||||
* If the first instruction fails, then the second one is executed.
|
||||
|
||||
**Figure 6: Null Instruction** ![Execution](https://github.com/fluencelabs/gitbook-docs/tree/84e814d02d9299034c9c031adf7f081bb59898b9/.gitbook/assets/air_null_6%20%281%29%20%282%29.png)
|
||||
|
||||
This is an empty instruction: it takes no arguments and does nothing. The _**null**_ instruction is useful for generating code.
|
||||
|
2
knowledge_aquamarine/hll/vm.md
Normal file
2
knowledge_aquamarine/hll/vm.md
Normal file
@ -0,0 +1,2 @@
|
||||
# Aqua VM
|
||||
|
14
knowledge_aquamarine/marine/README.md
Normal file
14
knowledge_aquamarine/marine/README.md
Normal file
@ -0,0 +1,14 @@
|
||||
# Marine
|
||||
|
||||
[Marine](https://github.com/fluencelabs/marine) is a general purpose WebAssembly runtime favoring Wasm modules based on the [ECS](https://en.wikipedia.org/wiki/Entity_component_system) pattern or plugin architecture and uses Wasm [Interface Types](https://github.com/WebAssembly/interface-types/blob/master/proposals/interface-types/Explainer.mdhttps://github.com/WebAssembly/interface-types/blob/master/proposals/interface-types/Explainer.md) \( IT\) to implement a [shared-nothing](https://en.wikipedia.org/wiki/Shared-nothing_architecture) linking scheme. Fluence [nodes](https://github.com/fluencelabs/fluence) use Marine to host the Aqua VM and execute hosted Wasm services.
|
||||
|
||||
The [Marine Rust SDK](https://github.com/fluencelabs/marine-rs-sdk) allows to hide the IT implementation details behind a handy procedural macro `[marine]` and provides the scaffolding for unit tests.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
35
knowledge_aquamarine/marine/marine-cli.md
Normal file
35
knowledge_aquamarine/marine/marine-cli.md
Normal file
@ -0,0 +1,35 @@
|
||||
# Marine CLI
|
||||
|
||||
The [Marine command line tool](https://github.com/fluencelabs/marine) provides the project `marine build` functionality, analogous to `cargo build`, that results in the Rust code to be compiled to _wasm32-wasi_ modules. In addition, `marine` provides utilities to inspect Wasm modules, expose Wasm module attributes or manually set module properties.
|
||||
|
||||
```rust
|
||||
mbp16~(:|✔) % marine --help
|
||||
Fluence Marine command line tool 0.6.7
|
||||
Fluence Labs
|
||||
|
||||
USAGE:
|
||||
marine [SUBCOMMAND]
|
||||
|
||||
FLAGS:
|
||||
-h, --help Prints help information
|
||||
-V, --version Prints version information
|
||||
|
||||
SUBCOMMANDS:
|
||||
aqua Shows data types of provided module in a format suitable for Aqua
|
||||
build Builds provided Rust project to Wasm
|
||||
help Prints this message or the help of the given subcommand(s)
|
||||
info Shows manifest and sdk version of the provided Wasm file
|
||||
it Shows IT of the provided Wasm file
|
||||
repl Starts Fluence application service REPL
|
||||
set Sets interface types and version to the provided Wasm file
|
||||
mbp16~(:|✔) %
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
35
knowledge_aquamarine/marine/marine-repl.md
Normal file
35
knowledge_aquamarine/marine/marine-repl.md
Normal file
@ -0,0 +1,35 @@
|
||||
# Marine Repl
|
||||
|
||||
[`mrepl`](https://crates.io/crates/mrepl) is a command line tool to locally run a Marine instance to inspect, run, and test Wasm modules and service configurations. We can run the Repl either with `mrepl` or `marine repl`
|
||||
|
||||
```text
|
||||
mbp16~(:|✔) % mrepl
|
||||
Welcome to the Marine REPL (version 0.7.2)
|
||||
Minimal supported versions
|
||||
sdk: 0.6.0
|
||||
interface-types: 0.20.0
|
||||
|
||||
New version is available! 0.7.2 -> 0.7.4
|
||||
To update run: cargo +nightly install mrepl --force
|
||||
|
||||
app service was created with service id = d81a4de5-55c3-4cb7-935c-3d5c6851320d
|
||||
elapsed time 486.234µs
|
||||
|
||||
1> help
|
||||
Commands:
|
||||
|
||||
n/new [config_path] create a new service (current will be removed)
|
||||
l/load <module_name> <module_path> load a new Wasm module
|
||||
u/unload <module_name> unload a Wasm module
|
||||
c/call <module_name> <func_name> [args] call function with given name from given module
|
||||
i/interface print public interface of all loaded modules
|
||||
e/envs <module_name> print environment variables of a module
|
||||
f/fs <module_name> print filesystem state of a module
|
||||
h/help print this message
|
||||
q/quit/Ctrl-C exit
|
||||
|
||||
2>
|
||||
```
|
||||
|
||||
|
||||
|
531
knowledge_aquamarine/marine/marine-rs-sdk.md
Normal file
531
knowledge_aquamarine/marine/marine-rs-sdk.md
Normal file
@ -0,0 +1,531 @@
|
||||
# Marine Rust SDK
|
||||
|
||||
The [marine-rs-sdk](https://github.com/fluencelabs/marine-rs-sdk) empowers developers to write services suitable for peer hosting in peer-to-peer networks using the Marine Virtual Machine by enabling the wasm32-wasi compile target for Marine. For an introduction to writing services with the marine-rs-sdk, see the [Developing Modules And Services]() section.
|
||||
|
||||
### API
|
||||
|
||||
The procedural macros `[marine]` and `[marine_test]` are the two primary features provided by the SDK. The `[marine]` macro can be applied to a function, external block or structure. The `[marine_test]` macro, on the other hand, allows the use of the familiar `cargo test` to execute tests over the actual Wasm module generated from the service code.
|
||||
|
||||
#### Function Export
|
||||
|
||||
Applying the `[marine]` macro to a function results in its export, which means that it can be called from other modules or AIR scripts. For the function to be compatible with this macro, its arguments must be of the `ftype`, which is defined as follows:
|
||||
|
||||
`ftype` = `bool`, `u8`, `u16`, `u32`, `u64`, `i8`, `i16`, `i32`, `i64`, `f32`, `f64`, `String`
|
||||
`ftype` = `ftype` \| `Vec`<`ftype`>
|
||||
`ftype` = `ftype` \| `Record`<`ftype`>
|
||||
|
||||
In other words, the arguments must be one of the types listed below:
|
||||
|
||||
* one of the following Rust basic types: `bool`, `u8`, `u16`, `u32`, `u64`, `i8`, `i16`, `i32`, `i64`, `f32`, `f64`, `String`
|
||||
* a vector of elements of the above types
|
||||
* a vector composed of vectors of the above type, where recursion is acceptable, e.g. the type `Vec<Vec<Vec<u8>>>` is permissible
|
||||
* a record, where all fields are of the basic Rust types
|
||||
* a record, where all fields are of any above types or other records
|
||||
|
||||
The return type of a function must follow the same rules, but currently only one return type is possible.
|
||||
|
||||
See the example below of an exposed function with a complex type signature and return value:
|
||||
|
||||
```rust
|
||||
// export TestRecord as a public data structure bound by
|
||||
// the IT type constraints
|
||||
#[marine]
|
||||
pub struct TestRecord {
|
||||
pub field_0: i32,
|
||||
pub field_1: Vec<Vec<u8>>,
|
||||
}
|
||||
|
||||
// export foo as a public function bound by the
|
||||
// IT type contraints
|
||||
#[marine] #
|
||||
pub fn foo(arg_1: Vec<Vec<Vec<Vec<TestRecord>>>>, arg_2: String) -> Vec<Vec<Vec<Vec<TestRecord>>>> {
|
||||
unimplemented!()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
{% hint style="info" %}
|
||||
Function Export Requirements
|
||||
|
||||
* wrap a target function with the `[marine]` macro
|
||||
* function arguments must by of `ftype`
|
||||
* the function return type also must be of `ftype`
|
||||
{% endhint %}
|
||||
|
||||
#### Function Import
|
||||
|
||||
The `[marine]` macro can also wrap an [`extern` block](https://doc.rust-lang.org/std/keyword.extern.html). In this case, all functions declared in it are considered imported functions. If there are imported functions in some module, say, module A, then:
|
||||
|
||||
* There should be another module, module B, that exports the same functions. The name of module B is indicated in the `link` macro \(see examples below\).
|
||||
* Module B should be loaded to `Marine` by the moment the loading of module A starts. Module A cannot be loaded if at least one imported function is absent in `Marine`.
|
||||
|
||||
See the examples below for wrapped `extern` block usage:
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Example 1" %}
|
||||
```rust
|
||||
#[marine]
|
||||
pub struct TestRecord {
|
||||
pub field_0: i32,
|
||||
pub field_1: Vec<Vec<u8>>,
|
||||
}
|
||||
|
||||
// wrap the extern block with the marine macro to expose the function
|
||||
// as an import to the Marine VM
|
||||
#[marine]
|
||||
#[link(wasm_import_module = "some_module")]
|
||||
extern "C" {
|
||||
pub fn foo(arg: Vec<Vec<Vec<Vec<TestRecord>>>>, arg_2: String) -> Vec<Vec<Vec<Vec<TestRecord>>>>;
|
||||
}
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Example 2" %}
|
||||
```rust
|
||||
[marine]
|
||||
#[link(wasm_import_module = "some_module")]
|
||||
extern "C" {
|
||||
pub fn foo(arg: Vec<Vec<Vec<Vec<u8>>>>) -> Vec<Vec<Vec<Vec<u8>>>>;
|
||||
}
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
|
||||
|
||||
{% hint style="info" %}
|
||||
|
||||
|
||||
#### Function import requirements
|
||||
|
||||
* wrap an extern block with the function\(s\) to be imported with the `[marine]` macro
|
||||
* all function\(s\) arguments must be of the `ftype` type
|
||||
* the return type of the function\(s\) must be `ftype`
|
||||
{% endhint %}
|
||||
|
||||
####
|
||||
|
||||
#### Structures
|
||||
|
||||
Finally, the `[marine]` macro can wrap a `struct` making possible to use it as a function argument or return type. Note that
|
||||
|
||||
* only macro-wrapped structures can be used as function arguments and return types
|
||||
* all fields of the wrapped structure must be public and of the `ftype`.
|
||||
* it is possible to have inner records in the macro-wrapped structure and to import wrapped structs from other crates
|
||||
|
||||
See the example below for wrapping `struct`:
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Example 1" %}
|
||||
```rust
|
||||
#[marine]
|
||||
pub struct TestRecord0 {
|
||||
pub field_0: i32,
|
||||
}
|
||||
|
||||
#[marine]
|
||||
pub struct TestRecord1 {
|
||||
pub field_0: i32,
|
||||
pub field_1: String,
|
||||
pub field_2: Vec<u8>,
|
||||
pub test_record_0: TestRecord0,
|
||||
}
|
||||
|
||||
#[marine]
|
||||
pub struct TestRecord2 {
|
||||
pub test_record_0: TestRecord0,
|
||||
pub test_record_1: TestRecord1,
|
||||
}
|
||||
|
||||
#[marine]
|
||||
fn foo(mut test_record: TestRecord2) -> TestRecord2 { unimplemented!(); }
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Example 2" %}
|
||||
```rust
|
||||
#[fce]
|
||||
pub struct TestRecord0 {
|
||||
pub field_0: i32,
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub struct TestRecord1 {
|
||||
pub field_0: i32,
|
||||
pub field_1: String,
|
||||
pub field_2: Vec<u8>,
|
||||
pub test_record_0: TestRecord0,
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub struct TestRecord2 {
|
||||
pub test_record_0: TestRecord0,
|
||||
pub test_record_1: TestRecord1,
|
||||
}
|
||||
|
||||
#[fce]
|
||||
#[link(wasm_import_module = "some_module")]
|
||||
extern "C" {
|
||||
fn foo(mut test_record: TestRecord2) -> TestRecord2;
|
||||
}
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Example 3" %}
|
||||
```rust
|
||||
mod data_crate {
|
||||
use fluence::marine;
|
||||
#[marine]
|
||||
pub struct Data {
|
||||
pub name: String,
|
||||
pub data: f64,
|
||||
}
|
||||
}
|
||||
|
||||
use data_crate::Data;
|
||||
use fluence::marine;
|
||||
|
||||
fn main() {}
|
||||
|
||||
#[marine]
|
||||
fn some_function() -> Data {
|
||||
Data {
|
||||
name: "example".into(),
|
||||
data: 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
|
||||
|
||||
{% hint style="info" %}
|
||||
|
||||
|
||||
> #### Structure passing requirements
|
||||
>
|
||||
> * wrap a structure with the `[marine]` macro
|
||||
> * all structure fields must be of the `ftype`
|
||||
> * the structure must be pointed to without preceding package import in a function signature, i.e`StructureName` but not `package_name::module_name::StructureName`
|
||||
> * wrapped structs can be imported from crates
|
||||
{% endhint %}
|
||||
|
||||
####
|
||||
|
||||
#### Call Parameters
|
||||
|
||||
There is a special API function `fluence::get_call_parameters()` that returns an instance of the [`CallParameters`](https://github.com/fluencelabs/marine-rs-sdk/blob/master/fluence/src/call_parameters.rs#L35) structure defined as follows:
|
||||
|
||||
```rust
|
||||
pub struct CallParameters {
|
||||
/// Peer id of the AIR script initiator.
|
||||
pub init_peer_id: String,
|
||||
|
||||
/// Id of the current service.
|
||||
pub service_id: String,
|
||||
|
||||
/// Id of the service creator.
|
||||
pub service_creator_peer_id: String,
|
||||
|
||||
/// Id of the host which run this service.
|
||||
pub host_id: String,
|
||||
|
||||
/// Id of the particle which execution resulted a call this service.
|
||||
pub particle_id: String,
|
||||
|
||||
/// Security tetraplets which described origin of the arguments.
|
||||
pub tetraplets: Vec<Vec<SecurityTetraplet>>,
|
||||
}
|
||||
```
|
||||
|
||||
CallParameters are especially useful in constructing authentication services:
|
||||
|
||||
```text
|
||||
// auth.rs
|
||||
use fluence::{marine, CallParameters};
|
||||
use::marine;
|
||||
|
||||
pub fn is_owner() -> bool {
|
||||
let meta = marine::get_call_parameters();
|
||||
let caller = meta.init_peer_id;
|
||||
let owner = meta.service_creator_peer_id;
|
||||
|
||||
caller == owner
|
||||
}
|
||||
|
||||
#[marine]
|
||||
pub fn am_i_owner() -> bool {
|
||||
is_owner()
|
||||
}
|
||||
```
|
||||
|
||||
####
|
||||
|
||||
#### MountedBinaryResult
|
||||
|
||||
Due to the inherent limitations of Wasm modules, such as a lack of sockets, it may be necessary for a module to interact with its host to bridge such gaps, e.g. use a https transport provider like _curl_. In order for a Wasm module to use a host's _curl_ capabilities, we need to provide access to the binary, which at the code level is achieved through the Rust `extern` block:
|
||||
|
||||
```rust
|
||||
// Importing a linked binary, curl, to a Wasm module
|
||||
#![allow(improper_ctypes)]
|
||||
|
||||
use fluence::marine;
|
||||
use fluence::module_manifest;
|
||||
use fluence::MountedBinaryResult;
|
||||
|
||||
module_manifest!();
|
||||
|
||||
pub fn main() {}
|
||||
|
||||
#[marine]
|
||||
pub fn curl_request(curl_cmd: Vec<String>) -> MountedBinaryResult {
|
||||
let response = curl(curl_cmd);
|
||||
response
|
||||
}
|
||||
|
||||
#[marine]
|
||||
#[link(wasm_import_module = "host")]
|
||||
extern "C" {
|
||||
fn curl(cmd: Vec<String>) -> MountedBinaryResult;
|
||||
}
|
||||
```
|
||||
|
||||
The above code creates a "curl adapter", i.e., a Wasm module that allows other Wasm modules to use the the `curl_request` function, which calls the imported _curl_ binary in this case, to make http calls. Please note that we are wrapping the `extern` block with the `[marine]`macro and introduce a Marine-native data structure [`MountedBinaryResult`](https://github.com/fluencelabs/marine/blob/master/examples/url-downloader/curl_adapter/src/main.rs) as the linked-function return value.
|
||||
|
||||
Please not that if you want to use `curl_request` with testing, see below, the curl call needs to be marked unsafe, e.g.:
|
||||
|
||||
```rust
|
||||
let response = unsafe { curl(curl_cmd) };
|
||||
```
|
||||
|
||||
since cargo does not access to the marine macro to handle unsafe.
|
||||
|
||||
MountedBinaryResult itself is a Marine-compatible struct containing a binary's return process code, error string and stdout and stderr as byte arrays:
|
||||
|
||||
```rust
|
||||
#[marine]
|
||||
#[derive(Clone, PartialEq, Default, Eq, Debug, Serialize, Deserialize)]
|
||||
pub struct MountedBinaryResult {
|
||||
/// Return process exit code or host execution error code, where SUCCESS_CODE means success.
|
||||
pub ret_code: i32,
|
||||
|
||||
/// Contains the string representation of an error, if ret_code != SUCCESS_CODE.
|
||||
pub error: String,
|
||||
|
||||
/// The data that the process wrote to stdout.
|
||||
pub stdout: Vec<u8>,
|
||||
|
||||
/// The data that the process wrote to stderr.
|
||||
pub stderr: Vec<u8>,
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
MountedBinaryResult then can be used on a variety of match or conditional tests.
|
||||
|
||||
#### Testing
|
||||
|
||||
Since we are compiling to a wasm32-wasi target with `ftype` constrains, the basic `cargo test` is not all that useful or even usable for our purposes. To alleviate that limitation, Fluence has introduced the [`[marine-test]` macro ](https://github.com/fluencelabs/marine-rs-sdk/tree/master/crates/marine-test-macro)that does a lot of the heavy lifting to allow developers to use `cargo test` as intended. That is, `[marine-test]` macro generates the necessary code to call Marine, one instance per test function, based on the Wasm module and associated configuration file so that the actual test function is run against the Wasm module not the native code.
|
||||
|
||||
Let's have a look at an implementation example:
|
||||
|
||||
```rust
|
||||
use fluence::marine;
|
||||
use fluence::module_manifest;
|
||||
|
||||
module_manifest!();
|
||||
|
||||
pub fn main() {}
|
||||
|
||||
#[marine]
|
||||
pub fn greeting(name: String) -> String { # 1
|
||||
format!("Hi, {}", name)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use fluence_test::marine_test; # 2
|
||||
|
||||
#[marine_test(config_path = "../Config.toml", modules_dir = "../artifacts")] # 3
|
||||
fn empty_string() {
|
||||
let actual = greeting.greeting(String::new()); # 4
|
||||
assert_eq!(actual, "Hi, ");
|
||||
}
|
||||
|
||||
#[marine_test(config_path = "../Config.toml", modules_dir = "../artifacts")]
|
||||
fn non_empty_string() {
|
||||
let actual = greeting.greeting("name".to_string());
|
||||
assert_eq!(actual, "Hi, name");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. We wrap a basic _greeting_ function with the `[marine`\] macro which results in the greeting.wasm module
|
||||
2. We wrap our tests as usual with `[cfg(test)]` and import the fluence_test crate._ Do **not** import _super_ or the _local crate_.
|
||||
3. Instead, we apply the `[marine_test]` to each of the test functions by providing the path to the config file, e.g., Config.toml, and the directory containing the Wasm module we obtained after compiling our project with `marine build`. It is imperative that project compilation proceeds the test runner otherwise there won't be the required Wasm file.
|
||||
4. The target of our tests is the `pub fn greeting` function. Since we are calling the function from the Wasm module we must prefix the function name with the module namespace -- `greeting` in this example case.
|
||||
|
||||
Now that we have our Wasm module and tests in place, we can proceed with `cargo test --release.` Note that using the `release`vastly improves the import speed of the necessary Wasm modules.
|
||||
|
||||
### Features
|
||||
|
||||
The SDK has two useful features: `logger` and `debug`.
|
||||
|
||||
#### Logger
|
||||
|
||||
Using logging is a simple way to assist in debugging without deploying the module\(s\) to a peer-to-peer network node. The `logger` feature allows you to use a special logger that is based at the top of the [log](https://crates.io/crates/log) crate.
|
||||
|
||||
To enable logging please specify the `logger` feature of the Fluence SDK in `Config.toml` and add the [log](https://docs.rs/log/0.4.11/log/) crate:
|
||||
|
||||
```rust
|
||||
[dependencies]
|
||||
log = "0.4.14"
|
||||
fluence = { version = "0.6.9", features = ["logger"] }
|
||||
```
|
||||
|
||||
The logger should be initialized before its usage. This can be done in the `main` function as shown in the example below.
|
||||
|
||||
```rust
|
||||
use fluence::marine;
|
||||
use fluence::WasmLogger;
|
||||
|
||||
pub fn main() {
|
||||
WasmLogger::new()
|
||||
// with_log_level can be skipped,
|
||||
// logger will be initialized with Info level in this case.
|
||||
.with_log_level(log::Level::Info)
|
||||
.build()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[marine]
|
||||
pub fn put(name: String, file_content: Vec<u8>) -> String {
|
||||
log::info!("put called with file name {}", file_name);
|
||||
unimplemented!()
|
||||
}
|
||||
```
|
||||
|
||||
In addition to the standard log creation features, the Fluence logger allows the so-called target map to be configured during the initialization step. This allows you to filter out logs by `logging_mask`, which can be set for each module in the service configuration. Let's consider an example:
|
||||
|
||||
```rust
|
||||
const TARGET_MAP: [(&str, i64); 4] = [
|
||||
("instruction", 1 << 1),
|
||||
("data_cache", 1 << 2),
|
||||
("next_peer_pks", 1 << 3),
|
||||
("subtree_complete", 1 << 4),
|
||||
];
|
||||
|
||||
pub fn main() {
|
||||
use std::collections::HashMap;
|
||||
use std::iter::FromIterator;
|
||||
|
||||
let target_map = HashMap::from_iter(TARGET_MAP.iter().cloned());
|
||||
|
||||
fluence::WasmLogger::new()
|
||||
.with_target_map(target_map)
|
||||
.build()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[marine]
|
||||
pub fn foo() {
|
||||
log::info!(target: "instruction", "this will print if (logging_mask & 1) != 0");
|
||||
log::info!(target: "data_cache", "this will print if (logging_mask & 2) != 0");
|
||||
}
|
||||
```
|
||||
|
||||
Here, an array called `TARGET_MAP` is defined and provided to a logger in the `main` function of a module. Each entry of this array contains a string \(a target\) and a number that represents the bit position in the 64-bit mask `logging_mask`. When you write a log message request `log::info!`, its target must coincide with one of the strings \(the targets\) defined in the `TARGET_MAP` array. The log will be printed if `logging_mask` for the module has the corresponding target bit set.
|
||||
|
||||
{% hint style="info" %}
|
||||
REPL also uses the log crate to print logs from Wasm modules. Log messages will be printed if`RUST_LOG` environment variable is specified.
|
||||
{% endhint %}
|
||||
|
||||
#### Debug
|
||||
|
||||
The application of the second feature is limited to obtaining some of the internal details of the IT execution. Normally, this feature should not be used by a backend developer. Here you can see example of such details for the greeting service compiled with the `debug` feature:
|
||||
|
||||
```bash
|
||||
# running the greeting service compiled with debug feature
|
||||
~ $ RUST_LOG="info" fce-repl Config.toml
|
||||
Welcome to the Fluence FaaS REPL
|
||||
app service's created with service id = e5cfa463-ff50-4996-98d8-4eced5ac5bb9
|
||||
elapsed time 40.694769ms
|
||||
|
||||
1> call greeting greeting "user"
|
||||
[greeting] sdk.allocate: 4
|
||||
[greeting] sdk.set_result_ptr: 1114240
|
||||
[greeting] sdk.set_result_size: 8
|
||||
[greeting] sdk.get_result_ptr, returns 1114240
|
||||
[greeting] sdk.get_result_size, returns 8
|
||||
[greeting] sdk.get_result_ptr, returns 1114240
|
||||
[greeting] sdk.get_result_size, returns 8
|
||||
[greeting] sdk.deallocate: 0x110080 8
|
||||
|
||||
result: String("Hi, user")
|
||||
elapsed time: 222.675µs
|
||||
```
|
||||
|
||||
The most important information these logs relates to the `allocate`/`deallocate` function calls. The `sdk.allocate: 4` line corresponds to passing the 4-byte `user` string to the Wasm module, with the memory allocated inside the module and the string is copied there. Whereas `sdk.deallocate: 0x110080 8` refers to passing the 8-byte resulting string `Hi, user` to the host side. Since all arguments and results are passed by value, `deallocate` is called to delete unnecessary memory inside the Wasm module.
|
||||
|
||||
#### Module Manifest
|
||||
|
||||
The `module_manifest!` macro embeds the Interface Type \(IT\), SDK and Rust project version as well as additional project and build information into Wasm module. For the macro to be usable, it needs to be imported and initialized in the _main.rs_ file:
|
||||
|
||||
```text
|
||||
// main.rs
|
||||
use fluence::marine;
|
||||
use fluence::module_manifest; // import manifest macro
|
||||
|
||||
module_manifest!(); // initialize macro
|
||||
|
||||
fn main() {}
|
||||
|
||||
#[marine]
|
||||
fn some_function() {}
|
||||
}
|
||||
```
|
||||
|
||||
Using the Marine CLI, we can inspect a module's manifest with `marine info`:
|
||||
|
||||
```rust
|
||||
mbp16~/localdev/struct-exp(main|…) % marine info -i artifacts/*.wasm
|
||||
it version: 0.20.1
|
||||
sdk version: 0.6.0
|
||||
authors: The Fluence Team
|
||||
version: 0.1.0
|
||||
description: foo-wasm, a Marine wasi module
|
||||
repository:
|
||||
build time: 2021-06-11 21:08:59.855352 +00:00 UTC
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,2 +0,0 @@
|
||||
# Knowledgebase
|
||||
|
@ -1,44 +0,0 @@
|
||||
# Concepts
|
||||
|
||||
Distributed, peer-to-peer networks serve a wide variety of constituents and causes but generally with the common goal of providing decentralization benefits: no single point of failure or control. Alas, the programming of and developing for peer-to-peer networks is hard. Distributed service deployment and composition are quite different from the current REST, or GraphQL, microservices model, where discovery tends to be an inherently centralized process. In distributed, peer-to-peer networks, endpoint-based service requests are discovery-based searches across peers comprising the network. The Fluence solution makes peer-to-peer development accessible and productive and empowers developers to quickly and efficiently develop, deploy, manage, and monetize distributed applications and backends.
|
||||
|
||||
At the core of the Fluence solution are Aquamarine, a new, open-source language and runtime to choreograph distributed services into robust applications, and the Fluence Compute Engine \(FCE\), an open-source Wasm runtime. These Fluence innovations combine with [libp2p](https://libp2p.io/), [Kademlia DHT](https://en.wikipedia.org/wiki/Kademlia) at the peer-to-peer network level with the portability advantages of Wasm modules to provide developers with a modern, ergonomic p2p network and development model.
|
||||
|
||||
For the purpose of mastering peer-to-peer application development and the Fluence solution, developers need to be aware of the following concepts in addition to the Fluence tools and runtimes.
|
||||
|
||||
## Module
|
||||
|
||||
Modules are logical units of code that can be used individually or in combination to create a service. In Fluence, modules are written in Rust and compiled to [Wasm IT](https://wasi.dev/) for eventual execution by the Fluence Compute Engine \(FCE\). Modules fall into three conceptual categories, which developers need to be aware of as the module type has a direct impact on service configuration:
|
||||
|
||||
* Facade Modules
|
||||
* Pure Modules
|
||||
* Effector modules
|
||||
|
||||
Facade modules expose the API of the services comprised of one or more modules. Every service has exactly one facade module.
|
||||
|
||||
Pure modules perform computations without side-effects.
|
||||
|
||||
Effector modules contain at least one computation with a side-effect, e.g., write to file or database, access eternal binaries, etc.
|
||||
|
||||
## Service
|
||||
|
||||
Services are logical compute units derived from linking of one or more Wasm modules. The linking of modules is facilitated by the Fluence Compute Engine \(FCE\) using a specially prepared configuration file. The configuration file which governs the
|
||||
|
||||
* Order of instantiation
|
||||
* Permission to resources
|
||||
* Maximum memory allocation
|
||||
|
||||
FCE uses a [shared nothing](https://en.wikipedia.org/wiki/Shared-nothing_architecture) linking scheme meaning that modules only expose functions explicitly marked to be publicly available while not sharing memory or any other resources. It should be further noted that services can **not** call on other services directly.
|
||||
|
||||
## Blueprint
|
||||
|
||||
The configuration map associating modules with service instantiations. This is a higher level construct than the low-level FCE linking described in the services section. Blueprints capture module names, blueprint name, and blueprint id. That allows the tracking and management of modules and services on a per-peer basis.
|
||||
|
||||
## Particle
|
||||
|
||||
A particle is a data structure combining data, service execution sequence, by means of an AIR script, and additional metadata. According to the AIR script specification, a particle travels through the network triggering execution at pre-defined service stops and peer nodes updating its data at every hop. Not surprisingly, the notion, implementation and processing of particles are a salient aspect of the Fluence solution.
|
||||
|
||||
## Application
|
||||
|
||||
An application in the Fluence solution is the "frontend" to one or more services and their execution sequence. Applications are developed by coordinating one or more services into a logical compute unit and tend to live outside the Fluence network. They can be executed in various runtime environments ranging from browsers to backend daemons with the help of Fluence command-line tools or the Fluence JS-SDK.
|
||||
|
@ -1,4 +0,0 @@
|
||||
# Overview
|
||||
|
||||
Developing peer-to-peer networks and applications are pretty much the only way to decentralize control and curtail censorship. In addition, public peer-to-peer networks can be designed and augmented to offer decentralized fail-over protection and network-level data replication. while proving resistant to several attacks, including Sybil and Eclipse attacks.
|
||||
|
@ -1,2 +0,0 @@
|
||||
# Node
|
||||
|
@ -1,2 +0,0 @@
|
||||
# Overview
|
||||
|
@ -1,4 +0,0 @@
|
||||
# TrustGraph
|
||||
|
||||
Coming soon. If you really need this section, contact us through any of the social media channels or Github.
|
||||
|
403
knowledge_node_services.md
Normal file
403
knowledge_node_services.md
Normal file
@ -0,0 +1,403 @@
|
||||
# Builtin Services
|
||||
|
||||
## Overview
|
||||
|
||||
Each Fluence peer is equipped with a set of "built-in" services that can be called from Aquamarine and fall into the following namespaces:
|
||||
|
||||
1. _peer_ - operations related to connectivity or state of a given peer
|
||||
2. _kad_ - Kademlia API
|
||||
3. _srv_ – management and information about services on a node
|
||||
4. _dist_ – distribution and inspection of modules and blueprints
|
||||
5. _script_ – to manage recurring scripts
|
||||
6. _op_ – basic operations on data deprecated - namespace for deprecated API Below is the reference documentation for all the existing built-in services. Please refer to the JS SDK documentation to learn how to easily use them from the JS SDK
|
||||
7. _deprecated_ - namespace for deprecated API
|
||||
|
||||
Please note that the [`fldist`](knowledge_tools.md#fluence-proto-distributor-fldist) CLI tool, as well as the [JS SDK](knowledge_tools.md#fluence-js-sdk), provide access to node-based services.
|
||||
|
||||
## API
|
||||
|
||||
### peer is\_connected
|
||||
|
||||
Checks if there is a direct connection to the peer identified by a given PeerId
|
||||
|
||||
* **Arguments**:
|
||||
* PeerId – id of the peer to check if there's a connection with
|
||||
* **Returns**: bool - true if connected to the peer, false otherwise
|
||||
|
||||
Example of a service call:
|
||||
|
||||
```scheme
|
||||
(call node ("peer" "is_connected") ["123D..."] ok)
|
||||
```
|
||||
|
||||
Initiates a connection to the specified peer
|
||||
|
||||
* **Arguments**
|
||||
* _PeerId_ – id of the target peer
|
||||
* [_Multiaddr_](https://crates.io/crates/multiaddr) – an array of target peer's addresses
|
||||
* **Returns**: bool - true if connection was successful
|
||||
|
||||
Example of a service call:
|
||||
|
||||
```scheme
|
||||
(seq
|
||||
(call node ("op" "identity") ["/ip4/1.2.3.4/tcp/7777" "/ip4/1.2.3.4/tcp/9999"] addrs)
|
||||
(call node ("peer" "connect") ["123D..." addrs] ok)
|
||||
)
|
||||
```
|
||||
|
||||
### peer get\_contact
|
||||
|
||||
Resolves the contact of a peer via [Kademlia](https://en.wikipedia.org/wiki/Kademlia)
|
||||
|
||||
* **Arguments**
|
||||
* _PeerId_ – id of the target peer
|
||||
* **Returns**: Contact - true if connection was successful
|
||||
|
||||
```rust
|
||||
// get_contact return struct
|
||||
Contact {
|
||||
peer_id: PeerId,
|
||||
addresses: [Multiaddr]
|
||||
}
|
||||
```
|
||||
|
||||
Example of a service call:
|
||||
|
||||
```scheme
|
||||
(call node ("peer" "get_contact") ["123D..."] contact)
|
||||
```
|
||||
|
||||
#### peer identify
|
||||
|
||||
Get information about the peer
|
||||
|
||||
* **Arguments**: None
|
||||
* **Returns:** _external address_
|
||||
|
||||
```javascript
|
||||
{ "external_addresses": [ "/ip4/1.2.3.4/tcp/7777", "/dns4/stage.fluence.dev/tcp/19002" ] }
|
||||
```
|
||||
|
||||
Example of service call:
|
||||
|
||||
```scheme
|
||||
(call node ("peer" "identify") [] info) peer timestamp_ms
|
||||
```
|
||||
|
||||
### peer timestamp\_ms
|
||||
|
||||
Get Unix timestamp in milliseconds
|
||||
|
||||
* **Arguments**: None
|
||||
* **Returns**: _u128_ - number of milliseconds since 1970
|
||||
|
||||
Example of service call:
|
||||
|
||||
```scheme
|
||||
(call node ("peer" "timestamp_ms") [] ts_ms)
|
||||
```
|
||||
|
||||
### peer timestamp\_sec
|
||||
|
||||
Get Unix timestamp in seconds
|
||||
|
||||
* **Arguments**: None
|
||||
* **Returns**: _u64_ - number of seconds since 1970
|
||||
|
||||
Example of service call:
|
||||
|
||||
```scheme
|
||||
(call node ("peer" "timestamp_sec") [] ts_sec)
|
||||
```
|
||||
|
||||
### kad neighborhood
|
||||
|
||||
Instructs node to return the locally-known nodes in the Kademlia neighborhood for a given key
|
||||
|
||||
* **Arguments**: _key_ – the peer ID \(PeerId\) of the node
|
||||
* **Returns**: _peers_ – an array of PeerIds of the nodes that are in the Kademlia neighborhood for the given hash\(key\)
|
||||
|
||||
Example of service call:
|
||||
|
||||
```scheme
|
||||
(call node ("dht" "neighborhood") [key] peers)
|
||||
```
|
||||
|
||||
Please note that this service does _not_ traverse the network and may yield incomplete neighborhood.
|
||||
|
||||
### srv create
|
||||
|
||||
Used to create a service on a certain node.
|
||||
|
||||
* **Arguments**:
|
||||
* blueprint\_id – ID of the blueprint that has been added to the node specified in the service call by the dist add\_blueprint service.
|
||||
* **Returns**: service\_id – the service ID of the created service.
|
||||
|
||||
Example of service call:
|
||||
|
||||
```scheme
|
||||
(call node ("srv" "create") [blueprint_id] service_id)
|
||||
```
|
||||
|
||||
### srv list
|
||||
|
||||
Used to enumerate services deployed to a peer.
|
||||
|
||||
* **Arguments**: None
|
||||
* **Returns**: a list of services running on a peer
|
||||
|
||||
Example of service call:
|
||||
|
||||
```scheme
|
||||
(call node ("srv" "list") [] services)
|
||||
```
|
||||
|
||||
### srv add\_alias
|
||||
|
||||
Adds an alias on service, so service could be called not only by service\_id but by alias.
|
||||
|
||||
* **Argument**: alias - settable service name service\_id – ID of the service whose interface you want to name.
|
||||
* **Returns**: alias id
|
||||
|
||||
Example of service call:
|
||||
|
||||
```scheme
|
||||
(call node ("srv" "add_alias") [alias service_id])
|
||||
```
|
||||
|
||||
### srv get\_interface
|
||||
|
||||
Retrieves the functional interface of a service running on the node specified in the service call.
|
||||
|
||||
* Argument: service\_id – ID of the service whose interface you want to retrieve.
|
||||
* Returns : an interface object of the following structure:
|
||||
|
||||
```typescript
|
||||
{
|
||||
interface: { function_signatures, record_types },
|
||||
blueprint_id: "uuid-1234...",
|
||||
service_id: "uuid-1234..."
|
||||
}
|
||||
```
|
||||
|
||||
Example of service call:
|
||||
|
||||
```scheme
|
||||
(call node ("srv" "get_interface") [service_id] interface)
|
||||
```
|
||||
|
||||
### dist add\_module
|
||||
|
||||
Used to add modules to the node specified in the service call.
|
||||
|
||||
* Arguments:
|
||||
|
||||
* bytes – a base64 string containing the .wasm module to add.
|
||||
* config – an object of the following structure
|
||||
|
||||
```javascript
|
||||
{
|
||||
"name": "my_module_name"
|
||||
}
|
||||
```
|
||||
|
||||
Example of service call:
|
||||
|
||||
```scheme
|
||||
(call node ("dist" "add_module") [bytes config] hash)
|
||||
```
|
||||
|
||||
### dist list\_modules
|
||||
|
||||
Get a list of modules available on the node
|
||||
|
||||
* Arguments: None
|
||||
* Returns: an array of objects containing module descriptions
|
||||
|
||||
```javascript
|
||||
[
|
||||
{
|
||||
"name": "moduleA",
|
||||
"hash": "6ebff28c",
|
||||
"config": { "name": "moduleA" }
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Example of service call:
|
||||
|
||||
```scheme
|
||||
(call node ("dist" "list_modules") [] modules)
|
||||
```
|
||||
|
||||
### dist get\_module\_interface
|
||||
|
||||
Get the interface of a module
|
||||
|
||||
* Arguments: hash of a module
|
||||
* Returns: an interface of the module \( see _srv get\_interface \)_ mple of service call:
|
||||
|
||||
```scheme
|
||||
(call node ("dist" "get_interface") [hash] interface)
|
||||
```
|
||||
|
||||
### dist add\_blueprint
|
||||
|
||||
Used to add a blueprint to the node specified in the service call.
|
||||
|
||||
* Arguments: blueprint – an object of the following structure
|
||||
|
||||
```javascript
|
||||
{
|
||||
"name": "good_service",
|
||||
"dependencies": [ "hash:6ebff28c...", "hash:1e59875a...", "hash:d164a07..." ]
|
||||
}
|
||||
```
|
||||
|
||||
```text
|
||||
Where module dependencies are specified as [_blake3_](https://crates.io/crates/blake3) hashes of modules
|
||||
```
|
||||
|
||||
* Returns: Generated blueprint id
|
||||
|
||||
Example of service call:
|
||||
|
||||
```scheme
|
||||
(call node ("dist" "add_blueprint") [blueprint] blueprint_id)
|
||||
```
|
||||
|
||||
### dist list\_blueprints
|
||||
|
||||
Used to get the blueprints available on the node specified in the service call.
|
||||
|
||||
* Arguments: None
|
||||
* Returns: an array of blueprint structures.
|
||||
|
||||
A blueprint is an object of the following structure:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"id": "uuid-1234-...",
|
||||
"name": "good_service",
|
||||
"dependencies": [ "hash:6ebff28c...", "hash:1e59875a...", "hash:d164a07..." ]
|
||||
}
|
||||
```
|
||||
|
||||
Example of service call:
|
||||
|
||||
```scheme
|
||||
(call node ("dist" "list_blueprints") [] blueprints)
|
||||
```
|
||||
|
||||
#### script add
|
||||
|
||||
Adds a given script to a node. That script will be called with a fixed interval with the default setting at approx. three \(3\) seconds.
|
||||
|
||||
Recurring scripts can't read variables from data, they must be literal. That means that every address or value must be specified as a literal: \(call "QmNode" \("service\_id-1234-uuid" "function"\) \["arg1" "arg2"\]\).
|
||||
|
||||
* Arguments:
|
||||
* _script_ – a string containing "literal" script
|
||||
* _interval_ – an optional string containing interval in seconds. If set, the script will be executed periodically at that interval. If omitted, the script will be executed only once. All intervals are rounded to 3 seconds. The minimum interval is 3 seconds.
|
||||
* Returns: uuid – script id that can be used to remove that script
|
||||
|
||||
Example of service call:
|
||||
|
||||
* Without an interval parameter value, the script executes once:
|
||||
|
||||
```text
|
||||
(call node ("script" "add") [script] id)
|
||||
```
|
||||
|
||||
* With an interval parameter value _k_ passed as a string, the script executes every _k_ seconds \(21 in this case\)
|
||||
|
||||
```scheme
|
||||
(call node ("script" "add") [script "21"] id)
|
||||
```
|
||||
|
||||
### script remove
|
||||
|
||||
Removes recurring script from a node. Only a creator of the script can delete it
|
||||
|
||||
* Arguments: _script id_ \(as received from _script add_\)
|
||||
* Returns: true if the script was deleted and false otherwise
|
||||
|
||||
Example of service call:
|
||||
|
||||
```scheme
|
||||
(call node ("script" "remove") [script_id] result)
|
||||
```
|
||||
|
||||
### script list
|
||||
|
||||
* Arguments: None
|
||||
* Returns: A list of existing scripts on the node. Each object in the list is of the following structure:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"id": "uuid-1234-...",
|
||||
"src": "(seq (call ...", //
|
||||
"failures": 0,
|
||||
"interval": "21s",
|
||||
"owner": "123DKooAbcEfgh..."
|
||||
}
|
||||
```
|
||||
|
||||
Example of a service call:
|
||||
|
||||
```scheme
|
||||
(call node ("script" "list") [] list)
|
||||
```
|
||||
|
||||
### op identity
|
||||
|
||||
Acts as an identity function. This service returns exactly what was passed to it. Useful for moving the execution of some service topologically or for extracting some data and putting it into an output variable.
|
||||
|
||||
Example of service call:
|
||||
|
||||
```scheme
|
||||
(call node ("op" "identity") [args] result)
|
||||
```
|
||||
|
||||
### deprecated add\_provider
|
||||
|
||||
Used in service aliasing. \_\*\*\_Stores the specified service provider \(provider\) in the internal storage of the node indicated in the service call and associates it with the given key \(key\). After executing add\_provider, the provider can be accessed via the get\_providers service using this key.
|
||||
|
||||
* Arguments:
|
||||
|
||||
* key – a string; usually, it is a human-readable service alias.
|
||||
* provider – the location of the service. It is an object of the following structure:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"peer": "123D...", // PeerId of some peer in the network
|
||||
"service_id": "uuid-1234-..." // Optional service_id of the service running on the peer specified by peer
|
||||
}
|
||||
```
|
||||
|
||||
Example of service call:
|
||||
|
||||
```scheme
|
||||
(call node ("deprecated" "add_provider") [key provider])
|
||||
```
|
||||
|
||||
### deprecated get\_providers
|
||||
|
||||
Used in service aliasing to retrieve providers for a given key.
|
||||
|
||||
* Arguments: _key_ – a string; usually, it is a human-readable service alias.
|
||||
* Returns: an array of objects of the following structure:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"peer": "123D...", // required field
|
||||
"service_id": "uuid-1234-..." // optional field
|
||||
}
|
||||
```
|
||||
|
||||
Example of service call:
|
||||
|
||||
```scheme
|
||||
(call node ("deprecated" "get_providers") [key] providers)
|
||||
```
|
||||
|
49
knowledge_tools.md
Normal file
49
knowledge_tools.md
Normal file
@ -0,0 +1,49 @@
|
||||
# Tools
|
||||
|
||||
### Fluence Proto Distributor: FLDIST
|
||||
|
||||
\`\`[`fldist`](https://github.com/fluencelabs/proto-distributor) is a command line interface \(CLI\) to Fluence peers allowing for the lifecycle management of services and offers the fastest and most effective way to service deployment.
|
||||
|
||||
```text
|
||||
mbp16~(:|✔) % fldist --help
|
||||
Usage: fldist <cmd> [options]
|
||||
|
||||
Commands:
|
||||
fldist completion generate completion script
|
||||
fldist upload Upload selected wasm
|
||||
fldist get_modules Print all modules on a node
|
||||
fldist get_interfaces Print all services on a node
|
||||
fldist get_interface Print a service interface
|
||||
fldist add_blueprint Add a blueprint
|
||||
fldist create_service Create a service from existing blueprint
|
||||
fldist new_service Create service from a list of modules
|
||||
fldist deploy_app Deploy application
|
||||
fldist create_keypair Generates a random keypair
|
||||
fldist run_air Send an air script from a file. Send arguments to
|
||||
"returnService" back to the client to print them in the
|
||||
console. More examples in "scripts_examples" directory.
|
||||
fldist env show nodes in currently selected environment
|
||||
|
||||
Options:
|
||||
--help Show help [boolean]
|
||||
--version Show version number [boolean]
|
||||
-s, --seed Client seed [string]
|
||||
--env Environment to use
|
||||
[required] [choices: "dev", "testnet", "local"] [default: "testnet"]
|
||||
--node-id, --node PeerId of the node to use
|
||||
--node-addr Multiaddr of the node to use
|
||||
--log log level
|
||||
[required] [choices: "trace", "debug", "info", "warn", "error"] [default:
|
||||
"error"]
|
||||
--ttl particle time to live in ms
|
||||
[number] [required] [default: 60000]
|
||||
```
|
||||
|
||||
### Fluence JS SDK
|
||||
|
||||
The Fluence [JS SDK](https://github.com/fluencelabs/fluence-js) supports developers to build full-fledged applications for a variety of targets ranging from browsers to backend apps and greatly expands on the `fldist` capabilities.
|
||||
|
||||
### Marine Tools
|
||||
|
||||
Marine offers multiple tools including the Marine CLI, REPL and SDK. Please see the [Marine section](knowledge_aquamarine/marine/) for more detail.
|
||||
|
13
node.md
Normal file
13
node.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Node
|
||||
|
||||
The Fluence protocol is implemented as the Fluence [reference node](https://github.com/fluencelabs/fluence) which includes the
|
||||
|
||||
* Peer-to-peer communication layer
|
||||
* Marine interpreter
|
||||
* Aqua VM
|
||||
* Builtin services
|
||||
|
||||
and more.
|
||||
|
||||
Builtin services are available on every Fluence peer and can be programmatically accessed and composed using Aqua. For a complete list of builtin services see the builtin.aqua file in the [Aqua Lib](https://github.com/fluencelabs/aqua-lib) repo. How to create your own builtin service, see the [Add Your Own Builtins](tutorials_tutorials/add-your-own-builtin.md) tutorial.
|
||||
|
11
node/README.md
Normal file
11
node/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Node
|
||||
|
||||
The Fluence protocol is implemented as the Fluence [reference node](https://github.com/fluencelabs/fluence) which includes the
|
||||
|
||||
* Peer-to-peer communication layer
|
||||
* Marine interpreter
|
||||
* Aqua VM
|
||||
* Builtin services
|
||||
|
||||
and more.
|
||||
|
@ -1,8 +1,8 @@
|
||||
# Services
|
||||
# Builtin Services
|
||||
|
||||
## Overview
|
||||
|
||||
Each Fluence peer is equipped with a set of "built-in" services that can be called from Aquamarine and fall into the following namespaces:
|
||||
Each Fluence node is equipped with a set of "builtin" services that can be called from Aquamarine and fall into the following namespaces:
|
||||
|
||||
1. _peer_ - operations related to connectivity or state of a given peer
|
||||
2. _kad_ - Kademlia API
|
3
p2p.md
3
p2p.md
@ -60,7 +60,8 @@ func foobar(node:string, service_id:string, func_name:string) -> string:
|
||||
<- res!
|
||||
```
|
||||
|
||||
As long as foo\(\) is running, the entire FooBar service, including bar\(\), is blocked. This has implications with respect to both service granularity and redundancy.
|
||||
As long as foo\(\) is running, the entire FooBar service, including bar\(\), is blocked. This has implications with respect to both service granularity and redundancy, where service granularity captures to number of functions per service and redundancy refers to the number of service instances deployed to different peers.
|
||||
|
||||
|
||||
## Summary
|
||||
|
||||
|
2
recipes_recipes/untitled.md
Normal file
2
recipes_recipes/untitled.md
Normal file
@ -0,0 +1,2 @@
|
||||
# Untitled
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Add Your Own Builtins
|
||||
|
||||
As discussed in the [Node](../knowledge_knowledge/node/knowledge_node_services.md) section, some service functionalities have ubiquitous demand making them suitable candidates to be directly deployed to a peer node. The [Aqua distributed hash table](https://github.com/fluencelabs/fluence/tree/master/deploy/builtins/aqua-dht) \(DHT\) is an example of builtin service. The remainder of this tutorial guides you through the steps necessary to create and deploy a Builtin service.
|
||||
As discussed in the [Node]() section, some service functionalities have ubiquitous demand making them suitable candidates to be directly deployed to a peer node. The [Aqua distributed hash table](https://github.com/fluencelabs/fluence/tree/master/deploy/builtins/aqua-dht) \(DHT\) is an example of builtin service. The remainder of this tutorial guides you through the steps necessary to create and deploy a Builtin service.
|
||||
|
||||
In order to have a service available out-of-the-box with the necessary startup and scheduling scripts, we can take advantage of the Fluence [deployer feature](https://github.com/fluencelabs/fluence/tree/master/deploy) for Node native services. This feature handles the complete deployment process including
|
||||
|
||||
@ -10,7 +10,7 @@ In order to have a service available out-of-the-box with the necessary startup a
|
||||
|
||||
Note that the deployment process is a fully automated workflow requiring you to merely submit your service assets, i.e., Wasm modules and configuration scripts, in the appropriate format as a PR to the [Fluence](https://github.com/fluencelabs/fluence) repository.
|
||||
|
||||
At this point you should have a solid grasp of creating service modules and their associated configuration files. See the [Developing Modules And Services](../development_development/) section for more details.
|
||||
At this point you should have a solid grasp of creating service modules and their associated configuration files. See the [Developing Modules And Services]() section for more details.
|
||||
|
||||
Our first step is fork the [Fluence](https://github.com/fluencelabs/fluence) repo by clicking on the Fork button, upper right of the repo webpage, and follow the instructions to create a local copy. In your local repo copy, checkout a new branch with a new, unique branch name:
|
||||
|
||||
@ -97,7 +97,7 @@ and the associated data file:
|
||||
|
||||
### **Scheduling Script**
|
||||
|
||||
Scheduling scripts allow us to decouple service execution from the client and instead can rely on a cron-like scheduler running on a node to trigger our service\(s\). For a brief overview, see [additional concepts](../development_development/development_reward_block_app/development_additional_concepts.md)
|
||||
Scheduling scripts allow us to decouple service execution from the client and instead can rely on a cron-like scheduler running on a node to trigger our service\(s\). For a brief overview, see [additional concepts]()
|
||||
|
||||
### Directory Structure
|
||||
|
||||
|
242
tutorials_tutorials/building-a-frontend-with-js-sdk.md
Normal file
242
tutorials_tutorials/building-a-frontend-with-js-sdk.md
Normal file
@ -0,0 +1,242 @@
|
||||
# Building a Frontend with JS-SDK
|
||||
|
||||
Fluence provides means to connect to the network from a javascript environment. It is currently tested to work in nodejs and modern browsers.
|
||||
|
||||
To create an application you will need two main building blocks: the JS SDK itself and the aqua compiler. Both of them are provided in a form npm packages. JS SDK wraps the air interpreter and provides a connection to the network. There is low-level api for executing air scripts and registering for service calls handlers. Aqua compiler allows to write code in aqua language and compile it into typescript code which can be directly used with the SDK.
|
||||
|
||||
Even though all the logic could be programmed by hand with raw air it is strongly recommended to use aqua.
|
||||
|
||||
### Basic usage
|
||||
|
||||
As previously said you can use Fluence with any frontend or nodejs framework. JS SDK could be as any other npm library. For the purpose of the demo we will init a bare-bones nodejs package and show you the steps needed install JS SDK and aqua compiler. Feel free to use the tool most suitable for the framework used in application, the installation process should be roughly the same
|
||||
|
||||
#### 1. Start with npm package
|
||||
|
||||
For the purpose of the demo we will use a very minimal npm package with typescript support:
|
||||
|
||||
```text
|
||||
src
|
||||
┗ index.ts (1)
|
||||
package.json (2)
|
||||
tsconfig.json
|
||||
```
|
||||
|
||||
index.ts \(1\):
|
||||
|
||||
```typescript
|
||||
async function main() {
|
||||
console.log("Hello, world!");
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
package.json \(2\):
|
||||
|
||||
```javascript
|
||||
{
|
||||
"name": "demo",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"exec": "node -r ts-node/register src/index.ts"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.2.4"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Let's test if it works:
|
||||
|
||||
```bash
|
||||
$ npm install
|
||||
$ npm run exec
|
||||
```
|
||||
|
||||
The following should be printed
|
||||
|
||||
```bash
|
||||
$ npm run exec
|
||||
|
||||
> demo@1.0.0 exec C:\work\demo
|
||||
> node -r ts-node/register src/index.ts
|
||||
|
||||
Hello, world!
|
||||
$ C:\work\demo>
|
||||
```
|
||||
|
||||
#### 2. Setting JS SDK and connecting to Fluence network
|
||||
|
||||
Install the dependencies, you will need these two packages.
|
||||
|
||||
```bash
|
||||
npm install @fluencelabs/fluence @fluencelabs/fluence-network-environment
|
||||
```
|
||||
|
||||
The first one is the SDK itself and the second is a maintained list of Fluence networks and nodes to connect to.
|
||||
|
||||
All of the communication with the Fluence network is done by using `FluenceClient`. You can create one with `createClient` function. The client encapsulates air interpreter and connects to the network through the relay. Currently any node in the network can be used a relay.
|
||||
|
||||
```typescript
|
||||
import { createClient } from "@fluencelabs/fluence";
|
||||
import { testNet } from "@fluencelabs/fluence-network-environment";
|
||||
|
||||
async function main() {
|
||||
const client = await createClient(testNet[1]);
|
||||
console.log("Is client connected: ", client.isConnected);
|
||||
|
||||
await client.disconnect();
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
Let's try it out:
|
||||
|
||||
```bash
|
||||
$ npm run exec
|
||||
|
||||
> demo@1.0.0 exec C:\work\demo
|
||||
> node -r ts-node/register src/index.ts
|
||||
|
||||
Is client connected: true
|
||||
$
|
||||
```
|
||||
|
||||
**Note**: typically you should have a single instance`FluenceClient` per application since it represents it's identity in the network. You are free to store the instance anywhere you like.
|
||||
|
||||
#### 3. Setting Up The Aqua Compiler
|
||||
|
||||
Aqua is the proffered language for the Fluence network. It can be used with javascript-based environments via npm package.
|
||||
|
||||
{% hint style="warning" %}
|
||||
**The package requires java to be installed as it calls "java -jar ... "**
|
||||
{% endhint %}
|
||||
|
||||
```bash
|
||||
npm install --save-dev @fluencelabs/aqua-cli
|
||||
```
|
||||
|
||||
We will also need the standard library for the language
|
||||
|
||||
```text
|
||||
npm install --save-dev @fluencelabs/aqua-lib
|
||||
```
|
||||
|
||||
Let's add our first aqua file:
|
||||
|
||||
```text
|
||||
aqua (1)
|
||||
┗ demo.aqua (2)
|
||||
node_modules
|
||||
src
|
||||
┣ compiled (3)
|
||||
┗ index.ts
|
||||
package-lock.json
|
||||
package.json
|
||||
tsconfig.json
|
||||
```
|
||||
|
||||
Add two directories, one for aqua sources \(1\) and another for the typescript output \(3\)
|
||||
|
||||
Create a new text file called `demo.aqua` \(2\):
|
||||
|
||||
```text
|
||||
import "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
func demo(nodePeerId: PeerId) -> []string:
|
||||
on nodePeerId:
|
||||
res <- Peer.identify()
|
||||
<- res.external_addresses
|
||||
```
|
||||
|
||||
This script will gather the list of external addresses from some node in the network. For more information about the aqua language refer to the aqua documentation.
|
||||
|
||||
The aqua code can now be compiled by using the compiler CLI. We suggest adding a script to the package.json file like so:
|
||||
|
||||
```javascript
|
||||
...
|
||||
"scripts": {
|
||||
"exec": "node -r ts-node/register src/index.ts",
|
||||
"compile-aqua": "aqua-cli -i ./aqua/ -o ./src/compiled"
|
||||
},
|
||||
...
|
||||
```
|
||||
|
||||
Run the compiler:
|
||||
|
||||
```bash
|
||||
npm run compile-aqua
|
||||
```
|
||||
|
||||
A typescript file should be generated like so:
|
||||
|
||||
```text
|
||||
aqua
|
||||
┗ demo.aqua
|
||||
node_modules
|
||||
src
|
||||
┣ compiled
|
||||
┃ ┗ demo.ts <--
|
||||
┗ index.ts
|
||||
package-lock.json
|
||||
package.json
|
||||
tsconfig.json
|
||||
```
|
||||
|
||||
#### 4. Consuming The Compiled Code
|
||||
|
||||
Using the code generated by the compiler is as easy as calling a function. The compiler generates all the boilerplate needed to send a particle into the network and wraps it into a single call. Note that all the type information and therefore type checking and code completion facilities are there!
|
||||
|
||||
Let's do it!
|
||||
|
||||
```typescript
|
||||
import { createClient } from "@fluencelabs/fluence";
|
||||
import { testNet } from "@fluencelabs/fluence-network-environment";
|
||||
|
||||
import { demo } from "./compiled/demo"; // import the generated file
|
||||
|
||||
async function main() {
|
||||
const client = await createClient(testNet[1]);
|
||||
console.log("Is client connected: ", client.isConnected);
|
||||
|
||||
const otherNode = testNet[2].peerId;
|
||||
const addresses = await demo(client, otherNode); // call it like a normal function in typescript
|
||||
console.log(`Node ${otherNode} is connected to: ${addresses}`);
|
||||
|
||||
await client.disconnect();
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
if everything is fine you have similar result:
|
||||
|
||||
```text
|
||||
$ npm run exec
|
||||
|
||||
> demo@1.0.0 exec C:\work\demo
|
||||
> node -r ts-node/register src/index.ts
|
||||
|
||||
Is client connected: true
|
||||
Node 12D3KooWHk9BjDQBUqnavciRPhAYFvqKBe4ZiPPvde7vDaqgn5er is connected to: /ip4/138.197.189.50/tcp/7001,/ip4/138.197.189.50/tcp/9001/ws
|
||||
|
||||
$
|
||||
```
|
||||
|
||||
### Advanced usage
|
||||
|
||||
Fluence JS SDK gives options to register own handlers for aqua vm service calls
|
||||
|
||||
**TBD**
|
||||
|
||||
### References
|
||||
|
||||
* For the list of compiler options see: [https://github.com/fluencelabs/aqua](https://github.com/fluencelabs/aqua)
|
||||
* Repository with additional examples: [**https://github.com/fluencelabs/aqua-playground**](https://github.com/fluencelabs/aqua-playground)\*\*\*\*
|
||||
|
105
tutorials_tutorials/curl-as-a-service.md
Normal file
105
tutorials_tutorials/curl-as-a-service.md
Normal file
@ -0,0 +1,105 @@
|
||||
# cUrl As A Service
|
||||
|
||||
### Overview
|
||||
|
||||
[Curl](https://curl.se/) is a widely available and used command-line tool to receive or send data using URL syntax. Chances are, you probably just used it when you set up your Fluence development environment. For Fluence services to be able to interact with the world, cUrl is one option to facilitate https calls. Since Fluence modules are Wasm IT modules, cUrl cannot not be a service intrinsic. Instead, the curl command-line tool needs to be made available and accessible at the node level. And for Fluence services to be able to interact with Curl, we need to code a cUrl adapter taking care of the mounted \(cUrl\) binary.
|
||||
|
||||
### Adapter Construction
|
||||
|
||||
The work for the cUrl adapter has been fundamentally done and is exposed by the Fluence Rust SDK. As a developer, the task remaining is to instantiate the adapter in the context of the module and services scope. The following code [snippet](https://github.com/fluencelabs/fce/tree/master/examples/url-downloader/curl_adapter) illustrates the implementation requirement.
|
||||
|
||||
```rust
|
||||
use fluence::fce;
|
||||
|
||||
use fluence::WasmLoggerBuilder;
|
||||
use fluence::MountedBinaryResult;
|
||||
|
||||
pub fn main() {
|
||||
WasmLoggerBuilder::new().build().unwrap();
|
||||
}
|
||||
|
||||
#[fce]
|
||||
pub fn download(url: String) -> String {
|
||||
log::info!("get called with url {}", url);
|
||||
|
||||
let result = unsafe { curl(vec![url]) };
|
||||
String::from_utf8(result.stdout).unwrap()
|
||||
}
|
||||
|
||||
#[fce]
|
||||
#[link(wasm_import_module = "host")]
|
||||
extern "C" {
|
||||
fn curl(cmd: Vec<String>) -> MountedBinaryResult;
|
||||
}
|
||||
```
|
||||
|
||||
with the following dependencies necessary in the Cargo.toml:
|
||||
|
||||
```rust
|
||||
fluence = { version = "=0.4.2", features = ["logger"] }
|
||||
log = "0.4.8"
|
||||
```
|
||||
|
||||
We are basically linking the [external](https://doc.rust-lang.org/std/keyword.extern.html) cUrl binary and are exposing access to it as a FCE interface called download.
|
||||
|
||||
### Code References
|
||||
|
||||
* [Mounted binaries](https://github.com/fluencelabs/fce/blob/c559f3f2266b924398c203a45863ebf2fb9252ec/fluence-faas/src/host_imports/mounted_binaries.rs)
|
||||
* [cUrl](https://github.com/curl/curl)
|
||||
|
||||
### Service Construction
|
||||
|
||||
In order to create a valid Fluence service, a service configuration is required.
|
||||
|
||||
```text
|
||||
modules_dir = "target/wasm32-wasi/release"
|
||||
|
||||
[[module]]
|
||||
name = "curl_adapter"
|
||||
logger_enabled = true
|
||||
|
||||
[mounted.mounted_binaries]
|
||||
curl = "/usr/bin/curl"
|
||||
```
|
||||
|
||||
We are specifying the location of the Wsasm file, the import name of the Wasm file, some logging housekeeping, and the mounted binary reference with the command-line call information.
|
||||
|
||||
### Remote Service Creation
|
||||
|
||||
```bash
|
||||
cargo new curl-service
|
||||
cd curl-service
|
||||
# copy the above rust code into src/main
|
||||
# copy the specified dependencies into Cargo.toml
|
||||
# copy the above service configuration into Config.toml
|
||||
|
||||
fce build --release
|
||||
```
|
||||
|
||||
You should have the Fluence module curl\_adapter.wasm in `target/wasm32-wasi/release` we can test our service with `fce-repl`.
|
||||
|
||||
### Service `Test`
|
||||
|
||||
Running the REPL, we use the `interface` command to list all available interfaces and the `call` command to run a method. Fr our purposes, we furnish the [https://duckduckgo.com/?q=Fluence+Labs](https://duckduckgo.com/?q=Fluence+Labs) url to give the the curl adapter a workout.
|
||||
|
||||
```bash
|
||||
fce-repl Config.toml
|
||||
Welcome to the FCE REPL (version 0.5.2)
|
||||
app service was created with service id = 8ad81c3a-8c5c-4730-80d1-c54cd177725d
|
||||
elapsed time 40.312376ms
|
||||
|
||||
1> interface
|
||||
Loaded modules interface:
|
||||
|
||||
curl_adapter:
|
||||
fn download(url: String) -> String
|
||||
|
||||
2> call curl_adapter download ["https://duckduckgo.com/?q=Fluence+Labs"]
|
||||
result: String("<!DOCTYPE html><html lang=\"en-US\" class=\"no-js has-zcm no-theme\"><head><meta name=\"description\" content=\"DuckDuckGo. Privacy, Simplified.\"><meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\"><title>Fluence Labs at DuckDuckGo</title><link rel=\"stylesheet\" href=\"/s1963.css\" type=\"text/css\"><link rel=\"stylesheet\" href=\"/r1963.css\" type=\"text/css\"><meta name=\"robots\" content=\"noindex,nofollow\"><meta name=\"referrer\" content=\"origin\"><meta name=\"apple-mobile-web-app-title\" content=\"Fluence Labs\"><link rel=\"preconnect\" href=\"https://links.duckduckgo.com\"><link rel=\"preload\" href=\"/font/ProximaNova-Reg-webfont.woff2\" as=\"font\" type=\"font/woff2\" crossorigin=\"anonymous\" /><link rel=\"preload\" href=\"/font/ProximaNova-Sbold-webfont.woff2\" as=\"font\" type=\"font/woff2\" crossorigin=\"anonymous\" /><link rel=\"shortcut icon\" href=\"/favicon.ico\" type=\"image/x-icon\" /><link id=\"icon60\" rel=\"apple-touch-icon\" href=\"/assets/icons/meta/DDG-iOS-icon_60x60.png?v=2\"/><link id=\"icon76\" rel=\"apple-touch-icon\" sizes=\"76x76\" href=\"/assets/icons/meta/DDG-iOS-icon_76x76.png?v=2\"/><link id=\"icon120\" rel=\"apple-touch-icon\" sizes=\"120x120\" href=\"/assets/icons/meta/DDG-iOS-icon_120x120.png?v=2\"/><link id=\"icon152\" rel=\"apple-touch-icon\"s
|
||||
<snip>
|
||||
ript\">DDG.index = DDG.index || {}; DDG.index.signalSummary = \"\";</script>")
|
||||
elapsed time: 334.545388ms
|
||||
|
||||
3>
|
||||
```
|
||||
|
51
tutorials_tutorials/recipes_setting_up.md
Normal file
51
tutorials_tutorials/recipes_setting_up.md
Normal file
@ -0,0 +1,51 @@
|
||||
# Setting Up Your Environment
|
||||
|
||||
In order to develop within the Fluence solution, [Rust](https://www.rust-lang.org/tools/install) and small number of tools are required.
|
||||
|
||||
## Rust
|
||||
|
||||
Install Rust:
|
||||
|
||||
```bash
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
```
|
||||
|
||||
once Rust is installed, we need to expand the toolchain and include [nightly build](https://rust-lang.github.io/rustup/concepts/channels.html) and the [Wasm](https://doc.rust-lang.org/stable/nightly-rustc/rustc_target/spec/wasm32_wasi/index.html) compile target.
|
||||
|
||||
```bash
|
||||
rustup install nightly
|
||||
rustup target add wasm32-wasi
|
||||
```
|
||||
|
||||
To keep Rust and the toolchains updated:
|
||||
|
||||
```bash
|
||||
rustup self update
|
||||
rustup update
|
||||
```
|
||||
|
||||
There are a number of good Rust installation and IDE integration tutorials available. [DuckDuckGo](https://duckduckgo.com/) is your friend but if that's too much effort, have a look at [koderhq](https://www.koderhq.com/tutorial/rust/environment-setup/).
|
||||
|
||||
## Fluence Tools
|
||||
|
||||
Fluence provides several tools to support developers. Fluence cli, `flcli`, facilitates the compilation of modules to the necessary wasm32-wasi target. Fluence REPL, `fce-repl`, on the other hand, is a cli tool to test and experiment with FCE modules and services locally.
|
||||
|
||||
```bash
|
||||
cargo install fcli
|
||||
cargo +nightly install frepl
|
||||
```
|
||||
|
||||
In addition, Fluence provides the [proto-distributor](https://github.com/fluencelabs/proto-distributor) tool, aka `fldist`, for service lifecyle management. From deploying services to the network to executing AIR scripts, `fldist` does it all.
|
||||
|
||||
```bash
|
||||
npm install -g @fluencelabs/fldist
|
||||
```
|
||||
|
||||
## Fluence SDK
|
||||
|
||||
For frontend development, the Fluence [JS-SDK](https://github.com/fluencelabs/fluence-js) is currently the favored, and only, tool.
|
||||
|
||||
```bash
|
||||
npm install @fluencelabs/fluence
|
||||
```
|
||||
|
Loading…
Reference in New Issue
Block a user