-
Notifications
You must be signed in to change notification settings - Fork 32
Description
The new table sent_payable is clearly different from the old pending_payable table.
It will have these extra fields: receiver_address, gas_price, nonce, status, retried.
Extra attention should be paid to the status column which may change its value in time.
You need to reimplement the methods of this DAO so that they refer to the new sent_payables table instead.
There will be definitely some minor challenges, but in the big picture, it shouldn't be so much hard. Remember to review the names of the methods to fit their purpose now serving to a different table.
NEW RECORDS
When a new record for a pending transaction is created, put the status p (meant literally) in there, meaning a simple pending.
This status isn't gonna be persistent, on the contrary, it's actually the only one being temporary. We'll always start with this status and will change it to either:
a)
bnxxxxxxx("block number", followed by the respective number of the mined block on the blockchain)
b)fxxx("failure", followed by a specific opcode that can be used to decode the given kind of failure).
p should never stay in the record longer than what will be the time limit for a transaction to qualify as pending unbearably long, also resulting in another failure fxxx.
PICKING RECORDS TO CHECK THEM
There will be one important difference in the way we will do the selection of those past transactions that need to be queried about by an RPC. Up to this point, we've always concentrated on the transactions considered pending at the very moment (in the new design, those are represented by the status p). However, it's not enough. With some lower possibility, but still real, we could be exposed to a moment when we'd believe that transactions that we just claimed as taking too long could actually finish before we retry with transaction bearing the same nonce. It could cause that transactions left behind with a failure status led to creating its younger springs which, however, will never be able to complete, because they would always just repeat the same nonce which has been taken once and will not be approved again. Eventually, this would probably make the whole payment mechanics collapse. To avoid an endless cycle of terribly wrong resubmitting attempts, we need to take a short look back and recheck transactions that were marked with the failure identified as "tx pending too long" in the previous cycle, and so include them in the set of transactions of which we will ask the blockchain service provider.
If we receive a response that the rechecked transactions (with the older hashes) have actually completed (been stuck in a block), we will correct our records which requires:
a) Rewrite
fxxxtobnxxxto express its completion.
b) Delete the1from theretriedcolumn, or writing something like101or some other code telling us later that this tx failure has been reverted
c) Rewrite status of the retrying transaction with a special failure typefxxxwhich will also help to explain the history of events if anybody is interested in tracking it down
UPDATING RECORD STATUSES AFTER SCAN
Recently, the interface consists of methods like increment_scan_attempts and mark_failures. We will want to dump one and modify another. mark_failures should probably become something like update_status which will turn to be one of the most important methods. When we receive the data from the blockchain we will evaluate it which should end up with a determined status that will describe how each record stands after one scanning cycle. Having the most suitable status at hand, we will want to write it in the respective column in the table and that's the crucial moment which requires this update_status method.
Most of the time, the writing will go only into the column labeled status, however, it's possible that the same method will also write into the retried column (or we will get an extra method for that purpose, alternatively). This dual writing should happen for transactions believed pending too long. Such will:
a) receive a failure status code fxxx
b) value 1 will be writen into the
retriedcolumn (this column is meant for conveying the urgency of a retry to the PayableScanner running immediately after).
Probably redesign the struct PendingPayableFingerprint into TransactionRecord. It may be used anytime when we will read from the sent_payables table. For inserting a new record that belongs to a fresh pending transaction we may want to establish a different structure SentTransaction.
struct TransactionRecord {
transaction: Transaction,
status: TransactionStatus
}
struct Transaction {
receiver_address: Address,
amount: u128,
tx_hash: String,
timestamp: SystemTime,
gas_price_wei: u64,
nonce: u32,
}
pub trait SentPayablesDao {
//TODO maybe search by wallet addresses instead as they are shorter than hashes (remember, both are stored as `text` in the database)
fn transaction_rowids(&self, hashes: &[H256]) -> TransactionHashes;
fn return_all_pending_transactions(&self) -> Vec<TransactionRecord>;
fn return_all_transactions_to_retry(&self) -> Vec<TransactionRecord>
fn insert_new_records(
&self,
transactions: Vec<Transactions>,
) -> Result<(), SentPayableDaoError>;
fn delete_records(&self, ids: &[u64]) -> Result<(), SentPayableDaoError>;
fn change_statuses(&self, ids: &[StatusChange]) -> Result<(), SentPayableDaoError>;
}
struct StatusChange {
rowid: u64,
new_status: TransactionStatus
}Side note:
Change the struct TransactionHashes to maybe TransactionRowids.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status