Skip to content

Commit

Permalink
fix(i): Make badger dependency optional (sourcenetwork#2828)
Browse files Browse the repository at this point in the history
## Relevant issue(s)

Resolves sourcenetwork#2827

## Description

This PR moves some things around to make the badger dependency optional
to allow for JS builds.

## Tasks

- [x] I made sure the code is well commented, particularly
hard-to-understand areas.
- [x] I made sure the repository-held documentation is changed
accordingly.
- [x] I made sure the pull request title adheres to the conventional
commit style (the subset used in the project can be found in
[tools/configs/chglog/config.yml](tools/configs/chglog/config.yml)).
- [x] I made sure to discuss its limitations such as threats to
validity, vulnerability to mistake and misuse, robustness to
invalidation of assumptions, resource requirements, ...

## How has this been tested?

`make test`

Specify the platform(s) on which this was tested:
- MacOS
  • Loading branch information
nasdf authored Jul 15, 2024
1 parent 7f66790 commit bfa791d
Show file tree
Hide file tree
Showing 22 changed files with 281 additions and 126 deletions.
2 changes: 1 addition & 1 deletion cli/server_dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func MakeServerDumpCmd() *cobra.Command {
return errors.New("server-side dump is only supported for the Badger datastore")
}
storeOpts := []node.StoreOpt{
node.WithPath(cfg.GetString("datastore.badger.path")),
node.WithStorePath(cfg.GetString("datastore.badger.path")),
}
rootstore, err := node.NewStore(cmd.Context(), storeOpts...)
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions cli/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ func MakeStartCommand() *cobra.Command {
}

opts := []node.Option{
node.WithPath(cfg.GetString("datastore.badger.path")),
node.WithInMemory(cfg.GetString("datastore.store") == configStoreMemory),
node.WithStorePath(cfg.GetString("datastore.badger.path")),
node.WithBadgerInMemory(cfg.GetString("datastore.store") == configStoreMemory),
node.WithDisableP2P(cfg.GetBool("net.p2pDisabled")),
node.WithACPType(node.LocalACPType),
node.WithPeers(peers...),
Expand Down Expand Up @@ -100,7 +100,7 @@ func MakeStartCommand() *cobra.Command {
if err != nil && !errors.Is(err, keyring.ErrNotFound) {
return err
}
opts = append(opts, node.WithEncryptionKey(encryptionKey))
opts = append(opts, node.WithBadgerEncryptionKey(encryptionKey))
}

n, err := node.NewNode(cmd.Context(), opts...)
Expand Down
8 changes: 2 additions & 6 deletions datastore/badger/v4/datastore.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ import (

var log = logger.Logger("badger")

var (
ErrClosed = errors.New("datastore closed")
ErrTxnConflict = badger.ErrConflict
)

type Datastore struct {
DB *badger.DB

Expand Down Expand Up @@ -767,7 +762,8 @@ func (t *txn) Commit(ctx context.Context) error {
}

func (t *txn) commit() error {
return t.txn.Commit()
err := t.txn.Commit()
return convertError(err)
}

func (t *txn) Discard(ctx context.Context) {
Expand Down
27 changes: 27 additions & 0 deletions datastore/badger/v4/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,39 @@ package badger

import (
dsq "github.com/ipfs/go-datastore/query"
badger "github.com/sourcenetwork/badger/v4"

datastoreErrors "github.com/sourcenetwork/defradb/datastore/errors"
"github.com/sourcenetwork/defradb/errors"
)

var (
ErrClosed = datastoreErrors.ErrClosed
ErrTxnConflict = datastoreErrors.ErrTxnConflict
)

const errOrderType string = "invalid order type"

func ErrOrderType(orderType dsq.Order) error {
return errors.New(errOrderType, errors.NewKV("Order type", orderType))
}

// convertError converts badger specific errors into datastore errors.
func convertError(err error) error {
// The errors we are matching against are never wrapped.
//
//nolint:errorlint
switch err {
case badger.ErrConflict:
return datastoreErrors.ErrTxnConflict

case badger.ErrReadOnlyTxn:
return datastoreErrors.ErrReadOnlyTxn

case badger.ErrDiscardedTxn:
return datastoreErrors.ErrTxnDiscarded

default:
return err
}
}
4 changes: 2 additions & 2 deletions datastore/blockstore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func TestBStoreGetWithStoreClosed(t *testing.T) {
require.NoError(t, err)

_, err = bs.Get(ctx, cID)
require.ErrorIs(t, err, memory.ErrClosed)
require.ErrorIs(t, err, ErrClosed)
}

func TestBStoreGetWithReHash(t *testing.T) {
Expand Down Expand Up @@ -190,5 +190,5 @@ func TestPutManyWithStoreClosed(t *testing.T) {
require.NoError(t, err)

err = bs.PutMany(ctx, []blocks.Block{b, b2})
require.ErrorIs(t, err, memory.ErrClosed)
require.ErrorIs(t, err, ErrClosed)
}
4 changes: 2 additions & 2 deletions datastore/concurrent_txt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func TestNewConcurrentTxnFromWithStoreClosed(t *testing.T) {
require.NoError(t, err)

_, err = NewConcurrentTxnFrom(ctx, rootstore, 0, false)
require.ErrorIs(t, err, badgerds.ErrClosed)
require.ErrorIs(t, err, ErrClosed)
}

func TestNewConcurrentTxnFromNonIterable(t *testing.T) {
Expand All @@ -67,7 +67,7 @@ func TestNewConcurrentTxnFromNonIterableWithStoreClosed(t *testing.T) {
require.NoError(t, err)

_, err = NewConcurrentTxnFrom(ctx, rootstore, 0, false)
require.ErrorIs(t, err, badgerds.ErrClosed)
require.ErrorIs(t, err, ErrClosed)
}

func TestConcurrentTxnSync(t *testing.T) {
Expand Down
5 changes: 4 additions & 1 deletion datastore/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package datastore

import (
datastoreErrors "github.com/sourcenetwork/defradb/datastore/errors"
"github.com/sourcenetwork/defradb/errors"
)

Expand All @@ -28,7 +29,9 @@ var (
// defradb/store.ErrNotFound => error
// ipfs-blockstore.ErrNotFound => error
// ErrNotFound is an error returned when a block is not found.
ErrNotFound = errors.New("blockstore: block not found")
ErrNotFound = errors.New("blockstore: block not found")
ErrClosed = datastoreErrors.ErrClosed
ErrTxnConflict = datastoreErrors.ErrTxnConflict
)

// NewErrInvalidStoredValue returns a new error indicating that the stored
Expand Down
24 changes: 24 additions & 0 deletions datastore/errors/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2024 Democratized Data Foundation
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package errors

import "errors"

var (
ErrClosed = errors.New("datastore closed")
// ErrConflict is returned when a transaction conflicts with another transaction. This can
// happen if the read rows had been updated concurrently by another transaction.
ErrTxnConflict = errors.New("transaction Conflict. Please retry")
// ErrDiscardedTxn is returned if a previously discarded transaction is re-used.
ErrTxnDiscarded = errors.New("this transaction has been discarded. Create a new one")
// ErrReadOnlyTxn is returned if an update function is called on a read-only transaction.
ErrReadOnlyTxn = errors.New("no sets or deletes are allowed in a read-only transaction")
)
13 changes: 7 additions & 6 deletions datastore/memory/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@

package memory

import "github.com/sourcenetwork/defradb/errors"
import (
"github.com/sourcenetwork/defradb/datastore/errors"
)

var (
ErrReadOnlyTxn = errors.New("read only transaction")
ErrTxnDiscarded = errors.New("transaction discarded")
//nolint:revive
ErrTxnConflict = errors.New("Transaction Conflict. Please retry")
ErrClosed = errors.New("datastore closed")
ErrReadOnlyTxn = errors.ErrReadOnlyTxn
ErrTxnDiscarded = errors.ErrTxnDiscarded
ErrTxnConflict = errors.ErrTxnConflict
ErrClosed = errors.ErrClosed
)
18 changes: 9 additions & 9 deletions datastore/txn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func TestNewTxnFromWithStoreClosed(t *testing.T) {
require.NoError(t, err)

_, err = NewTxnFrom(ctx, rootstore, 0, false)
require.ErrorIs(t, err, badgerds.ErrClosed)
require.ErrorIs(t, err, ErrClosed)
}

func TestOnSuccess(t *testing.T) {
Expand Down Expand Up @@ -107,7 +107,7 @@ func TestOnError(t *testing.T) {
require.NoError(t, err)

err = txn.Commit(ctx)
require.ErrorIs(t, err, badgerds.ErrClosed)
require.ErrorIs(t, err, ErrClosed)

require.Equal(t, text, "Source Inc")
}
Expand All @@ -131,7 +131,7 @@ func TestOnErrorAsync(t *testing.T) {

wg.Add(1)
err = txn.Commit(ctx)
require.ErrorIs(t, err, badgerds.ErrClosed)
require.ErrorIs(t, err, ErrClosed)
wg.Wait()
}

Expand Down Expand Up @@ -252,7 +252,7 @@ func TestMemoryStoreTxn_TwoTransactionsWithGetPutConflict_ShouldErrorWithConflic
require.NoError(t, err)

err = txn1.Commit(ctx)
require.ErrorIs(t, err, badger.ErrConflict)
require.ErrorIs(t, err, ErrTxnConflict)
}

func TestMemoryStoreTxn_TwoTransactionsWithHasPutConflict_ShouldErrorWithConflict(t *testing.T) {
Expand Down Expand Up @@ -281,7 +281,7 @@ func TestMemoryStoreTxn_TwoTransactionsWithHasPutConflict_ShouldErrorWithConflic
require.NoError(t, err)

err = txn1.Commit(ctx)
require.ErrorIs(t, err, badger.ErrConflict)
require.ErrorIs(t, err, ErrTxnConflict)
}

func TestBadgerMemoryStoreTxn_TwoTransactionsWithPutConflict_ShouldSucceed(t *testing.T) {
Expand Down Expand Up @@ -338,7 +338,7 @@ func TestBadgerMemoryStoreTxn_TwoTransactionsWithGetPutConflict_ShouldErrorWithC
require.NoError(t, err)

err = txn1.Commit(ctx)
require.ErrorIs(t, err, badger.ErrConflict)
require.ErrorIs(t, err, ErrTxnConflict)
}

func TestBadgerMemoryStoreTxn_TwoTransactionsWithHasPutConflict_ShouldErrorWithConflict(t *testing.T) {
Expand Down Expand Up @@ -369,7 +369,7 @@ func TestBadgerMemoryStoreTxn_TwoTransactionsWithHasPutConflict_ShouldErrorWithC
require.NoError(t, err)

err = txn1.Commit(ctx)
require.ErrorIs(t, err, badger.ErrConflict)
require.ErrorIs(t, err, ErrTxnConflict)
}

func TestBadgerFileStoreTxn_TwoTransactionsWithPutConflict_ShouldSucceed(t *testing.T) {
Expand Down Expand Up @@ -426,7 +426,7 @@ func TestBadgerFileStoreTxn_TwoTransactionsWithGetPutConflict_ShouldErrorWithCon
require.NoError(t, err)

err = txn1.Commit(ctx)
require.ErrorIs(t, err, badger.ErrConflict)
require.ErrorIs(t, err, ErrTxnConflict)
}

func TestBadgerFileStoreTxn_TwoTransactionsWithHasPutConflict_ShouldErrorWithConflict(t *testing.T) {
Expand Down Expand Up @@ -457,7 +457,7 @@ func TestBadgerFileStoreTxn_TwoTransactionsWithHasPutConflict_ShouldErrorWithCon
require.NoError(t, err)

err = txn1.Commit(ctx)
require.ErrorIs(t, err, badger.ErrConflict)
require.ErrorIs(t, err, ErrTxnConflict)
}

func TestMemoryStoreTxn_TwoTransactionsWithQueryAndPut_ShouldOmmitNewPut(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions datastore/wrappedstore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func TestQueryWithStoreClosed(t *testing.T) {
require.NoError(t, err)

_, err = dsRW.Query(ctx, query.Query{})
require.ErrorIs(t, err, badgerds.ErrClosed)
require.ErrorIs(t, err, ErrClosed)
}

func TestIteratePrefix(t *testing.T) {
Expand Down Expand Up @@ -118,5 +118,5 @@ func TestIteratePrefixWithStoreClosed(t *testing.T) {
require.NoError(t, err)

_, err = iter.IteratePrefix(ctx, ds.NewKey("key1"), ds.NewKey("key1"))
require.ErrorIs(t, err, badgerds.ErrClosed)
require.ErrorIs(t, err, ErrClosed)
}
6 changes: 3 additions & 3 deletions http/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
"net/http"

"github.com/sourcenetwork/defradb/client"
"github.com/sourcenetwork/defradb/datastore/badger/v4"
"github.com/sourcenetwork/defradb/datastore"
)

func requestJSON(req *http.Request, out any) error {
Expand All @@ -44,8 +44,8 @@ func parseError(msg any) error {
switch msg {
case client.ErrDocumentNotFoundOrNotAuthorized.Error():
return client.ErrDocumentNotFoundOrNotAuthorized
case badger.ErrTxnConflict.Error():
return badger.ErrTxnConflict
case datastore.ErrTxnConflict.Error():
return datastore.ErrTxnConflict
default:
return fmt.Errorf("%s", msg)
}
Expand Down
4 changes: 2 additions & 2 deletions internal/db/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (

"github.com/sourcenetwork/corelog"

"github.com/sourcenetwork/defradb/datastore/badger/v4"
"github.com/sourcenetwork/defradb/datastore"
"github.com/sourcenetwork/defradb/errors"
"github.com/sourcenetwork/defradb/event"
)
Expand Down Expand Up @@ -48,7 +48,7 @@ func (db *db) handleMessages(ctx context.Context, sub *event.Subscription) {
var err error
for i := 0; i < db.MaxTxnRetries(); i++ {
err = db.executeMerge(ctx, evt)
if errors.Is(err, badger.ErrTxnConflict) {
if errors.Is(err, datastore.ErrTxnConflict) {
continue // retry merge
}
break // merge success or error
Expand Down
10 changes: 9 additions & 1 deletion node/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,18 @@ import (

const (
errLensRuntimeNotSupported string = "the selected lens runtime is not supported by this build"
errStoreTypeNotSupported string = "the selected store type is not supported by this build"
)

var ErrLensRuntimeNotSupported = errors.New(errLensRuntimeNotSupported)
var (
ErrLensRuntimeNotSupported = errors.New(errLensRuntimeNotSupported)
ErrStoreTypeNotSupported = errors.New(errStoreTypeNotSupported)
)

func NewErrLensRuntimeNotSupported(lens LensRuntimeType) error {
return errors.New(errLensRuntimeNotSupported, errors.NewKV("Lens", lens))
}

func NewErrStoreTypeNotSupported(store StoreType) error {
return errors.New(errStoreTypeNotSupported, errors.NewKV("Store", store))
}
Loading

0 comments on commit bfa791d

Please sign in to comment.