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

TTL + table store #811

Merged
merged 21 commits into from
Oct 30, 2024
Merged

Conversation

cody-littley
Copy link
Contributor

@cody-littley cody-littley commented Oct 16, 2024

Why are these changes needed?

This PR unifies the concepts of a "table store" and a "ttl store". Table stores now support TTLs, and there is no stand alone ttl store.

Checks

  • I've made sure the lint is passing in this PR.
  • I've made sure the tests are passing. Note that there might be a few flaky tests, in that case, please comment that they are not relevant.
  • I've checked the new test coverage and the coverage percentage didn't drop.
  • Testing Strategy
    • Unit tests
    • Integration tests
    • This PR is not tested :(

Signed-off-by: Cody Littley <[email protected]>
Signed-off-by: Cody Littley <[email protected]>
Signed-off-by: Cody Littley <[email protected]>
Signed-off-by: Cody Littley <[email protected]>
Signed-off-by: Cody Littley <[email protected]>
@@ -5,14 +5,17 @@ import (
"github.com/Layr-Labs/eigenda/common/kvstore"
"github.com/syndtr/goleveldb/leveldb/iterator"
"github.com/syndtr/goleveldb/leveldb/util"
"time"
)

var _ kvstore.Table = &tableView{}

// tableView allows data in a table to be accessed as if it were a Store.
Copy link
Contributor

Choose a reason for hiding this comment

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

Table view tries to appear like a store, by wrapping two stores...these are getting too complicated and won't be simple to use.

Copy link
Contributor Author

@cody-littley cody-littley Oct 17, 2024

Choose a reason for hiding this comment

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

This isn't actually wrapping two stores, this class has access to two different interfaces on the same store. This constructor isn't publicly exported, so it's impossible for an end user to instantiate this class with two different stores.

That being said, in order to simplify this method, I've modified the function signature to make things easier to read.

The reason why this class needed access to the parent TableStore class was for the methods Shutdown(), Destroy(), and NewBatch(). Instead of passing in the whole TableStore, we can just pass in lambdas for the functionality needed by the table view.

func newTableView(
	base kvstore.Store,
	name string,
	prefix uint32,
	shutdown func() error,
	destroy func() error,
	batchBuilder func() kvstore.TableStoreBatch) kvstore.Table {

Copy link
Contributor

Choose a reason for hiding this comment

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

The specific issue here is that tableView doesn't appear to be Store, it's trying to be a Table (e.g. the TTL related interfaces do not exist for Store)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The interface Table currently extends the interface Store. A user can interact with a table as if it were a regular Store object.

type Table interface {
	Store

	Name() string
	TableKey(key []byte) TableKey
	PutWithTTL(key []byte, value []byte, ttl time.Duration) error
	PutWithExpiration(key []byte, value []byte, expiryTime time.Time) error
	NewTTLBatch() TTLStoreBatch
}

// parallel or to modify a batch while the store is being modified, it is not thread safe to concurrently
// modify the same batch.
type TTLStoreBatch TTLBatch[[]byte]

Copy link
Contributor

Choose a reason for hiding this comment

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

since you are trying to merge ttl into tablestore, can these be deleted?

Copy link
Contributor Author

@cody-littley cody-littley Oct 17, 2024

Choose a reason for hiding this comment

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

Done. I've merged the TTLStore interface into the Table interface.

Signed-off-by: Cody Littley <[email protected]>
@cody-littley cody-littley changed the title Ttl table store TTL + table store Oct 17, 2024
Signed-off-by: Cody Littley <[email protected]>
@@ -375,22 +371,46 @@ func loadNamespaceTable(namespaceTable kvstore.Table) (map[uint32]string, error)
return tableIDMap, nil
}

// CreateTable creates a new table with the given name. If a table with the given name already exists,
// this method becomes a no-op. Returns ErrTableLimitExceeded if the maximum number of tables has been reached.
// CreateTable creates a new table with the given name.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: createTable

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

// time-to-live (TTL) or expiration times. Although it is thread safe to modify different batches in
// parallel or to modify a batch while the store is being modified, it is not thread safe to concurrently
// modify the same batch.
type TTLBatch[K any] interface {
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks this is not needed?

  • if it's a Table, there is TableBatch, operating on the raw keys
  • if it's a TableStore, there is TableStoreBatch, operating on the namespaced keys

And the ttl related interfaces are always there.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The batch APIs have now been simplified so that they don't have generics. Are there additional simplifications you'd like to see?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note that we still need two batch interfaces if we want to support batches that can set different TTLs for operations within the same batch. The core reason is that the basic Store API does not have a concept of a TTL, meaning we need a batch interface that doesn't have TTLs.

@@ -5,14 +5,17 @@ import (
"github.com/Layr-Labs/eigenda/common/kvstore"
"github.com/syndtr/goleveldb/leveldb/iterator"
"github.com/syndtr/goleveldb/leveldb/util"
"time"
)

var _ kvstore.Table = &tableView{}

// tableView allows data in a table to be accessed as if it were a Store.
Copy link
Contributor

Choose a reason for hiding this comment

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

The specific issue here is that tableView doesn't appear to be Store, it's trying to be a Table (e.g. the TTL related interfaces do not exist for Store)

base kvstore.Store
// name is the name of the table.
name string
// prefix is the prefix for all keys in the table.
prefix uint32
// shutdown is a function that shuts down the table store.
Copy link
Contributor

Choose a reason for hiding this comment

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

Why the following 3 interfaces make sense to be here? They are all operating as the TableStore, not Table

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The core problem is that Table implements Store, which means it needs to implement methods like Shutdown(). If you'd like to change this, I can think of the following options:

  • make methods like Shutdown() into no-ops
  • make methods like Shutdown() return an error
  • split the Store interface into several interfaces:
    • the interface called Store will just have the methods Get(), Put(), Delete(), etc.
    • There will be an interface called DBStore (or similar) that implements Store and adds methods such as Shutdown()
    • Things such as LevelDBStore will implement DBStore, while Table will only implement Store. Table will no longer have odd methods such as Shutdown().
  • Replace Tables with key builders (I don't think you like this option, mentioning it for completeness 😜)

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 open to either option if it makes sense. I think the "weirdness" in APIs may indicate we could structure them better (like the case here). Do you prefer using key builder? Option 3 seems complicated to me.

Signed-off-by: Cody Littley <[email protected]>
Signed-off-by: Cody Littley <[email protected]>
Signed-off-by: Cody Littley <[email protected]>
Signed-off-by: Cody Littley <[email protected]>
Signed-off-by: Cody Littley <[email protected]>
Signed-off-by: Cody Littley <[email protected]>
Signed-off-by: Cody Littley <[email protected]>
Signed-off-by: Cody Littley <[email protected]>
Copy link
Contributor

@jianoaix jianoaix left a comment

Choose a reason for hiding this comment

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

lgtm mostly


// Key represents a key in a TableStore. Each key is scoped to a specific table.
type Key interface {
// AsString interprets the key as a string and returns it.
Copy link
Contributor

Choose a reason for hiding this comment

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

These are a lot of types, can we start with what we know we need?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've removed all of the methods except for the ones that deal with bytes. The other methods were not strictly necessary, just syntactic sugar.

Signed-off-by: Cody Littley <[email protected]>
@cody-littley cody-littley merged commit 410419a into Layr-Labs:master Oct 30, 2024
6 checks passed
@cody-littley cody-littley deleted the ttl-table-store branch October 30, 2024 16:40
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.

2 participants