Skip to content
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

[FUN-973] s4 snapshot caching #12275

Merged
merged 10 commits into from
Mar 11, 2024
Merged

Conversation

agparadiso
Copy link
Contributor

@agparadiso agparadiso commented Mar 4, 2024

Description

This pr introduces a s4 orm cache wrapper that accepts a ORM interface and wraps it with a in memory cache layer.
At the moment we are only focusing on caching the retrieve of Snapshots but the rest of the methods can also be cached if needed.

the Update method will invalidate the cache only if the given address is within the range of address cached.

Copy link
Contributor

github-actions bot commented Mar 4, 2024

I see that you haven't updated any CHANGELOG files. Would it make sense to do so?

@agparadiso agparadiso force-pushed the feat/FUN-973_s4_snapshot_caching branch from 4ca8dd6 to 051cd9e Compare March 4, 2024 15:26
@agparadiso agparadiso force-pushed the feat/FUN-973_s4_snapshot_caching branch from 051cd9e to 1652ecd Compare March 4, 2024 16:04
@agparadiso agparadiso force-pushed the feat/FUN-973_s4_snapshot_caching branch from 1652ecd to a025fbc Compare March 4, 2024 17:11
@agparadiso agparadiso force-pushed the feat/FUN-973_s4_snapshot_caching branch from a025fbc to 7af9645 Compare March 4, 2024 17:13
@agparadiso agparadiso force-pushed the feat/FUN-973_s4_snapshot_caching branch from 7af9645 to d0fe543 Compare March 5, 2024 12:14
@agparadiso agparadiso force-pushed the feat/FUN-973_s4_snapshot_caching branch from d0fe543 to 3beb238 Compare March 5, 2024 12:18
@agparadiso agparadiso force-pushed the feat/FUN-973_s4_snapshot_caching branch from 3beb238 to 29a1558 Compare March 5, 2024 13:06
@agparadiso agparadiso marked this pull request as ready for review March 5, 2024 13:32
@agparadiso agparadiso requested a review from a team as a code owner March 5, 2024 13:32
@agparadiso agparadiso self-assigned this Mar 5, 2024
Copy link
Contributor

@bolekk bolekk left a comment

Choose a reason for hiding this comment

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

looks reasonable!

return c.underlayingORM.GetUnconfirmedRows(limit, qopts...)
}

func (c CachedORM) clearCache(row *Row) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure if returning an error from this method has any value. If any of the three error cases below happen, we should simply delete the key and continue iterating in the loop.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

makes sense! added the changes 👍🏼

}

func (c CachedORM) DeleteExpired(limit uint, utcNow time.Time, qopts ...pg.QOpt) (int64, error) {
return c.underlayingORM.DeleteExpired(limit, utcNow, qopts...)
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if we should clear the cache here if DeleteExpired removed any entries.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

💡 good idea, I'll flush the cache to start fresh given there is no way of knowing what was deleted

for key := range c.cache.Items() {
keyParts := strings.Split(key, "_")
if len(keyParts) != 3 {
c.lggr.Errorf("invalid cache key: %s", key)
Copy link
Contributor

Choose a reason for hiding this comment

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

Still delete the key on every error? We don't want any invalid keys in the cache anyway.

Copy link
Contributor Author

@agparadiso agparadiso Mar 6, 2024

Choose a reason for hiding this comment

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

got it, I've addressed it on this commit.

I changed it slightly to delete only if the key is a GetSnapshot key and it fails to parse the addresses.
I think this is safer, because if at some point we decide to add a cache layer to the eg the Get(address *ubig.Big, slotId uint, qopts ...pg.QOpt) (*Row, error) this will wrongly delete records and it will be painful to find why.
Worst case scenario if the key is wrong it will die because of the TTL, wdyt?

bolekk
bolekk previously approved these changes Mar 6, 2024
KuphJr
KuphJr previously approved these changes Mar 6, 2024
"strings"
"time"

"github.com/patrickmn/go-cache"
Copy link
Contributor

Choose a reason for hiding this comment

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

This dependency must already exist I suppose since I don't see any changes to the go.mod file

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes! the evmregistry is already using it

)

// CachedORM is a cached orm wrapper that implements the ORM interface.
// It adds a cache layer in order to remove unnecessary preassure to the underlaying implementation
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: spelling of pressure

continue
}

if row.Address.ToInt().Cmp(minAddress) >= 0 && row.Address.ToInt().Cmp(maxAddress) <= 0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

I am trying to understand a case where this would not be true...

Copy link
Contributor

Choose a reason for hiding this comment

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

S4 supports snapshot sharding.

Copy link
Contributor

Choose a reason for hiding this comment

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

Gotcha. I re-read the CLIP and this now makes sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, we want to only delete the cached snapshots that its addressRange contain a specific row. Just to avoid deleting snapshots that are not affected

return cached.([]*SnapshotRow), nil
}

c.lggr.Info("Snapshot not found in cache, fetching it from underlaying implementation")
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: this could probably be debug level

}

if deletedRows > 0 {
c.cache.Flush()
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need to flush the entire cache every time a single row is expired?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

more ctx here but basically its because we know some rows where deleted, but we don't know which ones, so the best effort on keeping the cache sync is to flush it

@agparadiso agparadiso added this pull request to the merge queue Mar 11, 2024
Merged via the queue into develop with commit f077a43 Mar 11, 2024
96 of 97 checks passed
@agparadiso agparadiso deleted the feat/FUN-973_s4_snapshot_caching branch March 11, 2024 12:15
ogtownsend pushed a commit that referenced this pull request Mar 14, 2024
* feat: s4 get snapshot cached

* chore: log and continue in case of error cleaning the cache

* feat: flush cache in case of deleting expired from underlaying orm

* feat: delete invalid keys

* chore: typo + log level
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.

3 participants