Skip to content

Latest commit

 

History

History

README.md

Tac Operation Lifecycle Service

Intro

Ton Application Chain (TAC) is an EVM-compatible extension for the TON blockchain. TAC transactions are ordered and executed under a separate consensus mechanism, with only the execution results being posted back on-chain — a pattern somewhat similar to how rollups operate.

Users interact with TAC either through dedicated dApps or via smart contracts on the TON chain. Regardless of the method, the user’s intention — along with all resulting artifacts — is encapsulated under a single concept called an “Operation.”

These Operations can involve different data flows and a variety of status types. This complexity can be confusing for inexperienced users and may hinder debugging for dApp developers.

This feature addresses that by indexing TAC Operations in a way that provides a clear, high-level overview of what occurred as a result of a user’s action — making it easier for both users and developers to understand at a glance.

Improvements

Indexer Logic Description The TAC Operation Lifecycle Indexer follows a process describing below:

  1. Timeline Dissection:
  • The indexer divides the historical timeline into fixed-size intervals
  • The watermark marks the latest timestamp covered by intervals
  • The watermark advances as new intervals are added
  • For historical data, intervals are processed in both directions: from the oldest to the newest and vice versa.
  1. Historical Interval Processing:
  • For each interval, the indexer fetches a list of operations that occurred within that time window
  • Operations are stored in the database with a pending status
  • The interval is marked as finalized once operations are fetched
  • If fetching fails, the interval is scheduled for retry
  1. Realtime Interval Processing
  • For realtime data, new intervals are not created in advance.
  • A separate thread fetches new operations starting from the latest known operation up to the current timestamp.
  • Once new operations are fetched, a new interval in the finalized state is created to match the request range — from the previously latest known operation to the current one. This approach helps avoid issues caused by the remote TAC RPC being out of sync.
  1. Operation Processing:
  • For each operation, the indexer fetches detailed stage information
  • Operation stages track the lifecycle of the operation across different blockchains
  • Once stages are fetched, the operation is marked as finalized
  • If fetching fails, the operation is scheduled for retry
+----------------------------------------------------------------------------------------+
|                                    TAC OPERATION LIFECYCLE INDEXER                      |
+----------------------------------------------------------------------------------------+
                                                                                          
                                                                                          
+-------------------+     +-------------------+     +-------------------+                  
|                   |     |                   |     |                   |                  
|  Timeline         |     |  Intervals        |     |  Operations       |                  
|  Dissection       |---->|  Processing       |---->|  Processing       |                  
|                   |     |                   |     |                   |                  
+-------------------+     +-------------------+     +-------------------+                  
        |                         |                         |                              
        |                         |                         |                              
        v                         v                         v                              
+-------------------+     +-------------------+     +-------------------+                  
|                   |     |                   |     |                   |                  
|  Watermark        |     |  Fetch            |     |  Fetch            |                  
|  Advancement      |     |  Operations       |     |  Operation        |                  
|                   |     |  for Interval     |     |  Stages           |                  
+-------------------+     +-------------------+     +-------------------+  

We persist and track latest saved interval (watermark) in the database and advance it alongside with creating new intervals. Apart from latest interval we also track latest operation so that if we get a falsely empty response we would automatically request it again. The indexer follows the following practices specifically the server launches multiple future streams:

  • historic operation fetcher that selects intervals in both directions from a configurable starting timestamp
  • realtime operation fetcher that selects intervals in ascending order after the service has started
  • failed intervals and operations fetcher resends failed requests
+----------------------------------------------------------------------------------------+
|  (high prio)         --->         PRIORITIZED STREAMS         --->         (low prio)  |
+----------------------------------------------------------------------------------------+
                                                                                          
                                                                                          
+-------------------+     +-------------------+     +-------------------+                  
|                   |     |                   |     |                   |                  
|  Operation        |     |  Historical       |     |  Operations and   |                  
|  Streams          |     |  Intervals        |     |  Intervals        |                  
|  (Pending + New)  |     |  Streams          |     |  Retry Streams    |
|                   |     |                   |     |                   |                  
+-------------------+     +-------------------+     +-------------------+                  
        |                         |                         |                              
        |                         |                         |                              
        v                         v                         v                              
+----------------------------------------------------------------------------------------+
|                                    COMBINED STREAM                                      |
+----------------------------------------------------------------------------------------+

Configuration Parameters

Parameters can be configured either using a toml file or environment variables. See example in tac-operation-lifecycle-server/config.toml

Variable Req​uir​ed Description Default value
TAC_OPERATION_LIFECYCLE__INDEXER__CONCURRENCY The number of jobs simultaneously fetched from the common job stream. num_of_cores
TAC_OPERATION_LIFECYCLE__INDEXER__CATCHUP_INTERVAL The size of time windows (in seconds) used for processing historical data. Smaller intervals provide more granular processing but may increase the number of RPC calls. 5
TAC_OPERATION_LIFECYCLE__INDEXER__POLLING_INTERVAL Determines how frequently the indexer checks for new (realtime) data. The value is provided in seconds. 2
TAC_OPERATION_LIFECYCLE__INDEXER__RETRY_INTERVAL Determines how frequently the indexer will retry failed intervals and operations. The value is provided in seconds. 120
TAC_OPERATION_LIFECYCLE__INDEXER__START_TIMESTAMP Specifies a custom starting point for historical data indexing. Setting it to 0 means the indexer will start from the earliest available data (this will significantly increase sync time). Events before this epoch are ignored. Useful for partial sync. 0
TAC_OPERATION_LIFECYCLE__INDEXER__FOREVER_PENDING_OPERATIONS_AGE_SEC The operation is considered completed if it is older than this value (in seconds) but remains in the PENDING state. The value is hardcoded by the protocol and equals one week. 604800
TAC_OPERATION_LIFECYCLE__INDEXER__INTERVALS_QUERY_BATCH The number of pending intervals simultaneously fetched from the database to be processed. Lower values will reduce database load. 10
TAC_OPERATION_LIFECYCLE__INDEXER__INTERVALS_RETRY_BATCH The number of failed intervals simultaneously fetched from the database during the retry cycle. Lower values will reduce database load. 10
TAC_OPERATION_LIFECYCLE__INDEXER__INTERVALS_LOOP_DELAY_MS Delay between interval fetches (from the database) to prevent a tight loop. The value is in milliseconds. 100
TAC_OPERATION_LIFECYCLE__INDEXER__OPERATIONS_QUERY_BATCH The number of pending operations simultaneously fetched from the database to be processed. Lower values will reduce database load. 10
TAC_OPERATION_LIFECYCLE__INDEXER__OPERATIONS_RETRY_BATCH The number of failed operations simultaneously fetched from the database during the retry cycle. Lower values will reduce database load. 10
TAC_OPERATION_LIFECYCLE__INDEXER__OPERATIONS_LOOP_DELAY_MS Delay between operation fetches (from the database) to prevent a tight loop. The value is in milliseconds. 200
TAC_OPERATION_LIFECYCLE__RPC__URL TAC Staging Service RPC endpoint. https://data.turin.tac.build/
TAC_OPERATION_LIFECYCLE__RPC__REQUEST_PER_SECOND The rate limit for requests per second. 100
TAC_OPERATION_LIFECYCLE__RPC__NUM_OF_RETRIES The number of retries for each request. A request is considered failed after this number of retries. 10
TAC_OPERATION_LIFECYCLE__RPC__RETRY_DELAY_MS The delay in milliseconds between retries. 1000
TAC_OPERATION_LIFECYCLE__DATABASE__CREATE_DATABASE Whether to create the database if it does not exist. false
TAC_OPERATION_LIFECYCLE__DATABASE__RUN_MIGRATIONS Whether to run database migrations on startup. false
TAC_OPERATION_LIFECYCLE__DATABASE__CONNECT__URL The database connection URL (e.g., postgres://postgres:postgres@database:5432/blockscout). None
TAC_OPERATION_LIFECYCLE__DATABASE__CONNECT_OPTIONS__ACQUIRE_TIMEOUT The timeout (in seconds) for acquiring a database connection. null
TAC_OPERATION_LIFECYCLE__DATABASE__CONNECT_OPTIONS__CONNECT_TIMEOUT The timeout (in seconds) for establishing a database connection. null
TAC_OPERATION_LIFECYCLE__DATABASE__CONNECT_OPTIONS__IDLE_TIMEOUT The timeout (in seconds) for idle database connections. null
TAC_OPERATION_LIFECYCLE__DATABASE__CONNECT_OPTIONS__MAX_CONNECTIONS The maximum number of database connections. null
TAC_OPERATION_LIFECYCLE__DATABASE__CONNECT_OPTIONS__MAX_LIFETIME The maximum lifetime (in seconds) of a database connection. null
TAC_OPERATION_LIFECYCLE__DATABASE__CONNECT_OPTIONS__MIN_CONNECTIONS The minimum number of database connections. null
TAC_OPERATION_LIFECYCLE__DATABASE__CONNECT_OPTIONS__SQLX_LOGGING Whether to enable SQLx logging. true
TAC_OPERATION_LIFECYCLE__DATABASE__CONNECT_OPTIONS__SQLX_LOGGING_LEVEL The logging level for SQLx. debug
TAC_OPERATION_LIFECYCLE__DATABASE__CONNECT_OPTIONS__CONNECT_LAZY Whether to establish database connections lazily. false
TAC_OPERATION_LIFECYCLE__DATABASE__CONNECT_OPTIONS__SQLX_SLOW_STATEMENTS_LOGGING_LEVEL The logging level for slow SQL statements. off
TAC_OPERATION_LIFECYCLE__DATABASE__CONNECT_OPTIONS__SQLX_SLOW_STATEMENTS_LOGGING_THRESHOLD The threshold (in seconds) for logging slow SQL statements. 1

Dev

  • Install just cli. Just is like make but better.
  • Execute just to see avaliable dev commands
just
  • Start dev postgres service by just typing
just start-postgres
  • For ORM codegen and migrations install sea-orm-cli

  • Write initial migration inside tac-operation-lifecycle-logic/migration/src/m20220101_000001_create_table.

  • If you want you can create another migration by just typing:

just new-migration <name>
  • Apply migration by just typing:
just migrate-up
  • Generate ORM codegen by just typing:
just generate-entities
  • Now you ready to start API server! Just run it:
just run