-
Notifications
You must be signed in to change notification settings - Fork 50
Remove old timestamps in scheduleld transaction manager cleanup #571
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -119,6 +119,7 @@ access(all) contract FlowTransactionSchedulerUtils { | |
| access(all) view fun getTransactionIDsByTimestamp(_ timestamp: UFix64): [UInt64] | ||
| access(all) fun getTransactionIDsByTimestampRange(startTimestamp: UFix64, endTimestamp: UFix64): {UFix64: [UInt64]} | ||
| access(all) view fun getTransactionStatus(id: UInt64): FlowTransactionScheduler.Status? | ||
| access(all) view fun getSortedTimestamps(): FlowTransactionScheduler.SortedTimestamps | ||
| } | ||
|
|
||
| /// Manager resource is meant to provide users and developers with a simple way | ||
|
|
@@ -221,6 +222,7 @@ access(all) contract FlowTransactionSchedulerUtils { | |
|
|
||
| // Store the handler capability in our dictionary for later retrieval | ||
| let id = scheduledTransaction.id | ||
| let actualTimestamp = scheduledTransaction.timestamp | ||
| let handlerRef = handlerCap.borrow() | ||
| ?? panic("Invalid transaction handler: Could not borrow a reference to the transaction handler") | ||
| let handlerTypeIdentifier = handlerRef.getType().identifier | ||
|
|
@@ -250,14 +252,14 @@ access(all) contract FlowTransactionSchedulerUtils { | |
| self.scheduledTransactions[scheduledTransaction.id] <-! scheduledTransaction | ||
|
|
||
| // Add the transaction to the sorted timestamps array | ||
| self.sortedTimestamps.add(timestamp: timestamp) | ||
| self.sortedTimestamps.add(timestamp: actualTimestamp) | ||
|
|
||
| // Store the transaction in the ids by timestamp dictionary | ||
| if let ids = self.idsByTimestamp[timestamp] { | ||
| if let ids = self.idsByTimestamp[actualTimestamp] { | ||
| ids.append(id) | ||
| self.idsByTimestamp[timestamp] = ids | ||
| self.idsByTimestamp[actualTimestamp] = ids | ||
| } else { | ||
| self.idsByTimestamp[timestamp] = [id] | ||
| self.idsByTimestamp[actualTimestamp] = [id] | ||
| } | ||
|
|
||
| return id | ||
|
|
@@ -284,27 +286,26 @@ access(all) contract FlowTransactionSchedulerUtils { | |
| /// @param timestamp: The timestamp of the transaction to remove | ||
| /// @param handlerTypeIdentifier: The type identifier of the handler of the transaction to remove | ||
| access(self) fun removeID(id: UInt64, timestamp: UFix64, handlerTypeIdentifier: String) { | ||
| pre { | ||
| self.handlerInfos.containsKey(handlerTypeIdentifier): "Invalid handler type identifier: Handler with type identifier \(handlerTypeIdentifier) not found in manager" | ||
| self.idsByTimestamp.containsKey(timestamp): "Invalid timestamp: Timestamp \(timestamp) not found in manager for transaction with ID \(id)" | ||
| } | ||
|
|
||
| if let ids = self.idsByTimestamp[timestamp] { | ||
| let index = ids.firstIndex(of: id) | ||
| ids.remove(at: index!) | ||
| if ids.length == 0 { | ||
| self.idsByTimestamp.remove(key: timestamp) | ||
| } else { | ||
| self.idsByTimestamp[timestamp] = ids | ||
| } | ||
| let ids = &self.idsByTimestamp[timestamp]! as auth(Mutate) &[UInt64] | ||
| let index = ids.firstIndex(of: id) | ||
| ids.remove(at: index!) | ||
| if ids.length == 0 { | ||
| self.idsByTimestamp.remove(key: timestamp) | ||
| self.sortedTimestamps.remove(timestamp: timestamp) | ||
| } | ||
|
|
||
| let handlerUUID = self.handlerUUIDsByTransactionID.remove(key: id) | ||
| ?? panic("Invalid ID: Transaction with ID \(id) not found in manager") | ||
|
|
||
| // Remove the transaction ID from the handler info array | ||
| if let handlers = self.handlerInfos[handlerTypeIdentifier] { | ||
| if let handlerInfo = handlers[handlerUUID] { | ||
| handlerInfo.removeTransactionID(id: id) | ||
| handlers[handlerUUID] = handlerInfo | ||
| } | ||
| self.handlerInfos[handlerTypeIdentifier] = handlers | ||
| let handlers = &self.handlerInfos[handlerTypeIdentifier]! as auth(Mutate) &{UInt64: HandlerInfo} | ||
| if let handlerInfo = handlers[handlerUUID] { | ||
| handlerInfo.removeTransactionID(id: id) | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -318,10 +319,21 @@ access(all) contract FlowTransactionSchedulerUtils { | |
| let pastTimestamps = self.sortedTimestamps.getBefore(current: currentTimestamp) | ||
| for timestamp in pastTimestamps { | ||
| let ids = self.idsByTimestamp[timestamp] ?? [] | ||
| if ids.length == 0 { | ||
| self.sortedTimestamps.remove(timestamp: timestamp) | ||
| continue | ||
| } | ||
| for id in ids { | ||
joshuahannan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| let status = FlowTransactionScheduler.getStatus(id: id) | ||
| if status == nil || status == FlowTransactionScheduler.Status.Unknown { | ||
| if status == nil || status! != FlowTransactionScheduler.Status.Scheduled { | ||
| transactionsToRemove.append(id) | ||
| // Need to temporarily limit the number of transactions to remove | ||
| // because some managers on mainnet have already hit the limit and we need to batch them | ||
| // to make sure they get cleaned up properly | ||
| // This will be removed eventually | ||
| if transactionsToRemove.length > 50 { | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This limit is only temporary. The cases that we've become aware of going over the computation limit were in the 100s of iterations, so we believe that this should be sufficient to allow them to clean up without hitting the limit again. We'll be doing some more testing also to make sure
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this number should be the same as the max transactions that can be scheduled per time slot (technically per block).
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel like that number might be too high because this is just per user and can include transactions for a lot of previous timestamps. One of the partners whose transactions were failing was failing with only 150 transactions previously scheduled, so I think we need to keep the limit lower than that to make sure we don't hit their computation limit again, especially if they are doing a lot of other complex stuff in their transaction |
||
| break | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -541,6 +553,12 @@ access(all) contract FlowTransactionSchedulerUtils { | |
| } | ||
| return FlowTransactionScheduler.Status.Unknown | ||
| } | ||
|
|
||
| /// Gets the sorted timestamps struct | ||
| /// @return: The sorted timestamps struct | ||
| access(all) view fun getSortedTimestamps(): FlowTransactionScheduler.SortedTimestamps { | ||
| return self.sortedTimestamps | ||
| } | ||
| } | ||
|
|
||
| /// Create a new Manager instance | ||
|
|
||
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import "FlowTransactionSchedulerUtils" | ||
| import "FlowTransactionScheduler" | ||
|
|
||
| access(all) fun main(address: Address): [UFix64] { | ||
| let managerRef = FlowTransactionSchedulerUtils.borrowManager(at: address) | ||
| ?? panic("Invalid address: Could not borrow a reference to the Scheduled Transaction Manager at address \(address)") | ||
| return managerRef.getSortedTimestamps().getBefore(current: getCurrentBlock().timestamp) | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.