Anoma.Node.Transaction.Ordering (Anoma v0.35.0)
I am the Ordering Engine.
I act as a mediator between Workers and Shards. In particular, Workers working on a transaction may ask to read and write information. However, they do not know when to do it, they only know the ID of the transaction they work on. Moreover, they do not know where the key they are interested in is stored, i.e. on which shard.
I process such requests, keeping them waiting until consensus provides some ordering to a transaction in question. Once they do, I pair a transaction ID with its timestamp and forward queries to appropriate Shards.
Public API
I provide the following public functonality:
Summary
Types
Type of the arguments the ordering genserver expects
I am the type of possible ordering operations
I am a request that can be enqued
I am the type of reservations
I am the type of the Ordering Enigine.
Functions
Returns a specification to start this module under a supervisor.
I am the Ordering commit function. I handle checkpointing by committing blocks and shard states to tables.
I am the initialization function for the Ordering Engine.
I am the Ordering order function.
I am the Ordering read function.
I am the Ordering reserve function.
I am the start_link function for the Ordering Engine.
I am the Ordering write function.
Types
@type args_t() :: [node_id: String.t(), next_height: non_neg_integer()] | [{:node_id, String.t()}]
Type of the arguments the ordering genserver expects
@type flag() :: :read | :write
I am the type of possible ordering operations
@type request() :: {flag(), GenServer.from(), [{any(), any()}] | any()}
I am a request that can be enqued
I am the type of reservations
@type t() :: %Anoma.Node.Transaction.Ordering{ block_key_order: %{required(any()) => [{flag(), non_neg_integer()}]}, next_height: integer(), node_id: String.t(), requests: %{required(binary()) => request()}, reservations: %{required(any()) => reservations()}, shard_addresses: %{required(any()) => pid()}, tx_id_to_height: %{required(binary()) => integer()} }
I am the type of the Ordering Enigine.
I contain the Node for which the Ordering is launched, the upcoming hight as well as a map from transaction IDs to their global order.
Fields
:node_id- The ID of the Node to which an Ordering instantiation isbound.:next_height- The height that the next ordered transactioncandidate will get. Default: 1:tx_id_to_height- A map from an ID of a transaction candidate toits order.:requests- A map from the ID of a transaction candidate to itsworker address with the request to read or write. Default: %{}:shard_addresses- The addresses of the shards containing keys.Default: %{}:reservations- The map from IDs to lists of read and writereservations to be forwarded to shards. Default: %{}:block_key_order- The map from keys to a list of height orderedfrom most recent. Used to advance watermarks Default: %{}
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
I am the Ordering commit function. I handle checkpointing by committing blocks and shard states to tables.
Given a set of IDs for a block alongside with appropriate writes, I make sure that no reservations are to be completed, then ask each shard to backup state.
Finally, I create the block with the transaction completion information.
I am the initialization function for the Ordering Engine.
From the specified arguments, I get the Node ID as well as the info regarding the next height Ordering should be started with. I also subscribe to the completion events to finalize shard interactions.
I am the Ordering order function.
Given a Node ID and a list of transaction IDs, I percieve the latter as a partial ordering of transactions. Afterwards, I assign them a global ordering by adding the next height stored in the Ordering Engine to the respective ordering inside a list.
Afterwards, I send an event specifying that a particular ID has indeed received an order.
WARNING :: NO Read Only Transaction ID's should
I am the Ordering read function.
I receive a Node ID and an {id, key} tuple. There are two states possible when Ordering processes my request. Either:
- The id has been assigned an order.
- The id has not been assigned an order.
If the former is true, I send the request to read the key at the
specified height to the appropriate shard. That is, we ask the shard to
read the most recent value assigned to the key from the point of view of
the transaction candidate. See Shard.read/3.
If the latter is true, I leave the caller blocked until the id has been assigned a value, i.e. until a corresponding event gets received.
I am the Ordering reserve function.
Given an ID of a transaction, there are two possible states:
- The id has been assigned an order.
- The id has not been assigned an order.
If the former is true, I forward the reservations to the appropriate shards at the appropriate orders. Otherwise, I store the reservation requests in my state to forward them to shards once heights have been assigned.
@spec start_link(args_t()) :: GenServer.on_start()
I am the start_link function for the Ordering Engine.
I register the engine with supplied node ID provided by the arguments.
I am the Ordering write function.
I receive a Node ID and an {id, kvlist} tuple. There are two states possible when Ordering processes my request. Either:
- The id has been assigned an order.
- The id has not been assigned an order.
If the former is true, I send the request to write the key-value list at
the specified height to the appropriate shards by separating each element
in the list to its own request. See Shard.write/4
If the latter is true, I leave the caller blocked until the id has been assigned a value, i.e. until a corresponding event gets received.