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

Existence Invariants #27

Merged
merged 3 commits into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.16
go-version: 1.19.x

- name: Install Staticcheck
run: go install honnef.co/go/tools/cmd/staticcheck@latest
Expand All @@ -33,7 +33,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.16
go-version: 1.19.x

- name: Checkout Code
uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.16
go-version: 1.19.x

- name: Import GPG key
id: import_gpg
Expand Down
3 changes: 1 addition & 2 deletions bench_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package honu_test

import (
"io/ioutil"
"math/rand"
"os"
"testing"
Expand All @@ -21,7 +20,7 @@ var (

func setupLevelDB(t testing.TB) (*leveldb.DB, string) {
// Create a new leveldb database in a temporary directory
tmpDir, err := ioutil.TempDir("", "leveldb-*")
tmpDir, err := os.MkdirTemp("", "leveldb-*")
require.NoError(t, err)

// Open a leveldb database directly without honu wrapper
Expand Down
1 change: 1 addition & 0 deletions engines/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Engine interface {
// Store is a simple key/value interface that allows for Get, Put, and Delete. Nearly
// all engines should support the Store interface.
type Store interface {
Has(key []byte, options *opts.Options) (exists bool, err error)
Get(key []byte, options *opts.Options) (value []byte, err error)
Put(key, value []byte, options *opts.Options) error
Delete(key []byte, options *opts.Options) error
Expand Down
5 changes: 3 additions & 2 deletions engines/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package engine
import "errors"

var (
ErrNotFound = errors.New("not found")
ErrReadOnlyTx = errors.New("cannot execute a write operation in a read only transaction")
ErrNotFound = errors.New("not found")
ErrReadOnlyTx = errors.New("cannot execute a write operation in a read only transaction")
ErrAlreadyExists = errors.New("specified key already exists in the database")
)
29 changes: 29 additions & 0 deletions engines/leveldb/leveldb.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,35 @@ func (tx *Transaction) Finish() error {
return nil
}

// Has returns true if the DB does contains the given key.
func (tx *Transaction) Has(key []byte, options *opts.Options) (bool, error) {
return tx.db.has(key, options)
}

// Has returns true if the DB does contains the given key.
func (db *LevelDBEngine) Has(key []byte, options *opts.Options) (bool, error) {
db.RLock()
defer db.RUnlock()
return db.has(key, options)
}

// Has returns true if the DB does contains the given key.
func (db *LevelDBEngine) has(key []byte, options *opts.Options) (_ bool, err error) {
// Create a default to prevent panics when accessing options.
if options == nil {
if options, err = opts.New(); err != nil {
return false, err
}
}

// Namespaces in leveldb are provided not by buckets but by namespace:: prefixed keys
if options.Namespace != "" {
key = prepend(options.Namespace, key)
}

return db.ldb.Has(key, options.LevelDBRead)
}

// Get the latest version of the object stored by the key. This is the Transaction Get
// method which can be used in either readonly or write modes. This is the preferred
// mechanism to access the underlying engine.
Expand Down
12 changes: 10 additions & 2 deletions engines/leveldb/leveldb_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package leveldb_test

import (
"io/ioutil"
"os"
"testing"

Expand Down Expand Up @@ -38,7 +37,7 @@ var testNamespaces = []string{

// Returns a LevelDBEngine and the path where it was created.
func setupLevelDBEngine(t testing.TB) (_ *leveldb.LevelDBEngine, path string) {
tempDir, err := ioutil.TempDir("", "leveldb-*")
tempDir, err := os.MkdirTemp("", "leveldb-*")
require.NoError(t, err)

conf, _ := config.New()
Expand Down Expand Up @@ -71,6 +70,13 @@ func checkPut(ldbStore engine.Store, opts *options.Options, key []byte, value []
require.NoError(t, err)
}

// Wraps engine.Store.Has with testing checks
func checkHas(ldbStore engine.Store, opts *options.Options, key []byte, assert require.BoolAssertionFunc, t *testing.T) {
exists, err := ldbStore.Has(key, opts)
require.NoError(t, err)
assert(t, exists)
}

// Wraps engine.Store.Get with testing checks.
func checkGet(ldbStore engine.Store, opts *options.Options, key []byte, expectedValue []byte, t *testing.T) {
getValue, err := ldbStore.Get(key, opts)
Expand Down Expand Up @@ -134,7 +140,9 @@ func TestLevelDBTransactions(t *testing.T) {
opts, err := options.New(options.WithNamespace(namespace))
require.NoError(t, err)
value := []byte(namespace)
checkHas(tx, opts, key, require.False, t)
checkPut(tx, opts, key, value, t)
checkHas(tx, opts, key, require.True, t)
checkGet(tx, opts, key, value, t)
checkDelete(tx, opts, key, t)

Expand Down
47 changes: 39 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,14 +1,45 @@
module github.com/rotationalio/honu

go 1.16
go 1.19

require (
github.com/cockroachdb/pebble v0.0.0-20211021161301-9106d5d2238f
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2
github.com/klauspost/compress v1.12.3 // indirect
github.com/stretchr/testify v1.6.1
github.com/cockroachdb/pebble v0.0.0-20230906203007-2129a6e99d0f
github.com/golang/protobuf v1.5.3
github.com/stretchr/testify v1.8.4
github.com/syndtr/goleveldb v1.0.0
google.golang.org/grpc v1.39.0
google.golang.org/protobuf v1.27.1
google.golang.org/grpc v1.58.0
google.golang.org/protobuf v1.31.0
)

require (
github.com/DataDog/zstd v1.5.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cockroachdb/errors v1.11.1 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/redact v1.1.5 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/getsentry/sentry-go v0.24.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/onsi/ginkgo v1.13.0 // indirect
github.com/onsi/gomega v1.10.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/net v0.15.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading
Loading