Sample Txn Executor
Let's focus on the sample-txn-executor folder in this article. This is a brand new folder and it'll build the wasm file that will be loaded into the state machine .
Folder structure
All actors have the same folder structure:
codec contains all the type definitions.
impl contains all the logic.
One thing to mention and likely overlooked is the last line in the build.sh file: cp -r target/wasm32-unknown-unknown/release/sample_txn_executor.wasm ../../dev-runner/local/a-node/
You may have already noticed that the destination folder is an a-node instead of a b-node of the sample-actor.
Codec
In the txn.rs file, we have Task, Status, And Txns definitions.
Task is the model if you're familar with the MVC concept. This object will be mapped to the SQL database for CRUD.
Please note the types "Account, Balance". Those are predefined TEA Project types. You'll use them a lot.
Every task will need to have each of the following:
creator: who creates this task, who's also the owner. It's an Account type.
subject: the title of this task. Such as "Buy me a beer!"
price: The worker who has done this task successfully will receive the reward price from the owner/creator.
required_deposit: The worker who takes a task will need to pay the deposit. If they fail to complete the task, the deposit will be slashed and rolled into the price. The final successful worker will take the augmented price.
status: See below.
worker: None if no one takes a particular task, or the worker who is currently working on or completes a particular task.
The status is:
Their names explain the meaning.
The most important concept is txn:
Those Txn types are the Transaction objects that the hosting nodes (where the b-actor is running) sends to the state machine (A-actor) to handle. It's similar to the stored procedures inside of databases of the web2 era.
Every txn will have the parameters, and the execution logic of these txn will be inside the impl
folder.
In the lib.rs file, we have defined Requests and Responses as we did in our last step.
There's a new struct TaskQueryRequests:
and a response that returns a string of tasks. The Task has a type of txn::Task
.
TaskQueryRequests are used in Queries from the hosting nodes. When a B-actor wants to query a list of Tasks they can use these conditions.
Note: In TEA Project future versions, a local state cache will be provided to the hosting nodes. So in most cases, there's no need for the hosting node to query the list of Tasks from the state machine, which will ultimately reduce the cost.
Impl
manifest.yaml added new access
Compared with the previous steps, you'll notice there are lots of new access items added:
You can go to the developer documentation for the usage for each provider actor. Because the sql
branch has added many system features such as fund transfer, sql access, storage etc, it's required to claim the list in the manifest. Otherwise, the access will be banned by the tea-runtime.
tables.sql is a standard sql script
This is the first time you'll find a non rs file in the src folder. This is a standard SQL file. It's nothing but a script to create a table.
To simplify our tutorial, we didn't use any 3rd party MVC tools to build sql scripts for us. We use pure SQL which is easily understood by developers. When you're building your own TApp, feel free to use whatever existing web2 tools you're familiar with. They should all work well with the TEA Project.
You may be wondering where the other SQL scripts are located? We should use Create, Read, Update, Delete scripts. Well, they're inside the rs code as string and you'll see them soon.
Add new errors into error.rs
Because we're now handling the txn, there will be errors during txn execution. We need to define them inside of error.rs
:
Note, don't forget to add to the define_scope macro too:
Execute transactions in txn.rs
Most of the logic is here inside the txn.rs function txn_exec
.
You can see all txns defined in the codec have been handled in a match
branch, then return a commit_ctx. The commit_ctx is a Context type which records all changes during the txn execution. However, before the commit_ctx is finally commited at the last of the txn_exec
function, no actual changes happened in the state. That means, at any time, if the execution failed for whatever reason, the state will NOT be changed.
Let's use CreateTask as an example:
This txn is very simple and only runs SQL scripts. Before any real business logic, the line of check_account
will make sure the user is the task.creator
and isn't impersonated. If Alice is trying to create a task but claims the creator is Bob, this check will fail. If this check passes, the next new_gluedb_context()
will generate a new glue_ctx. It also starts an SQL Transaction. If anything failed before the commit, no change will be written to the SQL database.
The SQL scripts is inside the create_task
function.
The function exec_sql
will run the SQL scripts.
In TEA Project, the SQL engine is GlueSQL. This is not a fully featured SQL engine, so please review our documentation entry for GlueSQL ) for more details. In our tutorial, we only use very basic SQL features. For example, we didn't use auto increase ID but instead used the subject as ID. This isn't ideal but is good enough to demonstrate the logic. Teaching SQL is not the purpose of this tutorial.
Please make sure sql_init
is called at Txns::Init
.
TODO:// GOD_MODE_AUTH_KEY will be replaced later
lib.rs
Lib.rs is the entry point of the whole sample-txn-executor. It has the same structure as the sample-actor.
First, we should also list all txns that we can handle:
HttpRequest is a special request that we created for the local dev-runner only. In the real production environment this will not exist. The purpose of adding http requests to the sample-txn-executor is for easy CURL / Postman testing. In the real production environment, all txns are sent from the hosting nodes (B-actors). You have to have a B node to test the Txns, which causes additional complexities. Using this "mock" http request, you can write your own local test code. Especially when dealling with SQL, it's hard to test SQL in unit tests.
Last updated