refactor(ntx-builder): replace the account actors with a scheduler - #2585
refactor(ntx-builder): replace the account actors with a scheduler#2585SantiagoPittella wants to merge 1 commit into
Conversation
c33fb3c to
ccbc958
Compare
ccbc958 to
831b6f9
Compare
831b6f9 to
c5b29a1
Compare
There was a problem hiding this comment.
I'm not a fan of attempt as a base name.
Perhaps something like NetworkTransactionContext and the current free standing functions could be methods?
| /// Chain tip at submission. With the transaction expiration delta this bounds how long the | ||
| /// account stays blocked when the submission never lands. | ||
| submitted_at: BlockNumber, |
There was a problem hiding this comment.
Would it make more sense to store expires_at given that's what actually triggers?
| /// The spawned attempt tasks. | ||
| tasks: JoinSet<AttemptOutcome>, | ||
|
|
||
| /// Accounts with a running attempt, keyed by task id. These occupy the attempt slots. | ||
| running: HashMap<Id, AccountId>, |
There was a problem hiding this comment.
Perhaps we should make the utils Tasks generic and use that here?
| /// Maximum number of attempts computed concurrently. | ||
| max_concurrent_txs: usize, | ||
|
|
||
| /// Number of blocks after which a submitted transaction expires. An in-flight entry older than | ||
| /// this is dropped, which releases the account for a new attempt. | ||
| tx_expiration_delta: NonZeroU16, |
There was a problem hiding this comment.
Consider moving to a dedicated Config struct.
| pub async fn shutdown(&mut self) { | ||
| self.tasks.shutdown().await; | ||
| self.running.clear(); | ||
| self.in_flight.clear(); | ||
| } |
There was a problem hiding this comment.
When is this called? I'm surprised this isn't shutdown(self), then no need to keep this re-useable afterwards.
| loop { | ||
| match self.tasks.join_next_with_id().await { | ||
| Some(Ok((id, outcome))) => { | ||
| self.running.remove(&id); | ||
| return Ok(outcome); | ||
| }, | ||
| Some(Err(err)) => { | ||
| let account_id = self.running.remove(&err.id()); | ||
| // Cancelled tasks were aborted on shutdown. | ||
| if err.is_cancelled() { | ||
| continue; | ||
| } |
There was a problem hiding this comment.
This loop and cancellation check feel a bit weird?
| /// A slot is refilled immediately after an attempt that made progress, so a completed | ||
| /// transaction does not leave capacity idle until the next block. An attempt that found no | ||
| /// viable work, or that could not run at all, does not trigger a refill: the state that | ||
| /// selected its account has not changed, so an immediate re-dispatch could pick the same | ||
| /// account again. |
There was a problem hiding this comment.
This is referencing stuff outside of this functions scope.
| // Applied before the failures so a note that is both corrected and penalized keeps the | ||
| // backoff block the penalty computes, which is the later of the two. |
There was a problem hiding this comment.
I don't quite understand why notes need to be corrected?
c5b29a1 to
14c5a4e
Compare
14c5a4e to
d5adee5
Compare
Summary
Now the loop spawns a task per account, up to
--max-concurrent-txsat a time. The task picks notes, executes, proves, submits, and returns what happened, also this loops does the writting.The scheduler doesn't hold anything in memory per account except which transactions it has submitted and not yet seen committed.
Changelog