Skip to content

Conversation

@joshuahannan
Copy link
Member

@joshuahannan joshuahannan commented Dec 11, 2025

Fixes an issue in FlowTransactionSchedulerUtils.Manager.cleanup where we were not removing old timestamps from the array when their transactions were cleaned up. This was causing that array to grow without bounds and causing some apps to reach the computation limit.

Additionally, I removed the check for the transaction status to be nil or Unknown before removing because this is not sufficient to remove old transactions in time. We originally included this because we thought it might be useful for people to be able to query their executed transactions for their status, but the highest priority is actually to keep the computation limit low and apps can figure out different ways to monitor their transactions.

There is also the issue that some of these managers have already reached the computation limit, so if we just changed this check, it may not actually work to get those into a working state. Because of this, I included a conditional in the cleanup function that breaks the loop after 100 ids so that the old timestamps can be cleaned up in batches until it is in a manageable state. Then we can remove that check in an upgrade. Not sure it 100 ids is the right number because I just picked an arbitrary one. I'm open to feedback on other options for number of ids or other ways to batch it.

Another option would be to remove the cleanup function from schedule() entirely, but then there is no way to keep the maps from growing indefinitely without calling cleanup manually, so I would still like to keep it in there if possible.

Comment on lines 324 to 326
let status = FlowTransactionScheduler.getStatus(id: id)
if status == nil || status == FlowTransactionScheduler.Status.Unknown {
transactionsToRemove.append(id)
}
transactionsToRemove.append(id)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by removing the conditional, I think we're appending adding ids that could be scheduled. is that right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or is that not an issue because we're getting timestamps before the current timestamp?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wouldn't remove scheduled ids because it is only doing timestamps in the past, but now that you mention it, I think it might remove ids that are supposed to execute in the same block but haven't actually been executed yet. I need to think about it a bit more, but I don't think that is an issue because this just removes the scheduled transaction resource and does not affect the handler

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll still add a check that the status can't be scheduled though just to be safe

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, if anything likely more of an edge case where I cleanup something I want to cancel in the current or next block

ids.remove(at: index!)
if ids.length == 0 {
self.idsByTimestamp.remove(key: timestamp)
self.sortedTimestamps.remove(timestamp: timestamp)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these were not removed prior, do we need some sort of backfill logic to remove irrelevant sorted timestamps?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I'll add that

// 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 > 100 {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's an edge case, but if one timestamp has 200 transactions, all 200 get added before the check runs. Should the check be also inside the inner loop for stricter limiting?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I can put it in the inner loop

@joshuahannan joshuahannan requested a review from mfbz December 11, 2025 21:50
// 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 {
Copy link
Member Author

Choose a reason for hiding this comment

The 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

Copy link
Collaborator

Choose a reason for hiding this comment

The 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).

Copy link
Member Author

@joshuahannan joshuahannan Dec 12, 2025

Choose a reason for hiding this comment

The 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

// 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 {
Copy link
Collaborator

Choose a reason for hiding this comment

The 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).

@joshuahannan joshuahannan merged commit 00b6948 into master Dec 12, 2025
2 checks passed
@joshuahannan joshuahannan deleted the josh/manager-cleanup branch December 12, 2025 16:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants